大型系统的支撑
由于我家里到公司路程比较远,我就喜欢利用路上的时间看看风景、看看书、走走神什么的,有一天看书看累了,打算合上书(不特殊说明的情况下,书指的是DDD)走会儿神的时候,突然发现译者在背面书皮上写了一段话:“Eric Evans强调要聚焦于软件的核心领域,以它来驱动开发。软件能够在市场上卖出去,是因为它封装了别的软件所没有的一些核心领域知识,这就是核心竞争力,是利润所在的地方,也是最值得下工夫的地方,再难也不能逃避。”,这句话对我触动很大,把很多问题一下子连接在了一起。其实很多书上都或多或少提到过这个意思,比如有的书说再做需求前首先要定义系统要解决的问题。这是软件的核心竞争力,是要辅助客户达到的目的,比如客户的战略计划,是所有需求的核心,为了这个核心甚至可以一定程度上引导客户改变需求。
大家都知道,需求是开发的依据,定义了系统要解决的真正问题或者说掌握了描述问题的核心模型之后就是不断与领域专家交流---也就是书上说的知识积累和挖掘深层模型的过程,在这个过程中将不断丰富出一个贯穿于整个开发周期始终的框架---通用语言(Ubiquitous Language),这是协调整个开发团队的依据,清楚描述问题指导团队成员正确理解和讨论问题的基础,举个例子:工作时间比较长的朋友,或多或少会遇到过一个情况,工资问题,在有些公司工资是指基础工资加上绩效工资的和,而在另外一些公司,它仅仅指的是基础工资。如果我们在开发系统的时候使用到了“工资”这个词的时候,虽然使用的是同样的词汇,但极有可能理解是不同的,最终导致某个时间点,问题突然爆发出来,难以解决,而这种情况,我相信做项目的大家,都或多或少的遇到过类似情况。所以,形成并不断丰富一种UL是软件顺利完成的重要支撑,而且从需求到上线的所有阶段,都可能在不断完善它,甚至在上线之后的比如维护过程中也有可能还在完善,而且很多项目还会有二期,另外就我经历过的多数项目,真正能为公司带来最大利益的不是项目本身,而是项目的知识积累而形成的产品或对现有产品的丰富。
UL是需求、建模和模型迭代的依据,它描述了问题的概念,它必须是对业务概念的真实描述,是客户、领域专家、程序员都能理解的。如果UL的词语理解或使用上有了矛盾,就可以对这个矛盾点进行更深入的需求分析。有了最初的UL,就可以以它来表述概念,从而抽象出模型,UL的变化一般意味模型的变化,模型更合理,参照模型开发的软件也就更合理、前后一致。这里有个问题,之前群里一次讨论我写过个随笔---架构师要不要写代码,架构师不一定要写代码,但需要辅助程序员正确使用模型,Hands-On Modeler(建模人员参与开发)模式说的就是这个,一次就设计的很贴切的模型很难,设计好了之后使用中还会有各种各样的问题,很多一目了然的东西很有可能隐藏着不同的含义(比如上面的“工资”),设计无处不在,如果建模的人不能近距离配合程序员工作,有非常大的可能模型最后不能完整正确的表达。
三层大家都熟,笼统的说经典的DDD分层把业务层分离成为了应用层和领域层,核心的业务规则,业务概念的定义、模型包含在领域层中;应用层负责对业务的执行,协调领域对象和领域服务,相当于对三层中的业务层进行了定义与具体执行的分离。分离后,关注点更集中,对业务的表达也更纯粹。下面是书上的基本分层图:
图中UI可以直接访问领域层,领域层是业务软件的核心,除了定义规则、概念外还反应业务情况的状态,这一点联系后面的聚合的创建和重建模式就容易理解了,不过DDD更多的是思维导向的指引,对当前业务状态纯粹的查询其实是完全可以独立于领域层之外的,所以现在多数DDD的框架会采取CQRS的方式来做,因为读和写的逻辑分离即在结构上有性能方面的好处,又能更好的辅助DDD落地,这点如果没忘后面会细说的,对DDD理解的越多会发现这种方式越合适。
另外值得一提的点是,做软件应该更合理的完成软件。随机应变很重要,我后面或许会以随机应变作为这次总结的主题。并不是所有项目都适合使用DDD,当你的需求规模不大时,甚至完全可以不分层,只要规范的写代码,以后需要做二期,复杂的时候再去分层也不会有多大困难,老生常谈的词汇---KISS,但是真正做到不过度设计也不疏于设计并不容易。