2012-04-11 2 views
27

Я понимаю, что основы персистентности, такие как Morphia и Hibernate, полагаются на аннотации объектов домена, чтобы сделать свою магию. На каком-то уровне мне кажется, что это вставляет проблемы сохранения в доменный уровень, чего мы должны стремиться избегать.Являются ли аннотации настойчивости в объектах домена плохой практикой?

Это что-то, что я должен попытаться уклониться, возможно, используя внешний файл конфигурации или, возможно, отдельные DTO из модели домена? Или это небольшая утечка между уровнями персистентности и домена, которые обычно считаются приемлемыми?

+2

Просмотреть презентацию http://www.infoq.com/presentations/Clean-Model-Tim-McCarthy – MikeSW

+0

Спасибо, это выглядит великолепно! Наблюдение сейчас ... – HolySamosa

ответ

12

В моей последней итерации в существующей системе, использующей Spring и Hibernate, я начал двигаться в аналогичном случае. При первом внедрении моделей Hibernate я стремился отделить логику приложения в классах обслуживания от логики персистентности через объекты доступа к данным. При создании новой системы в прошлом году я разрешил большинству объектов persistence служить объектами домена, потому что это было целесообразным решением.

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

Я еще не убежден, что это лучший метод, но он имеет смысл на уровне кишечника. Мне очень хотелось иметь коллекцию persistence-agnostic - nay, persistence- невежественный - набор объектов, которые остаются постоянными для хранения данных в базе данных без учета стандартных упрощений CRUD. Тем не менее, я понимаю, что в конечном итоге все операции с базой данных реализованы как CRUD. Два мира должны столкнуться, и трюк заключается в том, чтобы заставить их танцевать в гармонии.

Hibernate аннотации на объекты домена? Это прекрасный компромисс между простотой внедрения и простотой обслуживания на мой взгляд.

+2

Это также дает вам возможность быть более строгим/менее строгим в отношении состояния ваших объектов персистентности против встроенных. Я стараюсь быть предельно осознанным входов и выходов из интерфейса, и это разделяет эти проблемы таким образом. – alexwen

4

На мой взгляд, нет необходимости дублировать объекты домена, чтобы отделить их от уровня вашего уровня. Он работает с дублирующимся кодом, и он отлично справляется с использованием тех же объектов, что и DTO. Если необходимо, вы всегда можете использовать отдельные классы, если это необходимо, но я бы не сделал это эмпирическим правилом, это будет стоить вам времени, и все мы знаем, что время ценно.

+3

Я не согласен. Объекты домена по своей природе отличаются от объектов модели настойчивости, они имеют разные цели. Если иногда домен на самом деле не является доминирующим, и сущности персистенции могут использоваться напрямую, это простое совпадение, деталь реализации. Идея заключается в том, что вы начинаете моделировать домен, игнорируя постоянство. Недавно я писал о такой ситуации http://www.sapiensworks.com/blog/post/2012/04/07/Just-Stop-It!- The-Domain-Model-Is-Not-The-Persistence-Model. aspx – MikeSW

+0

@MikeSW По моему опыту, объекты домена и таблицы do * not * сильно отличаются друг от друга. Различия, которые возникают, должны быть достаточно легкими для перевода через параметры настройки ORM. На мой взгляд, хороший ОРМ должен помочь сделать это легко. – Timo

+0

Полностью согласен с @MikeSW и его записью в блоге. Например, я не хочу, чтобы меня использовали уродливые get/seters в моей модели домена, чтобы удовлетворить потребности ORM. Я хочу, чтобы моя модель домена застенчиво, без каких-либо ограничений в мире персистентности. – Mik378

7

Я недавно работал над достаточно сложной системой, имеющей отдельный слой устойчивости, и это была огромная боль в заднице и очень плохая для ремонтопригодности. Вы в основном рассматриваете конфликт между принципами YAGNI и Single Responsibility. На мой взгляд, YAGNI является более важным (увы, также более часто игнорируется).

Я бы сказал, что в подавляющем большинстве случаев, это гораздо лучше сохраняться домен объекты непосредственно, если вы используете ORM, если у вас есть конкретные требования, которые заставляют сохраняемости объекты должны быть структурированы по-другому (если они имеют точно такую ​​же структуру, нет причин отделять их, кроме аргументов башни из слоновой кости).

Обязательно: всегда делать фактический упорный материал (вызывая функции ORM) в отдельном сервисе/слое DAO! Таким образом, легче ввести слой persistence позже, если вы обнаружите, что вам это нужно.

+1

Один случай, когда я столкнулся с проблемой использования одного и того же объекта, - это оптимистическая блокировка из нескольких потоков/серверов. Если вы попытаетесь сохранить изменение на 'firstName', например, и обнаружите, что кто-то другой изменил объект, вам необходимо перезагрузить объект, чтобы внести изменения. Как вы вставляете вновь загруженный и модифицированный объект обратно в дерево объектов домена? –

+2

