DDDA — Агрегированный корень, какой способ создания новых дочерних агрегатных элементов с разными типами? Заводской метод?

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

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

class Promotion (
PromotionIdentity $identity,
string $name,
){
$this->identity = $identity;
$this->name = $name;
$this->rules = new RuleCollection();
}

public function addRule(
RuleIdentity $ruleIdentity,
RuleType $ruleType,
array $configuration
) {
if (RuleType::EMAIL_LIST === $ruleType->value()) {
$makeRule = new EmailListRule($ruleIdentity, $configuration);
$this->rules->add($makeRule);
}

if (RuleType::MIN_ARTICLES === $ruleType->value()) {
$makeRule = new MinimumArticlesRule($ruleIdentity, $configuration);
$this->rules->add($makeRule);
}

... and so on, for example 15 rules
}

Я думаю, что это может сильно возрасти, я вижу запах кода здесь.

Можно ли сохранить эту логику создания правил в агрегатном корне? Можем ли мы перенести эту ответственность за создание правил на службу приложений на фабрике и передать построенное правило в метод addRule? Другие опции? Спасибо, друзья!

2

Решение

Правила, чтобы удовлетворить продвижение в качестве Агрегата

Ну, AR не может содержать экземпляры других AR, поэтому Rule не может быть AR здесь. Кроме того, на первый взгляд и не зная вашего домена, я вижу очень мало причин для Rule даже быть сущностью с точки зрения домена (это может быть с точки зрения хранения). не удалось Rule просто быть объектом значения, полностью замененным, если необходимо изменить?

//Application service
changePromotionRules(String promotionId, Set<Map<String, String>> rulesConfig) {
Set<Rule> rules = ruleFactory.rulesFromConfig(rulesConfig);
Promotion promotion = promotionRepository.promotionOfId(new PromotionIdentity(promotionId));
promotion.changeRules(rules);
}

//Promotion AR
changeRules(Set<Rule> rules) {
validateRules(rules);
this.rules = rules;
}

Приведенный выше пример предполагает CRUD-подобное поведение, при котором все правила заменяются одновременно, но вы можете сделать то же самое с более детальным addRule/removeRule операции, которые могут быть более подходящими.

Если у вас есть разъединение между поведением пользовательского интерфейса (например, все правила сохранены сразу) и доменом (например, addRule / removeRule), то вы можете адаптировать это на уровне службы приложений.

Например.

//Application service
changePromotionRules(String promotionId, Set<Map<String, String>> rulesConfig) {
Set<Rule> rules = ruleFactory.rulesFromConfig(rulesConfig);
Promotion promotion = promotionRepository.promotionOfId(new PromotionIdentity(promotionId));
withSetDiffBetween(rules, promotion.rules(), new SetDiffHandler<Rule>() {
withAdd(Rule rule) { promotion.addRule(rule); }
withRemove(Rule rule) { promotion.removeRule(rule); }
});
}
-1

Другие решения

Других решений пока нет …