如何避免聚集内部集合中的getter
本文关键字:getter 集合 内部 何避免 聚集 | 更新日期: 2023-09-27 18:21:35
我正试图遵循"在类中使用getter/setter是邪恶的"的建议。所以,假设我有一个具有以下签名的聚合类Invoice
:
public class Invoice{
ISet<Line> _lines;
public void ChangeLineAmount(int LineId, double newAmount){
//Your answer here
}
}
如果Line
类没有getter,我如何找到更改的具体行?
-
在"vanilla"DDD中,建议避免使用直接的setter(或可变集合的getter),而是将域操作显式。尽可能使用意图揭示、无处不在的语言兼容、不变的强制行为(方法)来变异您的实体。然而,在这种方法中,实体也是从中读取数据的地方,它们必须向读者公开它们的状态,所以我看不出没有getter怎么办。
-
DDD的CQRS(+ES)风格将有一个读取模型,在该模型中,您显然可以使用getter访问您想要的一切,以及只能通过命令更改其状态的聚合。由于所有读取都是通过辅助读取模型对象完成的,所有写入都是通过命令完成的,因此在面向外部的聚合根上不需要getter或setter,但根本身必须能够更改自己聚合内的实体,这有时需要setter。
在任何情况下,事情都不会像"在类中使用getter/setter是邪恶的"这样简单。
在DDD问题中,短语"在类中使用getters/ssetters是邪恶的"背后的原因是getters和setters通常不代表您的UL(普遍存在的语言),并导致贫血的实体。但如果在您的UL中有类似"我需要那个行的数量"的内容,那么您可以创建getter,但根据UL命名,如:invoice.lineAmount(lineId)
。
在方法内部,您可以简单地访问CharlesNRice已经回答的属性。如果您觉得在读取/设置行时需要任何特殊处理,那么您可以创建私有getter来在域逻辑方法中使用它。
更新:
首先需要getter和setter,因为在项目的后期,您可能希望在设置/获取属性之前添加一些额外的验证/转换,如果没有它,您将不得不找到正在访问属性的每一段代码并对其进行更改。使用getter/setter,您可以在一个位置访问属性,因此可以在一处更改代码-更容易维护。但由于在DDD中,您必须只使用域逻辑方法,所以您不能直接访问给定实体之外的任何地方的属性,因此也不必使用getter和setter。像invoice.lineAmount(lineId)
这样的域方法实际上和getter一样工作,但与UL配合使用,所以它们是可以的。如果你看到你在实体类中的几个地方访问属性,你会考虑创建真正的getters/ssetter供内部使用。
_line只是一个字段,如果它没有getter或setter的话。如果你添加它们,那么它就是一个属性。为了得到这条线,你会把它当作一处房产来使用。
public class Invoice{
ISet<Line> _lines;
public void ChangeLineAmount(int LineId, double newAmount)
{
var line = _lines.FirstOrDefault(l=>l.LineId == LineId);
if (line != null)
{
line.Amount = newAmount;
}
}
}
如果"在你的课上使用getters/ssetters是邪恶的",我认为这是个人观点。我个人没有这种感觉。