Контроллер, сервисы и DTO.
От: Sharov Россия  
Дата: 30.04.20 14:14
Оценка:
Здравствуйте.

Наверняка обсуждалось тут, но что-то не могу припомнить когда...
Итак, имеем сл. картинку -- тыц.
1)Правильно ли я понимаю, что слой controller'ов взаимодействие с *Service? Скорее всего это так.
2)Далее, а вот контроллер в кач-ве параметров в тот или иной *service должен передавать DTO или бизнес сущность? И соотв. получать от *Service должен уже DTO или сущность? Или он просто DTO прокидывает и возвращает тоже DTO? Т.е. в задачи контроллера входить отображения DTO в бизнес сущности или нет? Судя по картинке,
DTO и AppService в одном слое, поэтому AppService должен что-то знать о DTO?

Заранее благодарю.
Кодом людям нужно помогать!
Отредактировано 30.04.2020 14:14 Sharov . Предыдущая версия .
Re: Контроллер, сервисы и DTO.
От: Буравчик Россия  
Дата: 30.04.20 17:10
Оценка: 10 (1)
Здравствуйте, Sharov, Вы писали:

S>1)Правильно ли я понимаю, что слой controller'ов взаимодействие с *Service? Скорее всего это так.


Да

S>2)Далее, а вот контроллер в кач-ве параметров в тот или иной *service должен передавать DTO или бизнес сущность? И соотв. получать от *Service должен уже DTO или сущность? Или он просто DTO прокидывает и возвращает тоже DTO? Т.е. в задачи контроллера входить отображения DTO в бизнес сущности или нет?


Да, в задачи контроллера входит преобразование из DTO в сущности и наоборот. Это его основная и единственная задача.
Принимает DTO, преобразовывает в сущности, вызывает сервисы, получает от них сущности, отдает DTO.

S>Судя по картинке, DTO и AppService в одном слое, поэтому AppService должен что-то знать о DTO?


Нет, не должны. AppService является фасадом приложения, делает всю полезную работу, оперирует бизнес-сущностями, а не DTO.
Best regards, Буравчик
Re[2]: Контроллер, сервисы и DTO.
От: Sharov Россия  
Дата: 30.04.20 17:49
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Нет, не должны. AppService является фасадом приложения, делает всю полезную работу, оперирует бизнес-сущностями, а не DTO.


Благодарю, еще вдогонку вопрос: а это нормально, если у меня AppService зависит от нескольких репозиториев. SRP не нарушается. Или по DDD -- 1 к 1?
Кодом людям нужно помогать!
Re[3]: Контроллер, сервисы и DTO.
От: Буравчик Россия  
Дата: 30.04.20 18:07
Оценка: 5 (1)
Здравствуйте, Sharov, Вы писали:

S>Благодарю, еще вдогонку вопрос: а это нормально, если у меня AppService зависит от нескольких репозиториев. SRP не нарушается. Или по DDD -- 1 к 1?


Если несколько зависимостей (репозиториев), то нормально.
Если слишком много — то вероятно SRP нарушается, класс делает слишком много.
Если 1:1 — то может нормально, но может абстракции (интерфейсы) неправильно выбраны, и часть кода должно уйти из сервиса в репозиторий.
Best regards, Буравчик
Re: Контроллер, сервисы и DTO.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.04.20 18:14
Оценка: 1 (1)
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте.


S>Наверняка обсуждалось тут, но что-то не могу припомнить когда...

Такое тут всегда обсуждается.

S>Итак, имеем сл. картинку -- тыц.

Так себе картинка

S>1)Правильно ли я понимаю, что слой controller'ов взаимодействие с *Service? Скорее всего это так.

Да. Верхние слои вызывают нижние слои. Не наоборот.

S>2)Далее, а вот контроллер в кач-ве параметров в тот или иной *service должен передавать DTO или бизнес сущность? И соотв. получать от *Service должен уже DTO или сущность? Или он просто DTO прокидывает и возвращает тоже DTO? Т.е. в задачи контроллера входить отображения DTO в бизнес сущности или нет? Судя по картинке,

Получать IQueryable<BusinessEntity>, передавать BusinessEnitty, может несколько.

S>DTO и AppService в одном слое, поэтому AppService должен что-то знать о DTO?

DTO это не слой. Они логики не содержат. Более логично было бы на картинке нарисовать DTO в слое Presentation.
Re[3]: Контроллер, сервисы и DTO.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.04.20 18:14
Оценка: +1 :)
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, Буравчик, Вы писали:


