В F35 там же не только поворотное сопло двигателя работает. Ещё есть схема отбора мощности двигателя для второго вертикального потока воздуха сразу за кабиной пилота. Такого раньше ни у кого не было. В целом инженерное решение F35 для вертикального взлёта/посадки это технический шедевр.
Когда-то пришлось поработать с СОМ-технологией и СОМ компонентами. Как на меня это полный ужас. Её создали очень сложные люди, которые не стремились к простоте и красоте того, что они делают.
Статья очень информативна в том плане, что детально разбирается архитектура реально работающего проекта. Но то каким образом представлена схема архитектуры на схеме модуля вызывает много вопросов.
Один модуль вызывает менеджер другого
Из схемы модуля видно что при обращении к модулю идёт вызов к Anti-Corruption Layer, а не к менеджеру модуля.
затем в принимающем модуле, внешнее DTO преобразуется во внутреннее, из доменного слоя
Внутреннее DTO наверное надо назвать доменным объектом.
Архитектуру приведенную на схеме модуля скорее можно назвать многослойной архитектурой, адаптированной для взаимодействия между модулями одного приложения. Обычно многослойная архитектура описывает взаимодействие приложения с другими приложениями.
На схеме модуля на мой взгляд не указаны или перепутаны порядок использования слоёв и направления взаимодействия между слоями.
Anti-Corruption Layer скорее всего это и есть слой Presentation через который идёт вызов к функционалу модуля и при вызове ему передаётся объект dto. Если в Presentation используется cron, то вызов проходит без передачи объекта dto.
На схеме не показано откуда идёт вызов к Application. Можно предположит, что вызов идёт от Anti-Corruption Layer.
Непонятно что именно понимается под блоком Components и где находится блок доменной логики?
Для наглядности архитектуру удобно разделить на 2 части - схема взаимодействия между слоями/функциональными блоками модуля и схема переноса данных между моделями данных модуля. Сейчас на схеме вызовы идут и через функциональные блоки и через модели данных.
Если мы говорим о Stateless-приложениях, а обычно веб-приложения являются такими, то ORM объектов, которые извлекли на предыдущем шаге юз кейса (например извлечение данных из бд, которые на следующем шаге надо изменить и записать в бд) уже не существует. И объект persistence model надо создавать с нуля с помощью данных соответствующего доменного объекта.
В общем случае говорят о разделении доменной модели и persistence model. ORM и change tracking работают как раз с persistence model. Если в юз кейсе предполагается изменение данных в объектах доменной модели, то функционал юз кейса должен обеспечить копирование данных из изменённых доменных объектов в соответствующие объекты persistence model и далее сохранить их в бд. В подобном алгоритме уже не имеет значения используется ORM или нет.
В последнем примере статьи для извлечения данных используется Query объект HotelSearchQuery. Поэтому для изменения данных логично использовать объект типа Command. Использование связки объектов Query / Command для работы с данными в бд детально описано в технологии CQRS.
Command не может быть классом-наследником репозитория. Command и репозиторий находятся в разных слоях приложения. Command использует функционал репозитория для изменения данных в бд.
В последних примерах кода в статье автор смешивает между собой понятия репозитория и объектов типа Query / Command. Репозиторий IRepository<T> таким и должен быть, как описан в начале статьи. Использую генерик-тип Т его можно конкретизировать для нужного типа сущности - например BookingRepository. Но Command объект это не будет наследник IBookingRepository. Это будет объект BookingCommand, использующий репозиторий BookingRepository.
Репозиторий можно рассматривать как прослойку/API между вышележащим функционалом бизнес-логики и нижележащими механизмами работы с конкретным типом базы данных.
В общем случае вместо использования терминов DAO / Repository надо говорить про фасад слоя persistence layer через который UseCase работает с базой данных. Этот фасад можно назвать DAO или Repository. Хотя по теории сами паттерны DAO и Repository отличаются друг от друга. В самом простейшем случае DAO / Repository можно вообще отбросить и UseCase будет напрямую работать с ORM. Но таком случае вместо архитектуры получится каша из кода.
Вначале автор пишет, что доменный объект собирается при помощи Repository. Но далее
5. Каждый из методов DAO работает с ORM и получает объект, который возвращается в класс UseCase
6. UseCase из трех объектов собирает один DTO, возвращает этот DTO "наверх" в функцию для маршрута
Мне тоже всегда казалось странном постоянное упоминание про Repository в книгах по DDD. Объект UseCase сам может собрать агрегат домена и использование для этого Repository совершенно излишнее усложнение кода.
UseCase работает с DAO объектами. DAO объекты работают с данными в бд при помощи ORM или при помощи функционала прямых sql запросов.
Слой приложения обращается к DAO объектам слоя persistence layer. JPA интерфейсы лежат ниже DAO объектов. DAO объекты обращаются к базе данных, используя JPA интерфейсы.
PageQuery, PageResult и SortRequest живут в слое приложения.
Слой приложения - это набор use case, которые ничего о пагинации не должны знать. В этом основная проблема. Если рассмотреть простейшую архитектуру приложения с визуальным интерфейсом presentation layer -> use case -> persistence layer, то для presentation layer и persistence layer нужны данные пагинации и их надо пробрасывать из presentation layer в persistence layer. Но в этой схеме промежуточное звено use case заточено на бизнес-логику и ничего вообще не должно знать о пагинации. Поэтому приходится идти на не совсем правильные решения и пробрасывать пагинацию через use case.
Если F-35 это смесь Як-141 с Хариером, то лучше позорьтесь в комментариях. Сравнивать F-35 с Як-141 всё равно, что сравнить корабль SpaceX с кораблём Восток.
Поддержка транзакции на уровне юзкейсов - это типовой подход в многослойной архитектуре.
Очень напоминает гонения на генетику в советские времена.
В F35 там же не только поворотное сопло двигателя работает. Ещё есть схема отбора мощности двигателя для второго вертикального потока воздуха сразу за кабиной пилота. Такого раньше ни у кого не было. В целом инженерное решение F35 для вертикального взлёта/посадки это технический шедевр.
Когда-то пришлось поработать с СОМ-технологией и СОМ компонентами. Как на меня это полный ужас. Её создали очень сложные люди, которые не стремились к простоте и красоте того, что они делают.
Может есть смысл от обсуждения монолит vs микросервис, перейти к обсуждению вопроса компонент vs микросервис ?
Агрегат зависящий от набора флагов - это полный ужас.
Статья очень информативна в том плане, что детально разбирается архитектура реально работающего проекта. Но то каким образом представлена схема архитектуры на схеме модуля вызывает много вопросов.
Из схемы модуля видно что при обращении к модулю идёт вызов к Anti-Corruption Layer, а не к менеджеру модуля.
Внутреннее DTO наверное надо назвать доменным объектом.
Архитектуру приведенную на схеме модуля скорее можно назвать многослойной архитектурой, адаптированной для взаимодействия между модулями одного приложения. Обычно многослойная архитектура описывает взаимодействие приложения с другими приложениями.
На схеме модуля на мой взгляд не указаны или перепутаны порядок использования слоёв и направления взаимодействия между слоями.
Anti-Corruption Layer скорее всего это и есть слой Presentation через который идёт вызов к функционалу модуля и при вызове ему передаётся объект dto. Если в Presentation используется cron, то вызов проходит без передачи объекта dto.
На схеме не показано откуда идёт вызов к Application. Можно предположит, что вызов идёт от Anti-Corruption Layer.
Непонятно что именно понимается под блоком Components и где находится блок доменной логики?
Для наглядности архитектуру удобно разделить на 2 части - схема взаимодействия между слоями/функциональными блоками модуля и схема переноса данных между моделями данных модуля. Сейчас на схеме вызовы идут и через функциональные блоки и через модели данных.
Если мы говорим о Stateless-приложениях, а обычно веб-приложения являются такими, то ORM объектов, которые извлекли на предыдущем шаге юз кейса (например извлечение данных из бд, которые на следующем шаге надо изменить и записать в бд) уже не существует. И объект persistence model надо создавать с нуля с помощью данных соответствующего доменного объекта.
В общем случае говорят о разделении доменной модели и persistence model. ORM и change tracking работают как раз с persistence model. Если в юз кейсе предполагается изменение данных в объектах доменной модели, то функционал юз кейса должен обеспечить копирование данных из изменённых доменных объектов в соответствующие объекты persistence model и далее сохранить их в бд. В подобном алгоритме уже не имеет значения используется ORM или нет.
В последнем примере статьи для извлечения данных используется Query объект HotelSearchQuery. Поэтому для изменения данных логично использовать объект типа Command. Использование связки объектов Query / Command для работы с данными в бд детально описано в технологии CQRS.
Command не может быть классом-наследником репозитория. Command и репозиторий находятся в разных слоях приложения. Command использует функционал репозитория для изменения данных в бд.
В последних примерах кода в статье автор смешивает между собой понятия репозитория и объектов типа Query / Command. Репозиторий
IRepository<T>таким и должен быть, как описан в начале статьи. Использую генерик-тип Т его можно конкретизировать для нужного типа сущности - например BookingRepository. Но Command объект это не будет наследник IBookingRepository. Это будет объект BookingCommand, использующий репозиторий BookingRepository.Репозиторий можно рассматривать как прослойку/API между вышележащим функционалом бизнес-логики и нижележащими механизмами работы с конкретным типом базы данных.
В общем случае вместо использования терминов DAO / Repository надо говорить про фасад слоя persistence layer через который UseCase работает с базой данных. Этот фасад можно назвать DAO или Repository. Хотя по теории сами паттерны DAO и Repository отличаются друг от друга. В самом простейшем случае DAO / Repository можно вообще отбросить и UseCase будет напрямую работать с ORM. Но таком случае вместо архитектуры получится каша из кода.
Вначале автор пишет, что доменный объект собирается при помощи Repository. Но далее
Мне тоже всегда казалось странном постоянное упоминание про Repository в книгах по DDD. Объект UseCase сам может собрать агрегат домена и использование для этого Repository совершенно излишнее усложнение кода.
UseCase работает с DAO объектами. DAO объекты работают с данными в бд при помощи ORM или при помощи функционала прямых sql запросов.
Слой приложения обращается к DAO объектам слоя persistence layer. JPA интерфейсы лежат ниже DAO объектов. DAO объекты обращаются к базе данных, используя JPA интерфейсы.
Мои публикации в хабре.
Для многослойной архитектуры пока не вижу как можно пагинацию логично в неё включить.
Слой приложения - это набор use case, которые ничего о пагинации не должны знать. В этом основная проблема. Если рассмотреть простейшую архитектуру приложения с визуальным интерфейсом presentation layer -> use case -> persistence layer, то для presentation layer и persistence layer нужны данные пагинации и их надо пробрасывать из presentation layer в persistence layer. Но в этой схеме промежуточное звено use case заточено на бизнес-логику и ничего вообще не должно знать о пагинации. Поэтому приходится идти на не совсем правильные решения и пробрасывать пагинацию через use case.
Если F-35 это смесь Як-141 с Хариером, то лучше позорьтесь в комментариях. Сравнивать F-35 с Як-141 всё равно, что сравнить корабль SpaceX с кораблём Восток.
Это точно не про миграцию. Мне нравятся типовые механизмы, которые предоставляет JPA. Но так как JPA в шарпе нет, то использую то что есть в EF.