2009-03-04 4 views
20

Я прочитал некоторые из вопросов, касающихся моделей анемичных доменов и разделения проблем. Каковы наилучшие методы для выполнения/присоединения логики домена на объектах аномальной области? На моей работе у нас довольно анемичная модель, и в настоящее время мы используем «вспомогательные» классы для выполнения базы данных/бизнес-логики на объектах домена. Например:Методы обработки аномальной модели домена

public class Customer 
{ 
    public string Name {get;set;} 
    public string Address {get;set;} 
} 

public class Product 
{ 
    public string Name {get;set;} 
    public decimal Price {get;set;} 
} 

public class StoreHelper 
{ 
    public void PurchaseProduct(Customer c, Product p) 
    { 
     // Lookup Customer and Product in db 
     // Create records for purchase 
     // etc. 
    } 
} 

Когда приложение должно сделать покупку, это создало бы StoreHelper и вызвать метод на объекты домена. Для меня было бы разумным, чтобы Клиент/Продукт знал, как сохранить себя в репозитории, но вам, вероятно, не нужны методы Save() для объектов домена. Это также имеет смысл для такого метода, как Customer.Purchase (Product), но это то, что кладет доменную логику на объект.

Вот некоторые методы, которые я уже сталкивался, не уверен, которые хорошо/плохо:

  1. клиента и продукта наследуют от класса «Entity», который обеспечивает основные операции CRUD положенным образом (возможно, используя ORM).
    • Плюсы: Каждый объект данных будет автоматически получать операции CRUD, но затем привязаны к базе данных/ОРМ
    • Минусы: Это не решает проблему бизнес-операций на объектах, а также связывает все объекты домена к базовой Сущности, которая не может быть целесообразным
  2. Используйте вспомогательные классы для обработки операций CRUD и бизнес-логику
    • ли смысл иметь объекты DAO для «чистой базы данных» операций, а также отдельные бизнес-хелперы для них рудные операции бизнеса?
    • Лучше использовать для этого нестатические или статические вспомогательные классы?
    • Pros: объекты домена не привязаны к какой-либо базе данных/бизнес-логики (полностью анемией)
    • Минусы: не очень OO, не очень естественно использовать помощников в коде приложения (выглядит как код C)
  3. Используйте технику Double диспетчерской, где компания имеет методы для сохранения произвольного хранилища
    • Плюсы: лучшее разделение задач
    • Cons: объекты имеют некоторую дополнительную логику прикрепленную (хотя это развязано)
  4. В C# 3.0, вы можете использовать методы расширения для присоединения CRUD/бизнес-методы для объекта домена, не касаясь его
    • Является ли это действительный подход? Каковы плюсы и минусы?
  5. Другие техники?

Каковы наилучшие методы обработки этого? Я довольно новичок в DDD (я читаю книгу Эванса - так, может быть, это откроет мне глаза)

ответ

7

Martin Fowler много написал о моделях доменов, включая anemic domain models. Он также имеет краткие описания (и диаграммы классов UML) многих шаблонов проектирования для моделей и баз данных домена, которые могут быть полезны: Catalog of "Patterns of Enterprise Application Architecture".

Я предлагаю посмотреть модели Active Record и Data Mapper. Из описания вашей проблемы звучит так, что ваши вспомогательные классы содержат как правила домена/бизнеса , так и.

Активная запись переместила бы логику домена и код базы данных помощника в другие объекты домена (например, ваш базовый класс Entity). Data Mapper переместил бы логику домена помощника в объекты домена и код базы данных в отдельный объект карты. Любой подход был бы более объектно-ориентированным, чем вспомогательные классы процедурного стиля.

Книга Эрика Эванса «Управление доменом» отлично. Он становится немного сухим, но определенно стоит того. InfoQ имеет "Domain Driven Design Quickly" mini-book, что является хорошим введением в книгу Эванса. Плюс «Быстрое создание домена» можно получить в виде бесплатного PDF-документа.

2

Я всегда думал о модели анемичного домена как о анти-паттерне.Понятно, что клиент будет покупать продукты, что способность может быть generised путем реализации интерфейса

Interface IPurchase 
     Purchase(Product); 

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

14

Для того, чтобы избежать анемией модели, реорганизовать вспомогательные классы:

Логика как:
"Customer.PurchaseProduct (продукт, компенсация оплаты)",
«Customer.KillCustomer (Person убийца, оружие оружие) «
должен существовать прямо в объекте домена« Клиент ».

Логика как:
"Customer.IsCustomerAlive()"
"Customer.IsCustomerHappy()"
должны пойти в спецификации.

Логика как:
"Customer.Create()",
"Customer.Update()"
, очевидно, должны идти к хранилищам.

Логика как:
"Customer.SerializeInXml()"
"Customer.GetSerializedCustomerSizeInBytes()"
должны идти к услугам.

Комплексные конструкторы должны идти на заводы.

Вот как я его вижу. Я был бы рад, если бы кто-нибудь мог прокомментировать мое понимание подхода DDD.


Edit:

Иногда - анемией модель предметной области shouldn't be avoided.

Отредактирован мой ответ, чтобы добавить, что DDD - это не собирание и удаление шаблонов.
DDD - примерно способ мы думаем.

+0

Кажется, что много разных классов просто для обслуживания клиента. Почему бы не бросить большую часть этого в одном классе, с сервисом для обработки чего-либо сложного? –

+0

Мой ответ старый, как ад. : D –

+0

@ LuckyLindy В основном потому, что DDD - это создание моста между экспертами домена и программистами. Модель домена не должна содержать технических средств, иначе вездесущий язык не сможет существовать. Чтобы выйти из технического материала - мы должны его абстрагировать. Абстрагирование чего-то всегда раздувает базу кода. –

0

Один из подходов, который вы не упомянули, использует AOP для обработки доступа к данным. Пример моего недавнего использования этого подхода (хотя и значительно упрощенного для целей публикации) состоял в том, что у меня был объект домена Account, который имел метод debit, инкапсулируя бизнес-логику, необходимую для успешного дебетования со счета.

N.B. Весь код Java с AspectJ АОП нотации ...

public boolean debit(int amount) { 
    if (balance - amount >= 0) { 
     balance = balance - amount; 
     return true; 
    } 
    return false; 
} 

При соответствующем хранилище впрыскивают в моем аспекте, я тогда использовал Pointcut для перехвата вызовов этого метода ...

pointcut debit(Account account,int amount) : 
    execution(boolean Account.debit(int)) && 
    args(amount) && 
    target(account); 

. ..и применил некоторые советы:

after(Account account, int amount) returning (boolean result) : debit(account,amount) { 
    if (result) getAccountRepository().debit(account, amount); 
} 

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

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