DDD - 使用实例方法和工厂方法的不变执行

DDD - Invariant enforcement using instance methods and a factory method

我正在使用领域驱动设计原则设计一个系统。
我有一个名为 Album.
的聚合 它包含 Track 的集合。
Album 个实例是使用名为 create(props).
的工厂方法创建的 规则 1:一个 Album 必须至少包含一个 Track.
必须在创建时检查此规则(在 Album.create(props) 中)。
此外,必须有一个名为 addTrack(track: Track) 的方法,以便在创建实例后可以添加新的 Track。这意味着 addTrack(track: Track) 也必须检查规则。
如何避免这种逻辑代码重复?

好吧,如果 Album 确保它在实例化时至少有一个 Track 我不明白为什么 addTrack 会担心规则可能会被违反?您的意思是 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.');
  }
}

请注意,您也可以先改变状态,然后检查规则,乍一看这会使事情变得更简单,但这通常是一种不好的做法,因为如果处理了异常,模型可能会处于无效状态,除非模型还原更改,但这会变得更加复杂。

另请注意,如果 Track 是一个实体,最好不要让客户端代码创建 Track 来保留封装,而是传递一个 TrackInfo 值对象或类似的东西。