Где моя DDD логика принадлежит? - PullRequest
2 голосов
/ 23 октября 2010

Меня убедила книга Эрика Эванса, и я интегрирую DDD в мою структуру.Все базовые элементы (сервисы, репозитории, ограниченный контекст и т. Д.) Были реализованы, и теперь я ищу отзывы о том, как правильно интегрировать это.

У меня есть некоторая бизнес-логика, которая должна выполняться, когда сущностьсоздан или изменен.Этот пример очень простой.Большая часть бизнес-логики станет намного более сложной.

Эта бизнес-логика может быть разбита на следующие действия:

  1. Обновление вычисляемых полей;
  2. Обновление дочерней записивнутри совокупного корня.При создании сводного корня это влечет за собой создание дочерней записи по умолчанию.При обновлении сводного корня это влечет за собой удаление существующей дочерней записи и создание новой, если изменилось определенное поле в сводном корне;
  3. Распространение даты начала и окончания сводного корня на дату начала и окончаниядочерние записи внутри совокупного корня.Они должны синхронизироваться при определенных обстоятельствах;
  4. Распространить поле совокупного корня на другой совокупный корень.

Моя первая попытка - поместить все это в совокупностьroot, но я чувствую, что это не сработает.У меня есть следующие проблемы при интеграции этой логики:

  • Все эти действия должны быть выполнены как одно целое и не должны быть доступны как отдельные действия.Это приводит к тому, что это будет очень трудно проверить (TDD);
  • Я не уверен, можно ли перенести какое-либо из этих действий в службу.Причина этого в том, что они не имеют смысла вне совокупного корня, но это значительно упростит TDD;
  • Некоторые логические изменения меняются в зависимости от того, создан новый объект или изменен существующий.Должен ли я поместить эти две ветви в логику обновления или я должен создать два совершенно разных пути, которые разделяют бизнес-код, который не различает основанные создание / изменение.

Любая помощь по вышеуказанным вопросам будет оченьоценил и другие отзывы в целом.

1 Ответ

6 голосов
/ 23 октября 2010

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

Что касается TDD, то метод с доступом "package" к корню агрегата (например, "Calculate ()") должен координировать все действие, которое обычно вызывается либо сервисом, либо объектом репозитория.Это то, что тесты должны выполнять в сочетании с установкой различных комбинаций переменных экземпляра. Совокупный корень должен предоставлять свои переменные экземпляра, коллекцию дочерних элементов, а каждый дочерний элемент должен предоставлять свои переменные экземпляра через геттеры - это позволяет тестам проверять их состояние.В случаях, когда вам необходимо скрыть информацию, создайте пакет этих геттеров или частный доступ и используйте свою платформу модульного тестирования, чтобы сделать их общедоступными для целей тестирования.

Для вашей среды тестирования рассмотрите mocking хранилищеобъекты (вы используете внедрение зависимостей , верно?) для возврата жестко закодированных значений. Если не считать этого, рассмотрите возможность использования чего-то вроде dbunit для работы с базой данных в известном состоянии.

НасколькоИзменения в логике связаны с созданием и изменением. Вы имеете в виду, как сохранить или существует реальный алгоритм для рассмотрения?Если первое, я бы сделал хранилище ответственным, а во втором я бы сделал два отдельных метода (например, "cellCreate () "и" calcUpdate () "), которые делегировать (при необходимости) делегировать ().

Кроме того, есть проблема параллелизма, о которой следует подумать, потому что звучит так, как будто вычисляемые значения зависят от изменяемых полей.Так что либо нужно иметь тщательную блокировку, либо объединять корни, которые могут использоваться клиентом только один раз за раз.Это также относится к распространению поля по агрегатам - я бы, вероятно, использовал репозиторий для этой цели - но вам нужно тщательно продумать, как это должно или не должно влиять на других клиентов, которые используют объект репозитория.

...