Ответ 1
Но мне непонятно, где слой factory "лежит с DDD архитектура? Если factoryвызов непосредственно в репозиторий получить свои данные или услугу библиотека?
factory должен быть универсальным магазином для создания объектов домена. Любая другая часть кода, которая должна это сделать, должна использовать factory.
Как правило, существует как минимум три источника данных, которые используются как входные данные в конструкцию объекта factory для объекта: ввод из пользовательского интерфейса, результаты запросов от настойчивости и запросы, имеющие значение для домена. Поэтому, чтобы ответить на ваш конкретный вопрос, в репозитории будет использоваться factory.
Вот пример. Здесь я использую шаблон Holub Builder. Изменить: игнорировать использование этого шаблона. Я начал понимать, что не слишком хорошо смешивается с фабриками DDD.
// domain layer
class Order
{
private Integer ID;
private Customer owner;
private List<Product> ordered;
// can't be null, needs complicated rules to initialize
private Product featured;
// can't be null, needs complicated rules to initialize, not part of Order aggregate
private Itinerary schedule;
void importFrom(Importer importer) { ... }
void exportTo(Exporter exporter) { ... }
... insert business logic methods here ...
interface Importer
{
Integer importID();
Customer importOwner();
Product importOrdered();
}
interface Exporter
{
void exportID(Integer id);
void exportOwner(Customer owner);
void exportOrdered(Product ordered);
}
}
// domain layer
interface OrderEntryScreenExport { ... }
// UI
class UIScreen
{
public UIScreen(OrderEntryDTO dto) { ... }
}
// App Layer
class OrderEntryDTO implements OrderEntryScreenExport { ... }
Вот как выглядит OrderFactory:
interface OrderFactory
{
Order createWith(Customer owner, Product ordered);
Order createFrom(OrderEntryScreenExport to);
Order createFrom(List<String> resultSets);
}
Логика для выбранного продукта и генерация маршрута идут в OrderFactory.
Теперь вот как factory может использоваться в каждом экземпляре.
В OrderRepository:
public List<Order> findAllMatching(Criteria someCriteria)
{
ResultSet rcds = this.db.execFindOrdersQueryWith(someCriteria.toString());
List<List<String>> results = convertToStringList(rcds);
List<Order> returnList = new ArrayList<Order>();
for(List<String> row : results)
returnList.add(this.orderFactory.createFrom(row));
return returnList;
}
В вашем прикладном уровне:
public void submitOrder(OrderEntryDTO dto)
{
Order toBeSubmitted = this.orderFactory.createFrom(dto);
this.orderRepo.add(toBeSubmitted);
// do other stuff, raise events, etc
}
В вашем доменном слое unit test возможно:
Customer carl = customerRepo.findByName("Carl");
List<Product> weapons = productRepo.findAllByName("Ruger P-95 9mm");
Order weaponsForCarl = orderFactory.createWith(carl, weapons);
weaponsForCarl.place();
assertTrue(weaponsForCarl.isPlaced());
assertTrue(weaponsForCarl.hasSpecialShippingNeeds());
Где factory вписывается в следующая структура: UI > Приложение > Домен > Сервиs > Данные
Домен.
Кроме того, поскольку factory является единственным место, разрешенное для создания объекта вы не получите круговые ссылки если вы хотите создать свои объекты в ваших слоях данных и услуг?
В моем примере все зависимости распространяются сверху вниз. Я использовал Принцип инверсии зависимостей (ссылка PDF), чтобы избежать проблемы, о которой вы говорите.
Если роль класса factoryдля создания объекта, то какие выгоды имеет ли сервисный уровень?
Если у вас есть логика, которая не вписывается ни в один объект домена ИЛИ у вас есть алгоритм, который включает в себя организацию нескольких объектов домена, используйте службу. Служба будет инкапсулировать любую логику, которая не подходит ни к чему еще, и делегировать объекты домена, где она подходит.
В примере, который я написал здесь, я предполагаю, что при разработке маршрута для Ордена будут задействованы несколько доменных объектов. OrderFactory может делегировать такую услугу.
Кстати, описанная вами иерархия должна, вероятно, быть UI > App > Domain Services > Domain > Infrastructure (Data)
Я задал много вопросов и оценивать любой ответ. То, что я отсутствует примерное приложение, которое демонстрирует, как все слои в проект приводов с поддержкой домена вместе... Есть что-нибудь есть?
Применение дизайна и шаблонов Driven Driven от Jimmy Nilsson - отличный комплимент Эрику Эвансу Разработка доменов. В нем много примеров кода, хотя я не знаю, есть ли акцент на расслоении. Сложность может быть сложной и почти тема отдельно от DDD.
В книге Эванса есть очень маленький пример расслоения, который вы, возможно, захотите проверить. Layering - это шаблон предприятия, и Мартин Фаулер писал Шаблоны архитектуры корпоративных приложений, которые также могут оказаться полезными.