Управление историческими объектами сущностей - PullRequest
4 голосов
/ 19 июля 2011

Мы преобразуем существующую систему в DDD и изо всех сил пытаемся обдумать несколько концепций.

У нас есть совокупный корень с именем Animal, который имеет такие свойства, как Status и Source. В настоящее время в базе данных есть две таблицы с именами StatusHistory и SourceHistory, в которых хранится информация о животном при изменении статуса. В этих таблицах иногда удаляются записи, и их редко требуется получать при получении Animal от AnimalRepository.

Значит, большой вопрос, где они принадлежат? Вот несколько идей, которые у нас есть:

  • Имейте их обоих как различные объекты сущности как часть совокупности животных. И имеют соответствующие методы, которые позволяют их обновлять, например: Animal.UpdateStatus(newStatus), который добавит в коллекцию объект new StatusHistory(this). Но, как уже упоминалось выше, они редко требуются при получении существующего животного для хранилища, поэтому мы не хотим, чтобы хранилище загружало их. В настоящее время мы не используем ORM и вручную сопоставляем, используя шлюз данных таблиц внутри репозиториев.

  • Сделать каждую из сущностей истории совокупным корнем. Мы не фанат этого, так как кажется, что мы на самом деле не моделируем домен, а просто движемся к Active Record Pattern. Также задача их обновления для животных должна лежать вне животного существа.

  • Мы могли бы попытаться объединить эти истории в другой совокупный корень, называемый AnimalHistory, цель которого - поддерживать историю животного. Но опять-таки это будет двигать логику хранения истории в нечто иное, чем животное. Возможно, сервис, подобный AnimalProcessingService, который может показаться, что мы движемся к анемическому дизайну.

Я надеюсь, что есть еще один вариант, который обеспечит нам более чистый дизайн.

Ответы [ 2 ]

2 голосов
/ 19 июля 2011

Недавно появилась интересная статья Мартина Фаулера, в которой может быть рассмотрен вопрос о том, что вам не нужны некоторые вещи при поиске, и который называется «Разделение ответственности при выполнении командных запросов».Основная концепция заключается в том, что вы можете использовать «модель» для «запроса» (чтение), отличную от «команды» (сохранение).

http://martinfowler.com/bliki/CQRS.html

То, что вы выполняете DDD, не означает, что все должно содержаться в соответствующих объектах домена.Разработка вашего домена - это то же самое, что и разработка сервисов, мероприятий и т. Д. Я хочу сказать, что нужно сделать так, чтобы ваш домен получился более естественным, сосредоточив внимание на том, что требуется «домену», и на каких решениях можно удовлетворить эти требования.В DDD нет строгой методологии, это скорее выбор в перспективе, чем формальный шаблон проектирования.Таким образом, наличие объектов истории в качестве корней сущностей не обязательно является плохим, если они действительно используются только для сохранения.Ваши службы, связанные с «командами», составляют правильный логический поток для сохранения животных и историй.

Я также хотел бы отметить, что такие вещи, как Animal.UpdateStatus(newStatus), довольно активная запись, которую вы, казалось, хотели избежать.

0 голосов
/ 19 июля 2011

Если вы используете Ejb3, то вы можете написать свою собственную реализацию для другого слушателя, например @ PostInsert , @ PostUpdate и т. Д.

Предоставьте свою реализацию вэти слушатели.Например, предположим, что в Animal есть обновление, тогда будет вызван ваш прослушиватель PostUpdate, который обновит запись истории.

У этого подхода есть одно большое преимущество, так как все происходит в одной транзакции, и как только вы пишете общий код, выникогда не придется беспокоиться об обновлении таблиц истории.

Второй подход будет использовать REFLECTION + INTERCEPTORS

...