Пример решения анемичной доменной модели
Я рассматриваю области, в которых я могу оптимизировать дизайн своего инструмента для расчета ипотеки, в основном для целей обучения. Прочитав об Анемичных Доменных Моделях, я заинтересовался созданием Богатых Моделей и заметил, что моя текущая реализация может иметь анемию! Вот текущая реализация в псевдокоде:
class MortgageCalculator {
Mortgage mortgage; // mortgage object containing loanAmount, interest rate, etc.;
calculateMonthlyPayment(); // calculates monthly payments using mortgage object's properties
}
class Mortgage { // Anemic?
loanAmount;
interestRate;
}
В настоящее время объект ипотеки служит преимущественно для передачи данных между объектами и т. Д.
Вот несколько вариантов ревизии, которые я рассматриваю:
- Удалите объект Mortgage из MortgageCalculator и используйте Mortgage исключительно как DTO, в то время как методы калькулятора принимают аргументы (например, calcMonthlyPayment(loanAmount, InterestRate). Это поможет отсоединить MortgageCalculator от объекта Mortgage, но при этом все равно будет иметь Mortgage в качестве анемичной модели,
- Объедините оба класса в одну "богатую" модель MortgageCalculator, которая содержит как бизнес-логику (например, calcMonthlyPayment), так и свойства ипотеки (например, loanAmount). Меня беспокоит то, что я не уверен, нужно ли объекту калькулятора хранить свои операнды в качестве переменных экземпляра, но они облегчили бы передачу, хранение данных и, возможно, разрешили бы анемию?
Мне интересно, какой будет идеальный подход, или я упускаю суть?
3 ответа
Возможно, Mortgage
Объект может выполнять части расчета. Например, рассмотрим объект, который вычисляет сумму заказа:
for (Line line : orderLines)
int total += line.getPrice() * line.getQuantity();
Это известно как Feature Envy, и может быть:
for (Line line : orderLines)
int total += line.calculateTotal();
MortgageCalculator
на самом деле не является сущностью домена, потому что она не заполняется в базе данных, поэтому, чтобы избежать анемии, вы можете объединить Mortgage
юридическое лицо:
class Mortgage {
loanAmount;
interestRate;
calculateMonthlyPayment();
}
Другое дело: DTO отличается от объекта домена, DTO предназначен для передачи данных в среде распространения, тогда как объект домена должен сосредоточиться на доменной логике.
Вы можете использовать доменную сущность в качестве DTO, потому что в некоторых случаях DTO имеет те же свойства, что и Domain Entity. Но, в большинстве случаев, зависит от каждого клиента, возможно, им нужно получить данные, для которых требуется более одного объекта домена. Таким образом, для разделения проблем и обеспечения большей поддержки было бы предложено создать DTO, разделенный сущностью домена:
class MortgageDto {
loanAmount;
interestRate;
}
Вы не можете делать DDD, если не знаете своих ограниченных контекстов (BC). Так что же такое БК в этом случае? Потому что все зависит от этого.
Из того, что я понимаю в вашем случае, я думаю, хорошо, что у вас есть MortageCalculator, потому что у вас может быть несколько способов расчета ипотеки. Этот класс может иметь метод, который будет принимать аргумент Ипотека. Конечно, то, что я сказал, может быть неверным, потому что я не знаю ваш домен.
Всегда трудно ответить на конкретный вопрос о DDD, если не случается, что он является экспертом в требуемой области. Но все начинается с БК, поэтому снова, каков ваш БК и какова бизнес-роль Ипотеки?