浅谈应用架构之领域驱动设计

一、架构是什么

架构广义的说就是组合构造,有产品架构、有系统架构等,好的架构能够使产品、系统更好地呈现,更好地迭代与维护。好的架构是演进出来的,好的代码是重构出来的。

我们经常听到中台、平台、系统、应用等名词,它们之前有何关系?

1)应用:是最小粒度的,用于实现业务系统功能的。比如现在流行微服务,实现一个业务系统的应用一般都包括:web应用、service应用。

2)系统:这里说的系统都是业务系统,一般一个业务系统都至少是一个完整的商业产品。比如寻源系统、招投标系统等。

3)平台:由多个业务系统组合而成,平台的能力要比单个业务系统的能力丰富,平台提供某个领域较完整的商业能力。比如采购平台,它由寻源、招投标等业务系统组合而成。平台是功能复用,一般只支持单一场景,比如大企业采购平台,只支持大企业采购的场景。

4)中台:在平台的基础上,通过扩展点支持多场景,是业务复用。采购中台能支持大企业采购、中小企业采购、个人采购等。

每个层次都有自己的架构(平台架构、业务系统架构、应用架构),同时关注东西的也不一样。平台架构、系统架构更多的是关注:职责边界划分、部署方式、新技术(上云、微服务等)的应用。而应用架构更多的是关注应用本身的分层、设计方式。比如现在比较流行的有分层架构、DDD领域驱动设计,应用架构将是本文要讲的重点。

二、职责边界划分

系统边界的划分对于业务架构至关重要,总原则就是:按照职责划分。当某个职责不知道划分到哪个域时,可以分配一个中介领域。

通过分析用例,同领域的模型一定是交互很多的,跨域的模型一定是很少交互的,如果发现跨域的模型交互很多,那很可能就是领域职责划分有问题

三、领域驱动设计及其核心构件

领域驱动设计介绍

什么是领域驱动?领域驱动设计是一种指导系统设计与开发的思想,需要我们关注业务领域知识,理解领域知识,面向领域,面向模型设计。而不是面向技术、面向数据做设计。通过与业务领域专家不断交流,深入理解领域知识,不断迭代系统设计,然后呈现出更好的领域模型。有价值的领域模型一定不是立即就能出现的,需要深入理解领域知识后得出的。

为什么需要领域设计?软件系统的复杂性往往不是来自于技术实现本身,而是来源于业务本身,复杂的业务流程与演进。

领域模型需要技术与业务专家都能理解,如果领域专家都无法理解领域模型,那模型一定是设计得有问题的。领域建模不仅仅是建实体,还包括值对象、领域服务、实现模式等。设计与实现一定是绑定的,设计与实现不要分开。看到领域设计就应该知道系统实现的模式,不然越往后,实现的人不理解领域设计的意图,系统实现越偏离领域设计,领域模型数据完整性也难以保证,整个领域设计就没意义了。

领域模型不仅是领域核心概念的抽象,也要能够指导软件开发实现。面向对象设计是大多数领域建模所使用的建模范式。

领域核心构件包括了领域对象与领域对象生命周期的管理,领域对象包括:实体、值对象、领域服务。领域对象生命周期的管理包括:工厂、Repository、聚合。领域对象与领域对象生命周期管理都属于是领域层的核心资产

1)实体:实体在业务交互中是可以独立存在且有意义的,需要唯一标志的存在,且唯一标志是有实际业务含义的。比如网上购物,寄送的包裹虽然内容一样,但就是两个不一样的包裹。

2)值对象:一般只关心内容,不关心不需要唯一标志,通过聚合作为实体的附加属性。比如当人用画笔画画时,只关心画笔的颜色、粗细等特征,而不关系具体是哪根画笔。总之,在所处场景下,如果内容完全一样时可以认为是同一个对象,那就是值对象,反之就是实体。

3)领域服务:有些时候领域中会有些特殊的操作,它不属于任何实体、值对象,这时就可以使用领域服务,此时领域服务是表示领域概念的最好方式,领域服务的参数与返回值都应该是领域内的模型,服务应该是无状态的。

4)Aggregation:聚合就是以某个实体为聚合根,聚合其他值对象作为属性。聚合根应该是修改/查询的最小单元,必须以聚合根为单位进行修改/查询。聚合一般指实体与值对象之间的关系,关联一般指实体与实体之间的关系。

5)Factory:工厂的主要职责就是创建对象与重建对象(将从存储介质中查询出的数据重建成领域对象)。复杂对象的创建是属于领域层的事情,不一定要通过对象本身实现,可以通过工厂创建。工厂一般用于创建复杂的、需要泛化的对象类型,简单的模型对象可以直接通过构造函数创建。

6)Repository:主要职责就是对象与存储之间的互相转化,可以对类型进行适当抽象,没必要每个模型都对应一个repository。

DDD应用架构分层最佳实践

1)应用架构分层

2)商业能力

通过不同领域能力(可能跨组织、跨部门)的组装,可以合成一定的商业能力,通过配置+定制快速接入,加快业务迭代速速

四、领域驱动设计指导思想

1)在领域层内,必须使用本领域的概念进行业务逻辑的表达,所有核心的领域逻辑,都是基于领域构件实现的。而不应该直接依赖外部的实现,也不对外暴露无关的接口,领域层应该是重点保护对象。

2)repository层一般不参与事务控制的。

3)要始终关注领域模型的设计与职责,坚持面向对象设计的SOLID原则,不要将领域对象只当作数据容器来使用。

4)尽量通过聚合根遍历数据库,查找关联的值对象,而不是直接遍历值对象,如果确实需要跳过实体直接遍历值对象,那要考虑模型是否设计不合理,该值对象是否有必要设计成实体。

5)整个设计应该是低耦合、高内聚的,包括包的设计与划分。

6)软件设计要时刻与复杂性做斗争,把复杂的设计留给真正需要的地方。领域建模从简化关联关系开始。模型之间的关联尽量降低复杂度,能1对多关联的不要设计成多对多关联,能1对1关联的不要设计成1对多,能单向关联的不要双向关联。当无法简化时,考虑下是否可以添加一些适当的符合实际的条件,这样可以降低关联的复杂度。关联越复杂,数据的一致性就越难保证,系统的稳定性就越难保证,系统实现的复杂度就会提高。如果能够对关联关系适当简化,也体现出了对领域知识的深入理解。被约束的关联可以传达更多知识,也更实用,仔细简化并约束模型的关联是通往领域驱动设计的必经之路

7)根据实体、值对象按需设计数据存储结构,一般1对1的领域模型相关信息,可以放在一张数据表中存储,除非大字段分开到不同的表。1对多的数据只能分开到不同的表中。数据库设计应该坚持:让我们的数据查询与更新更高效,更安全地保障数据的完整性。

8)除了通过聚合根访问聚合内的关联对象,不允许通过其他任何方式访问聚合内其他对象

猜你喜欢

转载自blog.csdn.net/qq_42672856/article/details/116572922