Б>>Нет, не должны. AppService является фасадом приложения, делает всю полезную работу, оперирует бизнес-сущностями, а не DTO.


S>Благодарю, еще вдогонку вопрос: а это нормально, если у меня AppService зависит от нескольких репозиториев. SRP не нарушается. Или по DDD -- 1 к 1?


Это не нормально. репозитории вообще надо выкинуть и сжечь.
Re[2]: Контроллер, сервисы и DTO.
От: Sharov Россия  
Дата: 30.04.20 18:26
Оценка:
Здравствуйте, gandjustas, Вы писали:


S>>Итак, имеем сл. картинку -- тыц.

G>Так себе картинка

Почему, если не секрет?

S>>2)Далее, а вот контроллер в кач-ве параметров в тот или иной *service должен передавать DTO или бизнес сущность? И соотв. получать от *Service должен уже DTO или сущность? Или он просто DTO прокидывает и возвращает тоже DTO? Т.е. в задачи контроллера входить отображения DTO в бизнес сущности или нет? Судя по картинке,

G>Получать IQueryable<BusinessEntity>, передавать BusinessEnitty, может несколько.

Это для *Service слоя от контроллера? Или что это?


S>>DTO и AppService в одном слое, поэтому AppService должен что-то знать о DTO?

G>DTO это не слой. Они логики не содержат. Более логично было бы на картинке нарисовать DTO в слое Presentation.

Presentations -- это уже View. Высоковато, наверное.
Кодом людям нужно помогать!
Re[3]: Контроллер, сервисы и DTO.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 30.04.20 20:25
Оценка: 19 (3)
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, gandjustas, Вы писали:



S>>>Итак, имеем сл. картинку -- тыц.

G>>Так себе картинка

S>Почему, если не секрет?

Потому что слои это "кто кого вызывает". А на картинке много путаницы в этом плане.


S>>>2)Далее, а вот контроллер в кач-ве параметров в тот или иной *service должен передавать DTO или бизнес сущность? И соотв. получать от *Service должен уже DTO или сущность? Или он просто DTO прокидывает и возвращает тоже DTO? Т.е. в задачи контроллера входить отображения DTO в бизнес сущности или нет? Судя по картинке,

G>>Получать IQueryable<BusinessEntity>, передавать BusinessEnitty, может несколько.

S>Это для *Service слоя от контроллера? Или что это?

Контроллер вызывает app service. Следуя парадигме CQRS, когда запрос данных и команды на изменение это разные методы, то у нас есть две категории методов — "получить данные" или "отправить команду на изменение".
То что "получить данные" возвращает IQueryable<BusinessEntity>, а то что "отправить команду на изменение" в качестве параметров принимает BusinessEntity или другие скалярные параметры.

Контроллеры занимаются:
— валидацией данных от клиента
— мэппингом в обе стороны
— кешированием (особенно HTTP)
— аутентификацией и, если возможно, авторизацией.
— обработкой ошибок (чтобы не вываливать клиенту стектрейс)
И больше никакой код этим не занимается.

Теперь вернемся к вопросу "что не так на картинке"... много чего.
Re: Еще вопрос про DDD и AppService
От: Sharov Россия  
Дата: 01.05.20 15:32
Оценка:
Такой вопрос -- вот у меня appsrv получает извне файл, по типу файла(расширение) создает обработчик. Обработчик похож
на domainsrv, ибо специфические вещи происходят на ряду с просто сохранением файла в хранилище. Так вот, я этот domainsrv
создаю в appsrv при помощи фабрики, на основе типа файла. Это нормальная практика создавать доменные сервисы с
помощью фабрики? Или я что-то не так делаю. Т.е. с одной стороны не SL (ибо анти-паттерн), с другой стороны я динамически
создаю некий типизированный доменный сервис. Это как-то в DDD укладывается?

Что-то вроде:

 IFileHandlerService handler = null;
                switch(fileEnum)
                {
                     
                    case fileEnum.TypeA:
                        handler = _fileHandlerSrvFactory.CreateTypeAFileHandlerSrv();
                        
                        break;
                    case fileEnum.TypeB:
                        handler = _fileHandlerSrvFactory.CreateTypeBFileHandlerSrv();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                }


Заранее благодарю.
Кодом людям нужно помогать!
Re[2]: Еще вопрос про DDD и AppService
От: MaxRos  
Дата: 01.05.20 16:08
Оценка: 5 (1) +1
Здравствуйте, Sharov, Вы писали:

S>Это как-то в DDD укладывается?


