Интерфейс с сервисным уровнем или самими объектами домена?(DDD) - PullRequest
4 голосов
/ 29 ноября 2010

Я все еще изучаю DDD, и у меня есть два (возможно, простых) вопроса:

Если Factory создает новый объект / граф / совокупность экземпляров, но также "восстанавливает" объекты / графы из репозитория тогда:

(1) Функции / задания / задачи / единица работы вашего уровня обслуживания вызывают в Factory или поведенческий метод в экземпляре Entity или функцию DomainService? Я заблудился относительно стека вызовов, основанного на ответственности этих компонентов.

(2) Есть ли у экземпляров сущностей даже "поведенческие методы", подобные описанным выше? Например, имеет ли пост p.UpdatePost(string bodyText) или это не касается модели предметной области, и поэтому то же самое должно быть достигнуто с репозиторием? Или функция сервисного уровня, должна ли она вызывать репозиторий в этом случае, а у экземпляра сущности просто есть поведенческие методы, специфичные для домена, а не постоянства? Но тогда почему звучит так, будто «обновление сообщения» является функцией домена, если это цель пользователя?

Вы можете видеть, что я повсюду. Пожалуйста, помогите.

1 Ответ

3 голосов
/ 01 декабря 2010

(1) Вызывает ли ваш уровень / функции / задачи / единицу работы вашего уровня обслуживания в Factory или поведенческий метод в экземпляре Entity или функцию DomainService?Я потерян в отношении стека вызовов, основанного на ответственности этих компонентов.

Обычно - верхний уровень извлекает необходимый агрегатный корень и вызывает на нем функцию.Иногда верхний уровень извлекает несколько агрегатных корней и передает их службе домена, но не часто, потому что служба домена является довольно убедительным признаком того, что существует нераспознанный агрегатный корень.В конце - верхний уровень обеспечивает сохранение совокупного корня.

(2) Есть ли у экземпляров сущностей даже "поведенческие методы", подобные описанным выше?Например, имеет ли пост p.UpdatePost (string bodyText) или это не касается модели предметной области, и поэтому то же самое должно быть достигнуто с репозиторием?Или функция сервисного уровня, должна ли она вызывать репозиторий в этом случае, а у экземпляра сущности просто есть поведенческие методы, специфичные для домена, а не постоянства?Но тогда почему звучит так, будто «обновление сообщения» является функцией домена, если это цель пользователя?

Да, они делают.Доменная модель должна знать об изменениях своего состояния.И это гораздо выгоднее, как кажется на первый взгляд.Самое замечательное в этом то, что вы получаете точку расширяемости.Если клиент пойдет неделю к вам и скажет, что он хочет, чтобы система проверяла дополнительные вещи, когда пользователь обновляет сообщение - вместо поиска каждой строки post.bodyText="new value", вы сможете сразу перейти к методу post.UpdatePost и прикрепить туда необходимые вещи..

С другой стороны - CRUD не является взаимоисключающим с доменным дизайном.Например, в моем приложении управление пользователями и их ролями достаточно неинтересно, и я даже не пытаюсь их детально моделировать.Вам необходимо распознавать детали, которые важны для бизнеса. Ваше приложение описывает и работает с ним.

Помните, что проектирование на основе предметной области имеет смысл только для сложных приложений.Простому приложению для блогов это не нужно.

(3) Я ошибаюсь, полагая, что уровень сервиса (не доменные службы) должен инкапсулировать, как интерфейс взаимодействует с уровнем домена?

На мой взгляд, прикладные сервисы больше для организации инфраструктуры.Если инфраструктура не задействована, то прикладная служба теряет ценность :

Службы приложений в основном представляют собой только фасады.И каждый фасад плох, если сложность добавляет сложностей, которые он решает.


Внутри домена:

//aggregate root is persistence ignorant. 
//it shouldn't reference repository directly
public class Customer{
  public string Name {get; private set;}
  public static Customer Register(string name){
    return new Customer(name);
  }
  protected Customer(string name){
    //here it's aware of state changes.
    //aggregate root changes it's own state
    //instead of having state changed from outside
    //through public properties
    this.Name=name;
  }
}

//domain model contains abstraction of persistence
public interface ICustomerRepository{
  void Save(Customer customer);
}

За пределами домена:

public class CustomerRepository:ICustomerRepository{
  //here we actually save state of customer into database/cloud/xml/whatever
  public void Save(Customer customer){
    //note that we do not change state of customer, we just persist it here
    _voodoo.StoreItSomehow(customer);
  }
}

//asp.net mvc controller
public class CustomerController{
  public CustomerController(ICustomerRepository repository){
    if (repository==null)throw new ArgumentNullException();
    _repository=repository;
  }
  public ActionResult Register(string name){
    var customer=Customer.Register(name);
    _repository.Save(customer);
  }
}
...