Предположим, что у нас есть Акция в качестве совокупного корня и правила для выполнения Акции в качестве совокупного.
Правила представляют собой набор различных элементов правил, который расширяет класс абстрактных правил.
Как я узнал, я могу использовать фабричный метод, пример:
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? Другие опции? Спасибо, друзья!
Правила, чтобы удовлетворить продвижение в качестве Агрегата
Ну, 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); }
});
}
Других решений пока нет …