Как стать автором
Обновить

Code Interface Driven Design

Время на прочтение3 мин
Количество просмотров1.4K
Работая над уменьшением связанности и размышляя о SOA пришел к идее построения типов путем композиции интерфейсов.

В классическом DDD нужно выделить домен – совокупность объектов и их связей. Но когда я применял этот принцип в жизни, встретился с двумя трудностями:

  1. Если есть большой домен и кучка сервисов вокруг него, то становится сложным управление доступом к членам класса. Выглядит это так: есть объект User со свойством CreatedAt, которое я хочу разрешить редактировать только сервису MembershipService. Чтож, пишем InternalsVisibleTo с указанием MembershipService. Дальше нам нужно сделать объект, например Car, у которого есть свойство PassedDistance, которое я хочу открыть только для CarService. Опять повторяем манипуляции с InternalsVisibleTo, но тут появляется проблема: теперь Membersip может изменять километраж автомобиля, а CarService – дату регистрации пользователя.
  2. DDD всё еще не дает возможности строить приложение «по кирпичикам» – просто подключая нужные модули. Говорят, что в Ruby можно, поэтому хочется такой же легкости в .Net =). А не получается всё по той же причине – домен выделен в отдельную сборку, и, подключая сервис, приходится вручную тянуть из домена все зависимые сущности, перебирая их свойства, т.к. большинство из них в новом проекте не понадобятся. Т.е. проблему связанности сервисов DDD решает, а вот связанность домена всё еще не решена.


Выход один – объединить сервис и его сущности в один модуль. Будут это две сборки ( домен и сервис) или одна единая сборка – не важно. Цель – подключить всю функциональность модуля просто добавив reference к сборке, в которой выполняется композиция приложения (AppCore, например).

Сделав это, нужно как-то оставить возможность коммуникации между доменами разных модулей. Вполне вероятно, в нашем примере нужно будет реализовать свойство Car.Owner типа User, а потом House.Owner, CableTv.User и т.д. Добавить reference на Membership – не вариант, это уже противоречит главной идее – не допускать связанности модулей.

Идеи о решении


Выделить все такие зависимости в сборку, но уже не с целыми сущностями, а с интерфейсами-пустышками. В данном примере это будет пустой интерфейс IUser. Потом, при инициализации каждого модуля (в его Bootstrapper-е) расширить этот интерфейс тем, что указан внутри модуля (ICarOwner), в котором можно указать какие-то свойства, которые требуются для User в рамках этого модуля.

Таким образом каждый модуль дополняет интерфейс IUser своими полями. Потом нужно реализовать фабрику, которая на основе перечня интерфейсов будет создавать единый тип User, который будет закэширован в AppCore.

Плюсы и минусы:


+ Каждый модуль знает только только о тех полях, которые ему нужны

+ За исключением базовых интерфейсов модули будут абсолютно независимы.

+ При добавлении нового модуля необходимые для персистенции свойства добавятся автоматически. Т.е. при добавлении модуля Sql-схема автоматически пополнится нужными таблицами, колонками и другими объектами.

— Идея еще не реализована =). Но для того, кто захочет реализовать этот подход, это будет плюсом – он первым воплотит её в жизнь.

Цель – сделать функциональность Plug&Play.

Нужны Orders – добавил reference на OrdersLib, запустил, всё!
БД автоматически пополняется новыми таблицами, колонками, связями, которые требуются для работы OrdersLib. У Пользователя автоматически появится User.Orders и т.д.

Никаких работ по адаптации кода, только расширение там, где необходимо.

Как разобраться из чего же состоит объект Пользователь? Есть два варианта:
  1. кодогенерация общего интерфейса, что даже упростит создание фабрики
  2. разработкой в среде разрабатываемого приложения. Intellisense будет считывать не байт-код, а реальный инстанс динамичного объекта.

Первый путь сохранит строгую типизацию, второй – сделает разработку полностью динамичной.
Теги:
Хабы:
Всего голосов 18: ↑12 и ↓6+6
Комментарии56

Публикации

Истории

Работа

.NET разработчик
60 вакансий

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
11 сентября
Митап по BigData от Честного ЗНАКа
Санкт-ПетербургОнлайн
14 сентября
Конференция Practical ML Conf
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн