写点什么

DDD 领域驱动设计在团队中推广和实施

发布于: 2 小时前
DDD领域驱动设计在团队中推广和实施

什么样的代码是优秀的代码

大佬眼中的好代码

Bjarne Stroustrup——C++之父: 

我喜欢优雅、高效的代码: 

  • 逻辑应该是清晰的,bug 难以隐藏;

  • 依赖最少,易于维护;

  • 错误处理完全根据一个明确的策略;

  • 性能接近最佳化,避免代码混乱和无原则的优化;

  • 整洁的代码只做一件事。


Grady Booch——《面向对象分析与设计》作者: 

  • 整洁的代码是简单、直接的;

  • 整洁的代码,读起来像是一篇写得很好的散文;

  • 整洁的代码永远不会掩盖设计者的意图,而是具有少量的抽象和清晰的控制行。


Dave Thomas——OTI 公司创始人,Eclipse 战略教父: 

  • 整洁的代码可以被除了原作者之外的其他开发者阅读和改善;

  • 具备单元测试和验收测试;

  • 有一个有意义的名字;

  • 使用一种方式来做一件事情;

  • 最少的依赖,并明确定义;

  • 提供了一个清晰的、最小的 API;

  • 应该根据语言特性,在代码中单独显示必要的信息,而不是所有的信息。


Michael Feathers——《修改代码的艺术》作者: 

  • 整洁的代码看起来总是像很在乎代码质量的人写的;

  • 没有明显的需要改善的地方;

  • 代码的作者似乎考虑到了所有的事情。


Ward Cunningham——Wiki 和 Fit 创始人,极限编程联合创始人,Smalltalk 和面向对象的思想领袖: 

  • 当你读代码时,你发现每个程序都如你期待的那样

  • 你可以称之为漂亮的代码

  • 代码完美展现了该编程语言的设计目的


我眼中的好代码

  1. 代码是简单、直接,已最合适的方式解决问题

  2. 在设计上满足面向对象设计的六大原则

  3. 单一职责原则 (SRP)

    开闭原则 (OCP)

    里氏替换原则 (LSP)

    依赖倒置原则 (DIP)

    接口隔离原则 (ISP)

    迪米特原则 (LOD)

  4. 在功能上应该是易于维护的

  5. 代码的可读性,在编码规范上阅读好的代码就如阅读白话文一样,而非文言文,通过代码就能还原业务逻辑和场景

  6. 代码的扩展性,当需要添加新的需求功能点,需要改动的点最少

忌讳

  • 炫技:

小时候写作文,老师会叫我们一些写作技巧

记叙顺序:顺叙,倒叙,插叙

表现手法: 象征,对比,烘托,设置悬念,抑扬顿挫,托物言志

修辞手法:比喻,拟人,夸张,排比,对偶

代码是不是也需要符合这样的标准才是好的代码,这在行话里面叫炫技

  • 过度设计:

一个简单的功能,面向过程的方式就可以搞定的,或者他的生命周期就是 5 天,但是就是硬是设计出了需要维护一年的架势,也许在你还没有离开的时候,项目已经黄了,或者就是一个 demo 程序,这种就是过度设计

DDD 中常见术语

贫血和充血模型

贫血模型:

我们在定义一些领域对象,或者通俗的讲其实就是一些表对应的实体对象(entity)只有属性及对应的转换,不包含任何业务逻辑,不关心对象持久化,只是用来做为数据对象的承载和传递的介质

。这种方式对象的状态和行为分离,不能直观的描述领域对象。通俗的讲就是没有一个全局视野能描述一个领域整体。

充血模型:

这种模型下领域对象作用此领域相关行为,包含此领域相关的业务逻辑。同时包含持久化操作。对象的自洽程度很高,表达能力较强。可复用性较高

集合根

在 UML 类关系中有依赖、关联、聚合、组合、泛化关系,聚合关系使用实线加空心菱形表示。聚合用来表示集体与个体之间的关联关系,如班级和学生,订单详情和订单。他们的具有相同的生命周期,同生同灭。订单详情依赖于订单,订单没有了那么订单详情就没有存在的意义,同样班级没有了,班级里面的学生也同样没有存在的意义。

在 DDD 中,实体和值对象是很基础的领域对象。实体一般对应业务对象,它具有业务属性和业务行为;而值对象主要是属性集合,对实体的状态和特征进行描述。但实体和值对象都只是个体化的对象,它们的行为表现出来的是个体的能力。

