Действительно хороший вопрос. Я потратил немало времени на размышления на такие темы.
Вы демонстрируете глубокое понимание, отмечая противоречие между моделью выразительной области и разделением интересов. Это очень похоже на напряженность в вопросе, который я задал по поводу принципа «Не спрашивай» и принципа единой ответственности .
Вот мой взгляд на тему.
Модель предметной области анемична, поскольку не содержит логики предметной области. Другие объекты получают и устанавливают данные, используя объект анемичного домена. То, что вы описываете, не звучит для меня как логика предметной области. Это могут быть, но, как правило, справочные таблицы и другой технический язык, скорее всего, термины, которые что-то значат для нас, но не обязательно что-то для клиентов. Если это неверно, уточните.
В любом случае, создание и сохранение объектов домена не должны содержаться в самих объектах домена, потому что это не логика домена.
Таким образом, чтобы ответить на вопрос, нет, вам не следует вводить целую кучу недоменных объектов / концепций, таких как таблицы поиска и другие детали инфраструктуры. Это утечка одной заботы в другую. Шаблоны Factory и Repository из Domain-Driven Design лучше всего подходят для того, чтобы отделить эти проблемы от самой доменной модели.
Но учтите, что если у вас нет доменной логики, то в конечном итоге вы получите анемичные доменные объекты, то есть пакеты безмозглых получателей и установщиков, как это некоторые магазины утверждают, что делают SOA / уровни обслуживания .
Итак, как вы получаете лучшее из обоих миров? Как вы фокусируете свои доменные объекты только на доменной логике, сохраняя UI, конструкцию, постоянство и т. Д. В стороне? Я рекомендую вам использовать такую технику, как Double Dispatch или какую-либо форму ограниченного доступа к методу .
Вот пример двойной отправки. Скажем, у вас есть эта строка кода:
entity.saveIn(repository);
В вашем вопросе saveIn () будет обладать всевозможными знаниями об уровне данных. Используя Double Dispatch, saveIn () делает это:
repository.saveEntity(this.foo, this.bar, this.baz);
А метод saveEntity () в хранилище обладает всеми знаниями о том, как сохранять данные на уровне данных, как и положено.
В дополнение к этой настройке вы можете иметь:
repository.save(entity);
, который просто звонит
entity.saveIn(this);
Я перечитал это и заметил, что сущность все еще тонкая, потому что она просто отправляет свое постоянство в хранилище. Но в этом случае сущность должна быть тонкой, потому что вы не описали никакой другой доменной логики. В этой ситуации вы можете сказать: «Винт Double Dispatch, дай мне доступ».
И да, вы могли бы, но IMO показывает слишком много того, как реализована ваша сущность, и эти средства доступа отвлекают от предметной логики. Я думаю, что единственный класс, который должен иметь get и sets - это класс, имя которого заканчивается на «Accessor».
Я скоро заверну это. Лично я не пишу свои сущности с помощью методов saveIn (), потому что я думаю, что даже просто наличие метода saveIn () приводит к засорению объекта предметной области отвлекающими факторами. Я использую либо шаблон класса друга, частный доступ к пакету, либо, возможно, шаблон Builder .
ОК, я закончил. Как я уже сказал, я немного зациклен на этой теме.