Проголосовал, я не согласен. Слишком много аннотаций, ссылающихся на слишком много проблем, которые в течение многих раз приводят к тому, что ваша структура класса имеет разные направления, а также поведение, делает ваш класс трудным для чтения и поддержания, и это плохо. – dalvarezmartinez1

+0

@ dalvarezmartinez - Что делать, если аннотации используются не только для сохранения данных, но и для проблем домена? Например: Пометка свойства 'Name' объекта домена как' [Обязательный] 'делает довольно понятным, что это поле требуется, но также сообщает уровень уровня уровня проверки, что они не должны принимать значения NULL. – Sam

3

Короткий ответ: Мне нравятся постоянные, богатые объекты домена.

Длинный ответ:

В течение почти 10 лет я работал на довольно большой системе ~ 500k LOC с использованием Spring и Hibernate. Сначала мы начали с подхода «сценарий транзакции» (см. Раздел «Фаулер»), отчасти потому, что мы не доверяли Hibernate. Однако за короткое время мы стали доверять Hibernate, и благодаря моему гораздо более раннему обучению в довольно пуристском OO, я стал большим сторонником переходной настойчивости в сочетании с подходом, основанным на управлении доменами. Мы в основном пришли к мысли о том, что наша система поддерживается ODBMS (с большим количеством небольших утечек :-)).

Я назвал нашу архитектуру «ядром домена», потому что книга DDD еще не была написана. Это было в первые дни Hibernate, поэтому модель домена не была загрязнена аннотациями. Отдельная забота о сохранении сохранялась отдельно в XML-сопоставлениях.

Снова, с течением времени, мы улучшили нажатие на поведение в доменном слое. У нас была довольно традиционная схема контроллера -> service -> dao ->, которая была применена с учетом времени компиляции. То, что я наблюдал с течением времени, заключается в том, что эта модель очень хорошо работала для нашей системы, которая представляла каждый аспект довольно сложной области управления планом 401 (k), включая настройку плана, торговлю, учет, тестирование соответствия, продажи, брендинг и т. Д. Богатая модель домена с (относительно) прозрачной «магической» настойчивостью была ключом к тому, что мы могли создавать новые функции с точки зрения существующих функций в модели домена.

Наш сервисный уровень только организовал взаимодействие между техническими службами (такими как электронная почта, ввод-вывод файлов, очередь и т. Д.) И помог охватить пакеты доменов, когда это необходимо. Уровень сервиса также определяет границу транзакции (через Spring). Услуги только получили или выпустили DTO или примитивы. Многие люди ненавидят это, как перерыв в DRY, но мы обнаружили, что это помогло нам честно определить интерфейсы службы и код, который их использовал. Это также облегчило отдаленные вещи позже.

Этот подход позволил нам создать высококачественное программное обеспечение с довольно небольшой командой (мы были командой Scrum).

Итак, считайте меня верующим в постоянных объектах домена. Не знаю, помогает ли моя история, но я хотел поделиться ею.

9

Являются ли аннотации настойчивости в предметных объектах плохой практикой?

Да. С появлением NoSQL вы не можете полагаться на единую стратегию сохранения.

Например, сегодня я сохраняю свои объекты домена (допустим, используя морфию) в MongoDB. Что делать, если завтра я хочу сохранить объекты домена до Neo4j?

Или, возможно, вы захотите сохранить объекты домена для всех трех типов баз данных, таких как реляционные (Postgres/MySQL), MongoDB (хранилище документов) и Neo4J (база данных графов) только для оценки.

Во всех этих случаях лучше иметь отдельную стратегию сохранения состояния, а не просто полагаться на домен объекты

Лучшие практики: Передача Persistent стратегии как шаблон стратегии может помочь. Но будьте осторожны при разработке ваших классов/объектов.

+0

Я думаю, что слишком много вопросов «что, если ...». Я не видел ни одного проекта, который изменяет базу данных и не использует три разных технологии db в одном модуле, которые могли бы пожертвовать затратами на поддержку дополнительных стратегий/картографов и т. Д. По моему опыту проекты намного сложнее, начиная с этого подхода, а не просто аннотировать доменного уровня. – thilko

+0

@thilko Я думаю, что вы делаете справедливую точку, практически говоря.Тем не менее, это приводит меня к выводу, что ** необходимо упростить применение систем сохранения в сочетании с шаблоном репозитория ** - особенно в отношении DDD и/или TDD. – Timo

0

Я бы предпочел объекты с богатым доменом, на которых есть аннотации.Даже Эванс использует этот подход в своем sample app. Он использует XMl вместо Annotations, но он все еще сохраняет те же объекты.

Возможно, более чистое разделение домена и настойчивость, но не просто возможность потенциально выбрать другую технологию db в будущем. Это путь к черту сложности, и мистер YAGNI вас укусит.

4

Я полагаю, что буду использовать аннотации в своем домене, если я уже решил использовать структуру персистентности, которую я собираюсь использовать, однако XML будет более удобным, если вы будете следовать архитектуре Hexagonal и TDD. Если вы аннотируете свой домен с определенной структурой, вы будете связаны с интеграцией настойчивости и не сможете протестировать основные функции с целью стать агностиком технологии/структуры.

Смежные вопросы