领域模型内的实体和值对象就好比个体,而能让实体和值对象协同工作的组织就是聚合,它用来确保这些领域对象在实现共同的业务逻辑时,能保证数据的一致性。


六边形架构


六边形架构


所谓的六边形架构,其实就是在我们中间的领域及业务层外调用基础设施层的时候,会增加一些适配器。这样业务层不依赖底层设施的改变。具体的实施细节

  1. 业务层不强依赖基础设施层的任意一个框架组件

  2. 业务层不直接依赖外部的接口服务,而是依赖适配器服务,通过适配器调用外部的服务

  3. 业务层依赖的一些注解需要满足 JSR 标准

防污层(ACL)

Eric Evans:When systems based on different models are combined, the need for the new system to adapt to the semantics of the other system can lead to a corruption of the new system’s own. The underlying concept is pretty clear. When we need to "talk" with other system, data repository or legacy code (even "ours" legacy code) we should prevent our model from other "foreign models".(网页翻译:当基于不同模型的系统组合在一起时,新系统需要适应其他系统的语义,这可能导致新系统本身的腐败。 基本概念非常清楚。当我们需要与其他系统、数据存储库或旧代码(甚至"我们的"旧代码)进行"对话"时,我们应该阻止我们的模型与其他"外部模型"进行对话。)

对应到设计模式上,一般我们用适配器,门面模式,去做不同模块之间的适配,防止单一模块的边界上下文不被其他的模块所侵蚀。

值对象

值对象用于描述领域的某个方面而本身没有概念的对象称为值对象,值对象被实例化之后用来表示一些设计元素,对于这些设计元素,我们只关心它们是什么,不关心它是谁。

  • 值对象是不可变对象(Immutable)

  • 起描述性作用

  • 通过属性值判断相等性

  • 实现 equals()方法

  • 即时创建,用完销毁

  • 如 Address/Color


我们以电商为例,通常电商用户自己可以配置一个或多个收货地址,同时可以对用户收货地址进行修改、删除,像这个用户收货地址就是实体;而当用户下订单时从用户收货地址里选取一个地址作为订单送货地址,这个订单的送货地址就应该是个值对象,因为订单送货地址是随着订单创建后就固定下来了,它不会因为用户修改了用户收货地址而导致订单的送货地址发生变化,所以订单送货地址里应该保存的是地址的完整信息而非用户收货地址的 Id

整洁代码架构

整洁代码架构源自于《Clean Architecture》,作者是一位从事软件行业几十年的架构大师,参与开发了各种不同类型的软件,在职业生涯中发现了一个规律:那就是,尽管几十年来硬件、编程语言、编程范式发生了翻天覆地的变化,但架构规则并没有发生变化



整洁代码架构的核心原则是代码的依赖关系只能从外向内。整洁架构的每一圈层代表软件系统的不同部分。越往里抽象程度越高,外层为机制,内层为对应的策略


DDD 的业务实施

DDD 提供的是方法论,不是非黑即白的公式,究竟应该是实体还是值对象应该根据具体的业务场景来定。

我们在项目实施过程中需要在 DDD 实践方式和设计模式上达成必要的共识来推进 DDD 落地。

  1. 基于领域建模的方式做前期的业务分析和设计,构建出业务的 ER 关系图,业务模块限界上下文

  • 事件风暴

事件风暴是一种业务建模方式,先整理出状态,再抽象出事件,最后进行分解,从状态的变化中抽象出模块和模块之间的事件交互关系,展开头脑风暴,构建出业务模块之间的依赖及 ER 关系图

  • 四色原型法

  • 时标型(Moment-Interval)对象

  • PPT(Party/Place/Thing)对象

  • 角色(Role)对象

  • 描述(Description)对象

寻找要追溯的事件,谁,在什么时候,干了什么事

按时间发展的先后顺序,用红色所表示的起到“追溯单据”作用的“时标”概念

在“时标”对象周围的用绿色所表示的“人、地、物”概念

用黄色所表示的“角色”概念

用蓝色所表示的“描述”概念

  1. 系统工程设计上需要遵循六边形架构对系统模块做好分层及调用关系限制以及边界划分,在开发过程中要遵循整洁代码架构及优秀代码的方式进行实际的代码编程

发布于: 2 小时前阅读数: 6
用户头像

还未添加个人签名 2018.05.03 加入

还未添加个人简介

评论

发布
暂无评论
DDD领域驱动设计在团队中推广和实施