#c# #domain-driven-design #clean-architecture #onion-architecture
#c# #дизайн, управляемый доменом #чистая архитектура #onion-архитектура
Вопрос:
Рассмотрим:
Уровень прецедентов определяет интерфейс
public interface IGeocoder
{
Coordinate GetCoordinate(Address address);
}
Coordinate
и Address
являются объектами значений, определенными на уровне домена (то есть на уровне сущностей на жаргоне дяди Боба). Очевидно, что вариант использования (interactor) создает Address
и передает его IGeocoder
, ожидая, что Coordinate
будет возвращен.
Нарушит ли это какие-либо правила чистой архитектуры? Должен ли я вместо этого передавать DTO через интерфейс, чтобы фактическая реализация сервиса не отвечала за генерацию объектов домена? Или это нормально?
Обратите внимание, что я не вижу никакой разницы между этим и репозиторием (entity gateway), интерфейс которого также был бы определен на уровне прецедентов, но реализован на уровне окружающих интерфейсных адаптеров:
public interface IRestaurantRepository
{
// ...
}
Комментарии:
1. Я думаю, что это нормально. ИМХО
Ответ №1:
Кому принадлежит реализация инфраструктурной службы? Это одна и та же команда? Тогда должно быть нормально обрабатывать это аналогично репозиториям; возвращать объекты домена напрямую. Принадлежит ли он другой команде? Тогда создание границы и передача выделенных DTO могут быть полезными, поскольку это создает меньшую связь.
Комментарии:
1. Мне нравится этот ответ, поскольку речь идет о связывании, а не о слоях. Репозитории связаны с объектами домена, потому что это их ответственность (на мой взгляд). Идею службы геокодирования, вероятно, не следует связывать с объектами домена, поскольку ее было бы сложнее повторно использовать в другом месте. В данном случае это просто личный побочный проект, поэтому, вероятно, для него нормально возвращать объекты домена, но это делает его менее пригодным для повторного использования в других контекстах.
Ответ №2:
Все зависит от того, что такое ваша «сущность» и что такое «DTO». Если «объект» и «DTO» в основном одинаковы, то вы ничего не нарушаете, передавая объект.
Однако, если у вашего объекта была функция, подобная address.getISOAddress(), и ожидалось, что ваша функция getCoordinates вызовет эту функцию, чтобы получить правильный адрес / координаты, то это нарушило бы архитектуру, и вместо этого вам следует передать ISOAddress в вашу пользовательскую базу getCoordinates.
Важно помнить, что вы имеете дело с интерфейсами, контрактами или абстракциями. Если этот интерфейс имеет дело с абстрактным классом, конкретная реализация точного экземпляра не должна и не имеет значения. Важно то, что у вас есть понятный интерфейс на правильном уровне абстракции, и что ваша система гибкая, так что детали реализации могут меняться, и ваша система по-прежнему работает без серьезных изменений.
Комментарии:
1. Как насчет репозиториев? Они также являются адаптерами интерфейса и напрямую обрабатывают объекты домена.
2. Репозитории напрямую обрабатывают объекты домена только тогда, когда они немые, в противном случае они обрабатывают модели объектов.
3. Обычно я вижу их реализацию не так. Обычно они подключаются непосредственно к объектам. Представьте, что у вас есть приложение, в котором некоторые репозитории подключаются к объектам домена, а некоторые нет … это могло бы сбить с толку, нет? Отсутствует согласованность.
4. Даже если у вас одинаковые поля, уровень домена не должен знать уровень инфраструктуры (с DTO).
5. Обновлен ответ джордана-Уокера. Согласованность — это интерфейс, а не детали реализации.