В современном понимании DDD прежде всего не про паттерны или набор каких-то классов, а про аналитическую часть. То есть про то, как эксперты предметной области работают с технарями и насколько точно в итоге ваша модель отражает область, с короторый вы работаете. Насколько хорошо там определены контексты и изолированы друг от друга (то есть изменение в одном не затрагивает другие). А всякие конкретные технические решения вторичны. Например, репозитории, которые в связке с EF точно не нужны. Это я всё к тому, что ваш вопрос мало отношения имеет к DDD, это просто один из технических приёмов

вот доклад Эванса на эту тему https://www.youtube.com/watch?v=lE6Hxz4yomA
Re[2]: Контроллер, сервисы и DTO.
От: Pavel Dvorkin Россия  
Дата: 01.05.20 16:23
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Да, в задачи контроллера входит преобразование из DTO в сущности и наоборот. Это его основная и единственная задача.

Б>Принимает DTO, преобразовывает в сущности, вызывает сервисы, получает от них сущности, отдает DTO.

Вот здесь несколько иная точка зрения

Makes you feel like you are pulling the guts out right? According to Martin Fowler: the Service Layer defines the application's boundery, it encapsulates the domain. In other words it protects the domain.

https://stackoverflow.com/questions/21554977/should-services-always-return-dtos-or-can-they-also-return-domain-models

Если показать контроллеру сущности, то это означает выпустить их за пределы домена в слой представления.

и ниже

If you use domain models in your presentation layer (MVC-Controllers/View, WebForms, ConsoleApp), then the presentation layer is tightly coupled to your domain, any changes in the domain requires you to change your controllers.

Так что DTO — это объекты для взаимодействия контроллера с сервисом, а в сущности должен преобразовывать сервис, и он же должен возвращать DTO.
With best regards
Pavel Dvorkin
Re[3]: Контроллер, сервисы и DTO.
От: Qulac Россия  
Дата: 01.05.20 17:14
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Буравчик, Вы писали:


Б>>Да, в задачи контроллера входит преобразование из DTO в сущности и наоборот. Это его основная и единственная задача.

Б>>Принимает DTO, преобразовывает в сущности, вызывает сервисы, получает от них сущности, отдает DTO.

PD>Вот здесь несколько иная точка зрения


PD>Makes you feel like you are pulling the guts out right? According to Martin Fowler: the Service Layer defines the application's boundery, it encapsulates the domain. In other words it protects the domain.


PD>https://stackoverflow.com/questions/21554977/should-services-always-return-dtos-or-can-they-also-return-domain-models


PD>Если показать контроллеру сущности, то это означает выпустить их за пределы домена в слой представления.


Ну и что, изменения в интерфейсе не потребуют изменения в домене, т.е. он "изолирован".

PD>и ниже


PD>If you use domain models in your presentation layer (MVC-Controllers/View, WebForms, ConsoleApp), then the presentation layer is tightly coupled to your domain, any changes in the domain requires you to change your controllers.


PD>Так что DTO — это объекты для взаимодействия контроллера с сервисом, а в сущности должен преобразовывать сервис, и он же должен возвращать DTO.


Выделять отдельный слой с функцией "изолятора" и работы с сущностными не лучшая идея. Я пробовал так, все время кажется, что он тут лишний.
Программа – это мысли спрессованные в код
Re[4]: Контроллер, сервисы и DTO.
От: Pavel Dvorkin Россия  
Дата: 01.05.20 17:20
Оценка:
Здравствуйте, Qulac, Вы писали:

PD>>Makes you feel like you are pulling the guts out right? According to Martin Fowler: the Service Layer defines the application's boundery, it encapsulates the domain. In other words it protects the domain.


PD>>https://stackoverflow.com/questions/21554977/should-services-always-return-dtos-or-can-they-also-return-domain-models


PD>>Если показать контроллеру сущности, то это означает выпустить их за пределы домена в слой представления.


Q>Ну и что, изменения в интерфейсе не потребуют изменения в домене, т.е. он "изолирован".


Если он виден presentation layer, то он не изолирован

Q>Выделять отдельный слой с функцией "изолятора" и работы с сущностными не лучшая идея. Я пробовал так, все время кажется, что он тут лишний.


Зачем отдельный слой ? Сервис и есть этот слой. Выделил в цитате выше.
With best regards
Pavel Dvorkin
Отредактировано 01.05.2020 17:21 Pavel Dvorkin . Предыдущая версия .
Re[5]: Контроллер, сервисы и DTO.
От: Qulac Россия  
Дата: 01.05.20 17:28
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Qulac, Вы писали:


