Де ми проведемо межу між делегуванням та інкапсуляцією бізнес-логіки? Мені здається, що чим більше ми делегуємо, тим анемічнішими ми стаємо. Однак делегація також сприяє повторному використанню та принципу DRY. Отже, що доречно делегувати і що має залишитися в наших моделях домену?
Візьміть такі приклади як приклади:
Авторизація . Чи повинен об'єкт домену нести відповідальність за підтримку правил контролю доступу (наприклад, властивості CanEdit) або повинен бути делегований іншому компоненту / службі, що відповідає виключно за управління доступом, наприклад, IAuthorizationService.CanEdit (об'єкт)? Або це повинно бути поєднання двох? Можливо, в об’єкті домену є властивість CanEdit, яка делегує внутрішній сервіс IAuthorizationService для виконання фактичної роботи?
Перевірка . Те саме обговорення, що й вище, стосується валідації. Хто дотримується правил і хто відповідає за їх оцінку? З одного боку, стан об'єкта повинен належати цьому об'єкту, а дійсність - це стан, але ми не хочемо переписувати код, який використовується для оцінки правил для кожного об’єкта домену. У цьому випадку ми могли б використовувати спадщину ...
Створення об'єкта . Фабричний клас проти заводських методів порівняно з "нововведенням" екземпляра. Якщо ми використовуємо окремий заводський клас, ми можемо виділити та інкапсулювати логіку створення, але за рахунок відкриття стану нашого об'єкта на заводі. Цим можна керувати, якщо наш доменний шар знаходиться в окремій збірці, відкривши внутрішній конструктор, який використовується заводом, але це стає проблемою, якщо існує кілька моделей створення. І якщо вся фабрика робить виклик правильного конструктора, який сенс мати фабрику?
Фабричні методи класу усувають проблему з відкриттям внутрішнього стану об'єкта, але, оскільки вони є статичними, ми не в змозі розірвати залежності через інжекцію заводського інтерфейсу, як ми можемо з окремим заводським класом.
Наполегливість . Можна стверджувати, що якщо наш доменний об’єкт буде піддавати CanEdit під час делегування відповідальності за здійснення перевірки авторизації іншій стороні (IAuthorizationService), чому б не встановити метод "Зберегти" на нашому об'єкті домену, який робить те саме? Це дозволило б оцінити внутрішній стан об'єкта, щоб визначити, чи може операція виконуватися без порушення інкапсуляції. Звичайно, це вимагає, щоб ми ввели екземпляр сховища в наш об’єкт домену, який трохи пахне для мене, тож ми замість цього піднімаємо подію домену та дозволяємо обробнику виконувати операцію збереження?
Бачите, куди я йду з цим?
У Rockford Lhotka є велика дискусія щодо його причин проходження маршруту «Клас заряджання» для його CSLA-рамки, і я маю трохи історії з цим фреймом, і я бачу його уявлення про бізнес-об’єкти, що паралельно співпадають доменні об’єкти багато в чому. Але намагаючись стати більш прихильним до хороших ідеалів DDD, мені цікаво, коли співпраці стає занадто багато.
Якщо я закінчую IAuthorizationService, IValidator, IFactory та IRepository для мого сукупного кореня, що залишається? Чи достатньо методу Publish, який змінює стан об'єкта з проекту на опублікований, досить, щоб вважати клас об'єктом домену, який не є анемічним?
Твої думки?