Oop 使用实例方法和工厂方法的DDD不变强制
我正在使用领域驱动的设计原则设计一个系统。Oop 使用实例方法和工厂方法的DDD不变强制,oop,design-patterns,domain-driven-design,factory-pattern,aggregateroot,Oop,Design Patterns,Domain Driven Design,Factory Pattern,Aggregateroot,我正在使用领域驱动的设计原则设计一个系统。 我有一个名为相册的集合 它包含一组曲目s. Album实例是使用名为create(props)的工厂方法创建的 规则1:专辑必须至少包含一首曲目 创建时必须检查此规则(在相册中创建(道具))。 此外,必须有一个名为addTrack(track:track)的方法,以便在创建实例后可以添加新的track。这意味着addTrack(track:track)也必须检查规则。 如何避免这种逻辑代码重复?好吧,如果相册在实例化时确保它至少有一个音轨,我不明白为
我有一个名为
相册的集合
它包含一组曲目
s.
Album
实例是使用名为create(props)
的工厂方法创建的
规则1:专辑
必须至少包含一首曲目
创建时必须检查此规则(在相册中创建(道具)
)。
此外,必须有一个名为addTrack(track:track)
的方法,以便在创建实例后可以添加新的track
。这意味着addTrack(track:track)
也必须检查规则。
如何避免这种逻辑代码重复?
好吧,如果相册
在实例化时确保它至少有一个音轨
,我不明白为什么添加音轨
会担心违反规则?您的意思可能是removeTrack
在这种情况下,你可以做如下简单的事情:
class Album {
constructor(tracks) {
this._tracks = [];
this._assertWillHaveOneTrack(tracks.length);
//add tracks
}
removeTrack(trackId) {
this._assertWillHaveOneTrack(-1);
//remove track
}
_assertWillHaveOneTrack(change) {
if (this._tracks.length + change <= 0) throw new Error('Album must have a minimum of one track.');
}
}
类相册{
建造商(轨道){
这个。_tracks=[];
该资产将有一个轨道(轨道长度);
//添加曲目
}
removeTrack(trackId){
此._资产将有一个机架(-1);
//移除轨道
}
_资产将有一个机架(更改){
如果(this._tracks.length+change,我明白了。关于不让客户端代码创建曲目,您建议让客户端代码创建值对象,而不是像track这样的实体?为什么?我也可以在工厂内创建值对象吗?@plalx此外,像Album、track、User等聚合通常会更新其所有属性(几乎全部)。我应该创建一个实例方法来设置每一个吗?还是只使用一个简单的setter?@plalx原因是,如果客户端可以在相册
的上下文之外修改曲目
,那么不变量就无法得到保护。例如,如果不能有两个同名曲目,客户端可能会违反规则:track1=new Track('foo');album=new album(track1);album.addTrack(new Track('track2'));track1.changeName('track2');//违反规则
好吧,DDD战术模式可能会妨碍CRUD。如果您只做CRUD,那么就不希望有一个非常有趣且面向行为的模型。如果业务流程是“更新”/“更改跟踪信息”,然后您可以执行album.changeTrackInfo(trackId,newTrackInfo)
。请注意,如果您不关心特定曲目的生命周期,那么从模型的角度来看,曲目
也可能是一个值对象。明白了。我认为曲目
是一个实体,因为我将存储用户收听的每个曲目的数据。非常感谢@plalx。我想我现在就知道了。