PD>>>Makes you feel like you are pulling the guts out right? According to Martin Fowler: the Service Layer defines the application's boundery, it encapsulates the domain. In other words it protects the domain.


PD>>>https://stackoverflow.com/questions/21554977/should-services-always-return-dtos-or-can-they-also-return-domain-models


PD>>>Если показать контроллеру сущности, то это означает выпустить их за пределы домена в слой представления.


Q>>Ну и что, изменения в интерфейсе не потребуют изменения в домене, т.е. он "изолирован".


PD>Если он виден presentation layer, то он не изолирован


Смотря что понимать под "изолированостью".

Q>>Выделять отдельный слой с функцией "изолятора" и работы с сущностными не лучшая идея. Я пробовал так, все время кажется, что он тут лишний.


PD>Зачем отдельный слой ? Сервис и есть этот слой. Выделил в цитате выше.


Все равно лишний. Сервисы могут пригодится когда нужно выделить общий функционал у разных видом интерфейсов приложения, а так они не нужны. Зачем плодить лишние сущности?
Программа – это мысли спрессованные в код
Re[4]: Контроллер, сервисы и DTO.
От: MaxRos  
Дата: 01.05.20 17:32
Оценка:
Здравствуйте, Qulac, Вы писали:

PD>>Если показать контроллеру сущности, то это означает выпустить их за пределы домена в слой представления.


Q>Ну и что, изменения в интерфейсе не потребуют изменения в домене, т.е. он "изолирован".


Вот приходит запрос на получение документа. Документ — сложная сущность, для сборки которой надо залезть в несколько таблиц БД и дернуть сторонний сервис по http. Если это все будет делать контроллер, то чем займется следующий слой?

Имхо контроллеры это чисто утилитарный слой, в котором не должно быть никакой логики. Если говорить конкретно про asp net контроллеры, то их задача — описать интерфейс модуля в терминах http и заодно взять на себя автоматический вызов авторизации, валидации и маршрутизации запроса в нужный обработчик. Отсюда следует, что для контроллеров не нужны юнит тесты т.к. там нечего тестировать.
Re[5]: Контроллер, сервисы и DTO.
От: Qulac Россия  
Дата: 01.05.20 17:37
Оценка:
Здравствуйте, MaxRos, Вы писали:

MR>Здравствуйте, Qulac, Вы писали:


PD>>>Если показать контроллеру сущности, то это означает выпустить их за пределы домена в слой представления.


Q>>Ну и что, изменения в интерфейсе не потребуют изменения в домене, т.е. он "изолирован".


MR>Вот приходит запрос на получение документа. Документ — сложная сущность, для сборки которой надо залезть в несколько таблиц БД и дернуть сторонний сервис по http. Если это все будет делать контроллер, то чем займется следующий слой?


MR>Имхо контроллеры это чисто утилитарный слой, в котором не должно быть никакой логики. Если говорить конкретно про asp net контроллеры, то их задача — описать интерфейс модуля в терминах http и заодно взять на себя автоматический вызов авторизации, валидации и маршрутизации запроса в нужный обработчик. Отсюда следует, что для контроллеров не нужны юнит тесты т.к. там нечего тестировать.


А контролеры нельзя протестировать, по моему запросто.
Домен может содержать сервисы по бизнес логике, но это бизнес логика, а не что то добавленное из вне.
Программа – это мысли спрессованные в код
Re[6]: Контроллер, сервисы и DTO.
От: MaxRos  
Дата: 01.05.20 17:50
Оценка:
Здравствуйте, Qulac, Вы писали:

Q>А контролеры нельзя протестировать, по моему запросто.


В asp.net core можно тестировать контроллеры очень просто, но на уровне интеграционных тестов, они как раз позволят проверить работу всей обвязки вокруг контроллеров включая вызов бизнес логики.

Q>Домен может содержать сервисы по бизнес логике, но это бизнес логика, а не что то добавленное из вне.


Ну вот так иногда бывает, что бизнес логике приходится работать с данными извне, если речь про внешний сервис. Ничего страшного в этом нет, если сборкой таких сущностей не заняты контроллеры, конечно.
Re[2]: Еще вопрос про DDD и AppService
От: Буравчик Россия  
Дата: 01.05.20 17:51
Оценка: 5 (1)
Здравствуйте, Sharov, Вы писали:

S>Такой вопрос -- вот у меня appsrv получает извне файл, по типу файла(расширение) создает обработчик. Обработчик похож

