我在DDD日学到了什么?

这是一篇领域驱动设计Domain-Driven Design的简要总结:
What I have learned at DDD Day | Web Builder Zone

DDD是致力于复杂软件如银行,保险,运输等系统的软件开发,DDD日是由.NET成员组织和参加的一个聚会,参加人员大多是企业领域软件工作者。

DDD是一套方法或知识模式,用于协同开发人员和领域专家的合作,作者虽然举办了是一个PHP talk,但是他已经从其他talks比如Greg Young, Andrea Saltarello, Alberto Brandolini学到很多。

当初DDD一书写于2004年,而那时静态 引人注目的面向对象语言是一件非常Cool的事情,那时没有NoSQL解决方案或其他关系数据库替代方案。

作者认为虽然这本书大部分概念和模式都是依然有效的,但是有个问题就是没有强调一个强大的概念:Context mapping,上下文映射,或者场景映射。

作者对DDD领域其他概念进行了阐述,如CQRS和ES(Event Sourcing)等等,这些在本站都有详细讨论。

作者也学到了如何让DBA发疯的一些知识:不应该将自己的数据库作为一个整合点进行共享,要明确应用程序是一种有界的上下文,之间协调需要认真考虑,简单的共享数据库将限制你的领域演进改变,因为如果DBA总是检查你的数据表结构情况下,你是无奈的弱者。

重复数据并一定坏,除非类有重复的行为,经典案例来自Brandolini 的数据重复如果其有不同的生命周期实际是好的,这样就可以进行分离,订单中的客户地址能够被复制,因为如果客户改变了账单或运输单地址,老的订单就不应该也改变到新的地址。

作者学到了DDD和验证,目前互联网上讨论最热闹的是不变量和上下文验证( invariants and context validation.)的微弱区别。

不变量是一种验证,应该总是被执行,无论活动的对象是否真正被执行,字段需要一个正式的名称就是一个不变量。

因为不变量,验证总是非常有效,验证在对象构建时就能够进行,或者在状态改变时进行,这些将能始终保持一个有效的聚合。

上下文验证context validation是另外一种验证,可以在一些特殊活动之前或之后继续,比如访问一个非过期的金卡信用卡的折扣只有在下面场景才可能进行:对折扣感兴趣时;根据需要进行验证能够更好地配合为基于上下文的规则: 外部的对象执行存在于领域对象中的方法内验证。

双倍的Dispatch能够被放在外部服务中使用,可以使用一个工厂方法等,这个解决方案能够避免将私有字段从领域对象中暴露出来,也避免将这些字段传递给有校验功能的方法

最后,作者在认为Context Mapping上需要强调更多概念,这也是作者写该文的目的:

上下文映射有一系列模式,能够确保应用系统和外部应用之间能够协同,一个外部应用是指需要整合的系统,如传统系统 Web服务API或鉴权机制,来自政府法律部门的数据源等等。

映射需要理解各种场景(上下文),这些都是有着不同的领域语言或概念,更重要的是映射要创建一种他们之间的关系,通常需要三个模型用于协同,两个有界的上下文加一个用于联系的模型。

每次协同都有上下游关系要处理,两个模型中的一个都有权利改变另外一个,关系案例如下:
1.发布的语言,外部领域语言和API需要在这些模型间存在,文档和BUG修复外包给一些标准的组织机构。

2.防腐层:使用Facade或Adapte模式消耗很大但是很有用,将内外模型之间的转换隐藏起来,上流模型如果改变,防腐层能够防止这些频繁修改影响面扩散。

3.消费者/提供者方式:两个模型中一个是真正的源对象,而另外一个不断地去适应配合他。(banq注:类似代理模式)

在验证场景下,你就不能只在你的模型内实现DDD了,因为你的模型可能来自下游的两个其他应用,这时,必须创建一个上下文映射Context Map,你就能在正确地方发现你的核心领域,并且屏蔽来自其他系统的坏味道。