DDD:Domain-Driven Design(领域驱动设计)是软件开发中的一个非常重要的设计方式, 用业务领域来做模块分割,以领域为核心思想设计框架,用设计好的领域来驱动系统实现。它被誉为面向对象开发的正确使用方式。它可以保证软件开发到后期不会变成“屎山”。软件项目复杂度随时间推移如图所示:
领域驱动设计 | Mvvm |
实体 | 实体(属性、有key的实体) |
值对象 | 实体(没有主键的实体),[ComplexType]特性用于标注值对象 |
聚合根 | 实体(包含很多属性的实体) |
DDD是什么
首先,DDD是什么呢,DDD就是一个抽象的概念,DDD只在软件的架构设计阶段出现,它就是软件模块职责的划分,比如我们需要设计一个图书馆书籍借阅系统,我们在草稿纸上画出用户模块(包含注册登录借阅还书等)、图书模块(增删改查等)、管理员模块(录入注销统计分析报表等)、日志模块等等,然后画出它们之间的交互方式等等……,恭喜,你已经设计出了非常棒的DDD架构。你也许会疑惑,领域驱动设计这么简单?对的,它就是这么简单。
DDD同时又是一个非常容易被误解的概念,同时网上90%的领域模型教程、领域驱动设计方式文章都是错误的打开方式,它们会使得这个概念更加让人摸不着头脑。就拿abp来说,它是一个基于DDD的框架,但同时,因这类DDD框架的存在,使得DDD更加让人摸不着头脑。
DDD教程很多会说到贫血模型、充血模型、建立领域知识、和领域专家深入交流啥啥啥的,这些统统不用管。下面我将详细说说DDD如何学,如何用。
结构模型
DDD如何学
然后我说说领域驱动如何学。你需要知道的是,DDD是非常混乱的概念,首先它只存在于软件设计阶段,没有DDD框架之说。DDD只是一种软件的设计方式,怎样让软件做到高内聚低耦合,怎样让项目的可维护性始终处于最佳状态。
比如abp,虽然对外宣称它是基于DDD的软件开发框架,但这么说同时也是非常容易让新手误会的点,认为学DDD就是用框架,用框架就等于用了DDD的思想。这是非常错误的想法。DDD的存在的目的是,告诉开发者,应该怎样设计软件,怎样使得项目最终不会变成屎山。
就拿abp来说,它是具体实施的框架,强行把抽象概念用在实际编码上。具体用起来,很多概念就和现有框架很相似,大多数场合下就只是换了一个名字,比如实体(Entity)就是MVC/MVVM的数据库对象模型(Model),聚合跟(AggregateRoot)就是MVVM中的ViewModel,服务(Service)就是MVC中的Controller。
abp框架就是把握住了DDD噱头,故意将软件架构设计的思考方式与软件开发的具体实施混为一谈,在不懂DDD本质的程序员中广泛传播,似乎用了这个框架就等于用了高级的DDD,实际上在架构师看来,abp和其他MVC/MVVM框架没有任何本质区别。
我们从第一步开始,给你一个软件项目,你先不写代码,先分析分析,这个软件需要提供哪些功能,按照功能类型划分为多个模块,然后再独立出外部模块与内部模块,比如用户模块维护用户数据,始终与用户做交互,那么就是对外模块;日志模块的任何数据都不展示给用户,也不直接与用户做交互,那么就是对内模块。模块划分完成后,按照使用者的思维方式来设计接口,比如用户模块有注册接口、登录接口、图书模块有查询借阅等等接口等等……,这样就完成了非常出色的DDD领域驱动设计。
DDD如何用
接下来就说说如何用。有了上面的领域驱动设计文档,程序猿就开始开发软件了,选择自己喜欢的MVVM框架,主流的数据库等等……
但通常情况下,软件开发的一团糟。比如你们可能也会遇到过这样的情况:设计软件各模块、各架构设计文档里写的井井有条,头头是道,写软件时就写成了一坨屎,有个几年的屎山就完全没法继续开发,只能重构了。究其原因,不是是说DDD只能用DDD框架来开发,比如abp,根本原因在于DDD落地方式不对。通常软件最开始按照设计文档开发,写着写着就放飞自我了,最终成品中几乎看不出模块的划分;或者是整个软件严格按照设计文档开发出了成品,后面招新人加入项目后,新人为了完成任务放飞自我,这儿添一点那儿改一点,最终就脱离出了最开始的设计。
那么问题点出在哪呢?看过网上的其他的DDD的文章后,就会看到很多这样的概念:领域、值对象、界限上下文、聚合、聚合跟、DTO等等。那么我就告诉你,这些东西存在的目的就是,限制你的开发方式,使得你无法放飞自我,只能按照这种开发方式来开发软件,最终的结果就是,不论软件项目组经过多少人的加入及退出,只要没人故意捣乱,那么这个软件始终就是最科学的组织方式,永远不会变成屎山。
DDD的正确使用方式当然不是用DDD框架。正确使用方式是,按照DDD设计思路的约束,逻辑代码不要放到数据层,A模块的代码不要放到B模块层等等……理解了这一点,那么你就懂得了DDD的正确使用方式了。