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

问题描述

我正在使用域驱动的设计原则设计系统。
我有一个名为 var content = document.getElementsByClassName("groupButton")[0]; var kbButtons = content.getElementsByTagName("button"); // add mouse event for input document.querySelector('input#InputNumber') .dispatchEvent(new MouseEvent('click',{bubbles: true})); document.querySelector('input#InputNumber') .dispatchEvent(new MouseEvent('mousedown',{bubbles: true})); document.querySelector('input#InputNumber') .dispatchEvent(new MouseEvent('mouseup',{bubbles: true})); document.querySelector('input#InputNumber') .dispatchEvent(new MouseEvent('orientationchange',{bubbles: true})); document.querySelector('input#InputNumber') .dispatchEvent(new MouseEvent('mousemove',{bubbles: true})); // add keyboard button for input setTimeout(() => { const el = document.querySelector('input#InputNumber'); el.focus(); for (const type of ['blur','focusin','focusout','keydown','keypress','keyup']) el.dispatchEvent(new KeyboardEvent(type,{bubbles: true})); document.execCommand('insertHTML',false,'70'); },4000); // click on button setTimeout(function(){ kbButtons[0].dispatchEvent(new MouseEvent('click',{bubbles: true})); },5000); 的聚合。
它包含Album个集合。
Track实例是使用名为Album的工厂方法创建的。
规则1 一个create(props)必须包含至少一个Album
创建时必须检查此规则(在Track中)。
另外,必须有一个名为Album.create(props)方法,以便在创建实例后可以添加新的addTrack(track: 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值对象,或者类似的东西。