S>на domainsrv, ибо специфические вещи происходят на ряду с просто сохранением файла в хранилище. Так вот, я этот domainsrv
S>создаю в appsrv при помощи фабрики, на основе типа файла. Это нормальная практика создавать доменные сервисы с
S>помощью фабрики? Или я что-то не так делаю. Т.е. с одной стороны не SL (ибо анти-паттерн), с другой стороны я динамически
S>создаю некий типизированный доменный сервис. Это как-то в DDD укладывается?

Вообще, абстрактные фабрики — code smell, если используешь DI.
https://blogs.cuttingedge.it/steven/posts/2016/abstract-factories-are-a-code-smell/

Я бы сделал прокси, который бы работал как IFileHandlerService, но для любого известного типа файла.

class AnyTypeFileHandler: IFileHandlerService


Этот сервис выбирал бы нужный обработчик и передавал бы ему все операции.
Вся эта switch-магия была бы внутри этого сервиса (в дальнейшем и от нее можно избавиться).

S>Это как-то в DDD укладывается?


Как уже упоминалось другим участником беседы, это все-таки вопросы не про DDD, а, скорее, про дизайн.
Best regards, Буравчик
Re[6]: Контроллер, сервисы и DTO.
От: Pavel Dvorkin Россия  
Дата: 01.05.20 17:55
Оценка:
Здравствуйте, Qulac, Вы писали:

PD>>Если он виден presentation layer, то он не изолирован


Q>Смотря что понимать под "изолированостью".


Невозможность внесения изменений в структуры данных домена и ниже (БД) извне его. Только он сам может эти изменения вносить.

Q>>>Выделять отдельный слой с функцией "изолятора" и работы с сущностными не лучшая идея. Я пробовал так, все время кажется, что он тут лишний.



Q>Все равно лишний. Сервисы могут пригодится когда нужно выделить общий функционал у разных видом интерфейсов приложения, а так они не нужны. Зачем плодить лишние сущности?


Ты предлагаешь все в контроллере делать ? Тогда, у него будет 2 функции : presentation layer и бизнес-логика. Как заменить presentation layer в случае необходимости ? Например, вместо REST — GUI. Домен не должен измениться — он определяется задачей, а не способом передачи запросов и показа ответов.
With best regards
Pavel Dvorkin
Re[7]: Контроллер, сервисы и DTO.
От: Qulac Россия  
Дата: 01.05.20 18:06
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Qulac, Вы писали:


PD>>>Если он виден presentation layer, то он не изолирован


Q>>Смотря что понимать под "изолированостью".


PD>Невозможность внесения изменений в структуры данных домена и ниже (БД) извне его. Только он сам может эти изменения вносить.


Q>>>>Выделять отдельный слой с функцией "изолятора" и работы с сущностными не лучшая идея. Я пробовал так, все время кажется, что он тут лишний.



Q>>Все равно лишний. Сервисы могут пригодится когда нужно выделить общий функционал у разных видом интерфейсов приложения, а так они не нужны. Зачем плодить лишние сущности?


PD>Ты предлагаешь все в контроллере делать ? Тогда, у него будет 2 функции : presentation layer и бизнес-логика. Как заменить presentation layer в случае необходимости ? Например, вместо REST — GUI. Домен не должен измениться — он определяется задачей, а не способом передачи запросов и показа ответов.


Где тут бизнес-логика вылезла? Все на месте.

  customRepository.Find("SearchString").Select((с)=>new CustomeViewModel(.......
Программа – это мысли спрессованные в код
Отредактировано 01.05.2020 18:19 Qulac . Предыдущая версия .
Re[2]: Еще вопрос про DDD и AppService
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 01.05.20 21:37
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Такой вопрос -- вот у меня appsrv получает извне файл, по типу файла(расширение) создает обработчик. Обработчик похож

S>на domainsrv, ибо специфические вещи происходят на ряду с просто сохранением файла в хранилище. Так вот, я этот domainsrv
S>создаю в appsrv при помощи фабрики, на основе типа файла. Это нормальная практика создавать доменные сервисы с
S>помощью фабрики?
Этот вопрос звучит как "это нормальная практика использовать шлифованные деревянные балки для перекрытий". Мало данных для ответа на вопрос.

S>Или я что-то не так делаю. Т.е. с одной стороны не SL (ибо анти-паттерн), с другой стороны я динамически

S>создаю некий типизированный доменный сервис. Это как-то в DDD укладывается?
Возможно и укладывается. Но если вдруг не укладывается, то что?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.