假设我们有作为聚合根的提升和满足作为聚合的提升的规则。
规则是扩展抽象类规则的不同规则元素的集合。
据我所知,我可以使用工厂方法,例如:
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 方法吗?其他选择?谢谢 friend 们!
Rules to satisfy a promotion as an Aggregate
好吧,一个 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
操作来做同样的事情,这可能是更适合。
如果您在 UI 行为(例如一次保存所有规则)和域(例如 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); }
});
}