状态资源分类和《领域驱动设计》

柏舟   新冠4年 05-25

最近读了《领域驱动设计》对软件编写的状态有了更深刻的认识。软件的状态可以分为以下几类:

标准的耦合

这个标准是模糊的,根据《领域驱动设计》,领域的数据对象分为实体(entity)和值对象(value object)。对于实体的状态存储,常见的做法是通过数据库的锁和原子操作进行管理,这表面上看是基础设施的状态问题,实际上是将领域的状态问题转移到了基础设施上。一旦软件引入redis缓存等其它存储,同一个实体可能多次存储,这时就会发现实体本身的特性决定了它的存储方式,存储的复杂性大致分为接口、数据结构和基础设施三个方面:

领域驱动设计

《领域驱动设计》(DDD)这本书主要讨论了领域对象的状态问题和复杂度问题。如果一个程序完全由没有状态的函数构成,只需要将输入输出抽象成管道,实现中间过程就可以了。但问题是系统内部存在实体对象,这个对象存在以下特征:

架构模型

由于实体对象的特点,DDD将对象分为实体和值对象,在这个基础上建立了service, repository, aggregate, factory.

架构本身并不是很重要,对于MVC来说,MC是领域层,Model对应实体和值对象,Controller对应剩余的抽象;而View是应用层,MVC与DDD没有什么区别,只是DDD将业务规则区分得更细,更适合复杂的系统。DDD的核心观点是领域相关的逻辑封装到领域层中,而不要泄露到应用层。

为了达到这个目标,他做了以下几个方面的努力:

领域建模语言

团队内部使用领域语言。目的是:

这本质上是一个实践与知识的循环,通过领域模型和语言固化下来。因为代码和知识本身就是一种资产,需要人不断的维护,一个好的模型文档能够大幅降低新人的学习成本和后续开发难度,从而降低项目的管理成本。

控制复杂度

总结

相比于MVC,DDD通过将领域对象(Aggregate)的生命周期与操作区分,确实可以处理更复杂的系统。但是假如实体之间存在规则,就需要在实体和实体之间再封装Aggregate,这种递归的结构在书中并没有得到好的解决,在实践中,也很容易泄漏到应用层中。

领域驱动设计非常强调代码实现与领域模型一致,并且通过抽象封装管理领域的复杂性。