3 Comments

  1. 付大力

    我感觉始终有点没有想透彻,对于 service 需要冗长的代码表示的逻辑,充血模型是怎么简洁表达的?

    如果是指不同的对象抽象不同的方法来方便进行组合避免面条式代码,那我对于service进行同样的抽象进行组合会有什么问题?

    简单总结一下就是:service 模式带来了什么问题?充血模型怎么解决这些问题?为什么 service 模式没有办法解决这些问题?

    • 祁兮

      我理解你说的「service模式」,是指我文中提到的「Service+数据模型」模式,而你说的「充血模型」,对应我文中提到的「领域模型」模式。

      要选择哪种模式,主要看业务的特点。例如业务就是简单的CRUD,也就是仅仅对于数据的创建、修改、删除操作,那么Service+数据模型模式是合适的。

      文中主要讨论的是「复杂的业务逻辑」,这种情况更适合领域模型。老马在《企业应用架构模式》章节9.2.2中提到:「如果你的业务规则复杂多变,设计校验、计算、衍生,你就应该利用对象模型进行处理」。如果在对业务需求的建模过程中,发现了变化点,需要使用封装、继承、多态等面向对象特性,那么面向对象设计的领域模型的模式是更合适的。

      你说「对于 service 需要冗长的代码表示的逻辑,充血模型是怎么简洁表达的?」,如果需要使用封装、继承、多态等特性来表达业务需求,那么领域模型是很合适的。例如把Service中复杂的规则封装到专门的规则对象中,把分支使用继承、多态来建模。《企业应用架构模式》的第9章里的收入确认就是一个很好的例子,事务脚本模式的Service代码里就会有一大段分支逻辑,而领域模型模式里分支逻辑就转移到了不同的具体子类中。

      你说「对于service进行同样的抽象进行组合」,Service的确可以做抽象然后组合,只是Service是无状态的,它能力有限,需要结合有状态的实体、值对象才能发挥全部作用。例如上面提到的收入确认的例子,就是对于RecognitionStrategy做了抽象。

      另外,我的经验,不同的模式对应的建模方法也是不同的。如果采用Service+数据模型模式,那么就会站在DBA视角,使用数据库范式得到数据模型,而判断等逻辑就会自然放到Service中。如果采用领域模型模式,那应该抛开数据库范式的限制,站在纯业务视角,使用DDD的各种模式、[四色建模](https://www.infoq.cn/article/xh-four-color-modeling)或者%5B事件风暴%5D(https://en.wikipedia.org/wiki/Event_storming)等方法得到领域模型。

      希望可以解答你的疑惑。

    • Jxin

      1.相关的信息发散,容易因为信息的缺失(不知道,一时没想到)而出现代码bug。
      2.充血模型其实也代表了业务完整性,也就是刻画模块业务所需要的所有信息都在模型里面,信息在里面逻辑也就在里面。这样在写功能时就能看到有哪些信息需要关心,以及已经有哪些能力。而且你只会在充血模型最外层对外暴露能力。所以模型内部的子模型或则子功能就不会暴露出去。有些时候我们会因为一个原子操作下的子模型或者子功能单独暴露给外部,进而被错误的使用了,产生了代码错误。
      3.service模式,或则说事物脚本,它太灵活了,没这些限制。自然也控不住这些业务完整性和原子性。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据