Могут ли службы инфраструктуры возвращать объекты домена в архитектуре дяди Боба «The Clean»?

#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. Обновлен ответ джордана-Уокера. Согласованность — это интерфейс, а не детали реализации.