实战DDD(Domain-Driven Design领域驱动设计)


现代业务平台架构应该在什么理论指导下?无疑是MDD模型驱动设计和DDD,Eric的DDD是一本具有很大影响力的书籍
http://www.jdon.com/mda/ddd.html

回复这个帖子前,先扯一点儿其它,谈谈“软件的算法和方法”。

“软件的算法和方法”这个标题很大,有不懂装懂、故意卖弄之嫌。但我要表述的内容很浅显,只是借用了“XX法”这样高深的名词来表达在软件开发过程中,我们所关注的两个明显区分的领域。

算法
记得我在93年学习软件开发的时候主要关注的应该是算法。比如为了实现长方体的旋转,如何用最快的方式实现矩阵变换。这就是算法。教科书里通常都会精解例举若干种排序的代码。这也是算法。同样,采用不同的方式去遍历一个二叉树或“图”也是算法的范畴。那个时候的软件书籍,除了语言类的,绝大多数是这类的。
但是,跟我同龄段的软件从业者z们大都逐渐发现了一个事实:中国软件产业的发展的主流走向了管理软件和业务软件的方向。为早年写下WPS、CCDOS、CCED的精英们立下汗马功劳的精妙绝伦算法研究已经很难派上大的用场。只要你会用VB/PB/Delphi,通过Drag控件和凌乱的逻辑代码就可以实现一套完整的OA、管理信息系统、图书馆管理软件或者财务软件。这其实是中国软件产业的一个悲哀。
我们的专家们说,“中国软件业的前途是管理软件而不是系统软件”。于是我们从流,于是今天我们热衷于讨论的是软件设计的“方法”,“算法”的问题可以通过调用别人的lib去解决。
没错,牛顿也是站在别人的肩膀上的。可是我们同样站在上面望去,看不到我们民族的肩膀。跑题了。转回来。
在算法研究舞台上的缺位,让我们把所有的精力都倾注在了“方法”的研究和讨论上。特别最近3年,由Java开发本身所引出的各种方法层出不穷,引得我们无限追捧。

方法
软件开发/设计方法是一个这个行业最不可缺少的基础。软件工程组织、软件设计模式、软件框架、编程规范、测试驱动开发包括MDD/DDD都应该算是广义上的软件设计方法的范畴。而各个概念专注的领域不同,解决问题的重点也同:
软件工程的各种方法的目标是:组织和管理人员、时间、目标、过程、质量甚至预算。
软件设计模式的目标是:组织和管理程序的跳转逻辑。btw,“跳转逻辑”这个名词不够OO,是过程编程的概念。但任何OO语言走到下面到了编译原理和运算原理一层,就转化成“过程”了。
编程规范的目标是:组织和管理代码、注释、文档和数据资源。
测试驱动开发(TDD)的目标是:组织和管理编码和测试的过程,并最终对软件质量进行控制和管理。
MDD/DDD的目标则是:组织和管理复杂软件实现结构上的分析和设计,以求得一套清晰的指导思想来指引软件设计者在面对大型软件需求的时候,能够进入“万变不离其中”的“自由王国”。

DDD
做为《实战DDD(Domain-Driven Design领域驱动设计)》的跟帖,终于罗嗦到DDD。
我感觉到,无论采用何种方法翻译DDD中的Domain都难以找到一个最合理的汉语词汇来表达DDD的思想。即便现在普遍采用的“领域”一词,也令人感到晦涩。其实我们应该摒弃“望文生意”的方式。也许直接称其为DDD,把“DDD”当成跟Java一样的代号,然后再去理解其中所表达的思想,这样会对学习更有帮助一些。
另外一个重要的认识是:尽管DDD现在很流行,但从前没有DDD(词)的时候,一样可以开发出优秀的软件。在DDD这个词出现之前,许多类似的概念都在软件设计中大量采用了。也许你也用过,但从来没有提炼成一种“方法学”上的理论。Eric E.提炼了这个概念。这个概念必然来自于他的实践。

所谓“领域驱动设计”看样子是目前最难直接理解的概念之一(而且直译过来后跟汉语的语法出入很大)。但如果你能把DDD看成若干中“理论”中的一种,那这个概念就很好接受了。

首先,只要是“理论”,就会有很多流派。每个流派的理论都必然有其可取之处。DDD看似要成为主要流派之一的,那么初学者就可以暂时无条件的去接受它。这也是“站在别人肩膀”上的做法。――不要反驳“无条件”这个词,你不是也无条件接受了牛顿三定律么?
第二,只要是“理论”,初学者就大可不必去深究“为什么是这样”。没有4年5年6年的开发经验,就不要去质疑。否则你的质疑只能拿去印证“无知者无畏”这句话的真理性,或者直接陷入类似《一个“Spring轮子”引发的血案》的血案的血案的血案中去。“理解”本身需要一个过程。经历丰满的程序员在实践过DDD后会感慨:“从前我为什么不这样做!”。软件开发初学者没有从前,必然也无法体会出先苦后甜的感受。
第三,只要是“理论”,总是但方面的。总有站得住脚和站不住脚的地方。“算法”是有其唯一性的,是可以被证明其正确性和极限性(“顶点”)的。而“方法”则不具备唯一性的特质。歪用DDD中的一个词来阐释:某种方法在某些领域(Domain)中是优秀的,而在其它的(Domain)则可能并不合适。因此,DDD也不是放之四海而皆准的真理。

根据常年混帖的经验,必有血气方刚的革命小将会质疑我把DDD称为"理论”的做法。如有反驳的冲动,肯请不要在这里跟我理论。我只是一家之言,谈谈自己的感受罢了。

还是邓小平讲的好,管你白猫黑猫,逮到耗子就算好猫。
一些所谓“先进”不过是某些开发人员偏执的自娱自乐罢了。
过一段时间时机成熟,本人也打算对外发放一些开发框架库,包括web开发框架,数据库开发框架,业务层开发框架以及若干高性能开发程序包。这些东西不想与别人的东西争高低,只是想提供一种相当敏捷、相当高性能而且非常便于维护的开发工具组合。Java是个很优秀的语言,然而在国内外人很多“先进”人士的折腾和怂恿下,开发过程变得异常臃肿而晦涩。java应该反省了,不应该让php,asp等辈找到“开速开发”的口实。

>java应该反省了,不应该让php,asp等辈找到“开速开发”的口实。
DDD实际提供这样快速而又灵活的软件开发思路。

快速而又灵活非常重要,过去是快速而不灵活,象PHP等将Html和语言脚本混合在一起的软件系统易于维护和拓展吗?能灵活快速应付变化吗?显然不行。

所以,我们不能单纯看快速,而忘记软件解耦性,DDD是肯定软件分层架构:表现层、业务层(领域层和应用层)以及持久层基础上,提出快速建模方法,DDD认为那种智能UI快速开发是反模式。

为什么用“反模式”来否定它,因为模式是我们做软件基础,就象大家都接受过数学物理的基础教育,因此我们沟通交流就有了最基本的对话平台,如果你不懂模式,就象你没有上过学,如何和你对话呢?正是那句:秀才遇到兵,有理说不清!大家没有沟通对话的基础平台。

这也就是为什么那么多打着快速开发旗帜的工具受那么多人欢迎,因为他们虽然上过软件大学,但是没学过模式,所以,实际就是“小学没有毕业”,和他们讲,这样的工具要不得,就是说不清了,秀才遇到兵了,你说中国软件能不萧条吗?都是伪软件人在上面唱戏!

这些东西其实很早就使用了,只是没有去总结到理论的高度。
感觉大家老是讨论模型和各种新奇的理论、名词,而很少讨论开发过程中遇到的具体问题和解决方法。也就是说多数人总是在谈论各种“轮子”,而没有讨论如何让这些“轮子”去“转动”。

实际的项目开发中会遇到很多问题。实际的问题不仅在用户的需求,系统的开发维护和扩展更是需要重点考虑的。开发效率、可重用性、可扩展性、可维护性(包括稳定性)这些都是不可或缺的东西。举个例子:在管理系统中,权限系统是最麻烦、可重复性最大的部分之一,怎么没有看到谁在用什么模型来解决这个问题呢。笔者在开发领域混了N年,C++和JAVA都算得是经验丰富得实践者,自己设计、实现过不少架构性的东西(当然还不成体系的),很多模型都用过了,不过不是看书来的,是在解决问题的过程中自然总结而来。分层、解耦、SOA都是实践过程很自然的选择,根本就没有商业炒作的那么玄乎。建议新同志多去研究一下实际项目(开源的多得很),不要迷在各种理论、模式中。很多东西不经过实践是不能深刻理解它得真实意义的。另外很多时候都不是非此即彼的选择,得根据实际情况来决定。还有没有经过大项目的历练,是很难成为架构师的。否则理论再强,也不见得是真正的程序员、架构师,就如那个历史上著名的马谡一样.....

设想一下,如果一个项目不断延续开发好多年而不需要调整架构,能适应各种新需求、新应用环境,如果能做到这样可能就算得是真正得架构师了。

楼上有道理,主要意思让大家注重实践,非常正确。

我认为,除了拥有丰富实战经验,更要有先进的理论指导,两者结合才会对自己或项目产生根本的推动。

就以DDD来说,楼上也认为:这些东西其实很早就使用了,只是没有去总结到理论的高度。

正是如此,Eric Evans在他的 Domain-Driven Design一书的前言中也说了,这个课题20年来大家一直在做,令人惊讶的是,几乎所有文献来告诉大家应该做什么或如何做?作者认为在对象领域中出现了一种潜在的哲学体系,作者认为就是DDsD。

可以说,DDD是一种实践理论升华,DDD告诉我们:如何大比例分割一个复杂系统,如何以多层架构来分割,如果一些类涉及到多层关联如何处理?这些都是实战中碰到的设计问题。

总而

DDD和设计模式一样,不是一种新的理论,而是实战经验的总结,使用面向对象技术和分层架构来解决问题,而不是依赖数据库,纠正大家潜意识行为错误。

DDD不属于架构问题,而是属于如何使用架构,如果说:架构是轮子,那么DDD属于如何使用轮子!这点非常重要。

当我们陷入EJB或Spring等架构争执时,其实我们已经将大量时间浪费在无谓的架构平台选择上,我们业务重点都无暇顾及,这是非常重要的。

我是最近在选择合适的架构时偶尔逛到JDON的,虽然以前以零星拜读过里面的文章,但没留下什么印象。最近选择架构时看到JF的介绍,其中的理念(设计出发点)跟我的想法比较吻合,所以仔细看了一下关于JF的讨论和争论。在众多意见中,有份量的很少(从实践角度看)。很遗憾JF目前没有一个较为成功的应用案例,只好先放弃。

其实很佩服Banq的开拓精神,不管JF实质如何,都是值得肯定之举。一个项目的成熟需要N年的奋斗,多数主流开源框架都是这样艰难走过来的。只有在大量应用中不断改进、不断提高才可能有一个好的框架出现,希望banq继续努力。同时也建议banq用JF来解决开发中比较常见的问题,这样对你做咨询也有很大的好处――对企业架构是无形的东西,好处一下子看不见;而以架构解决的问题却是实实在在的好处。
Banq提到了树形结构,这是一个很好的实践点。不过树形结构模块决非容易实现,笔者在这方面有很深的体会,也有一个通用架构实现,不过没时间整理,等以后有闲了,也把它开源吧。

我是一个长期的OOP实践者,不喜欢POJOs的提法,在实际的项目中没有采用它,而是典型的DDD做法。我使用webwork+hibernate(因为时间紧,没有考虑AOP,IOC),在开发中还是发现这些结构带来不少的限制。比如webwork的Action机制、hibernate的joined-subclass和subclass不能混合使用给OOP的灵活性带来的困惑。总之任何架构都会有其好和不好之处,如何在别人的基础上提炼、整合一套自己实用的东西也是架构师需要重点考虑的事情。在我看来,任何单纯的架构都很难完全解决实践问题,某些架构带来的配置问题在产品的迭代开发中近乎灾难。至于什么用XML实现Domain Model,然后反向生成代码之类的技术更是难以操作。窃以为一个灵活而功能强大的框架+常用模块(通常是公共模块)+代码生成+整合的IDE才是PL的首选,很多架构的可操作性缺陷可以用代码生成来解决。对于项目开发来说,我们需要的远不止于框架,而是一个basic business solution。拿房子做比喻:我们需要的不是一个建筑框架,我们需要的是装修好的房子,只要搬入家具就可以入住了,多好。

象ofbiz,compiere这样的business solution && framework倒是符合PL的选择,可惜它们都是自成体系,很难集成别的成果。向OFBIZ几乎完全不用OOP,退到属性-值的原始出发地(Slide也有点类似),灵活倒是灵活,但对我这个OOP者而言则是完全不感冒。compiere则是一个混乱的体系,对象、属性混杂,对象关系混乱,AD也有不少需要精简之处,是一个三层结构,两层思维的东西(或者说Table-drived Design)。我想如果我们也来搞开源框架,不如搞一个Application/business Framework,可能更好吧

另外加一句:DDD,就是OOP-based,不管它真实意思是不是这样。我喜欢一个丰满的Object,不喜欢豆芽菜似的POJO,有很多项目实现居然全是使用一个个互不相干的object(连继承关系都没有!),代码根本无法阅读!与其这样,不如直接用ofbiz算了。这种做法还不如面向tabel的实现,至少人家还可以大量使用SQL来获得性能优势。丢掉继承、聚合,也就不要谈什么object了,还是谈table更直接。

首先多谢lhsail对jdonFramework肯定和建议。JF有一些成功案例了,可以从JF专门论坛中看出来,我曾经使用JF帮助一些公司迅速做演示系统来竞标,过段时间我会整理这些商务资料。

lhsail很多想法我都有同感。 特别是对于ofbiz compiere/slide批评非常到位,现在很多国外开源框架貌似非常符合胃口,其实类似国内那些几百元的盗版软件,挖了陷阱等你跳下去,扩展性以及持续发展性严重不足,说白了,就是没有生命性,功能是死做出来的。

>对于项目开发来说,我们需要的远不止于框架,而是一个basic business solution。
非常正确,需要一个业务解决方案,这个解决方案需要顾及两个方面:灵活的拓展性、也就是强有力的生命力,能够集成将来的一些新技术和新组件;其次才是完整的功能。

目前很多人对软件的思想还是焦点落在后者:完整的功能,觉得一个软件功能越完整越好,其实关键还是架构的灵活性,就是前者,基础架构好,功能添加只是时间和工作量问题,但是如果架构不好,功能再完整,也不可能包括未来所有功能,软件是有生命的,在未来成长时,更多功能需要加入,但是因为基础架构不灵活不能方便加入,死路一条。

正因为普通人对软件存在误区,对功能追求高于基础架构,出现短视现象,这样引导教育培训任务很繁重,而且,很多吃亏的老程序员就此离开软件行业,带走宝贵的失败经验,新的盲目的年轻程序员还是使用老的思维往前冲,义和团式冲动的造就了软件的畸形。

>不喜欢豆芽菜似的POJO,有很多项目实现居然全是使用一个个互不相干的object(连继承关系都没有!)
这是过于POJO化了,什么事情都不能走极端,其实领域建模的根本诀窍就在于如何做一个既不过于简单豆牙式的POJO,也不要做一个带有臃肿复杂关联关系的POJO。

模型的关联关系尽量减少,但是对于不能减少必须认真对待,而且不能搞乱层次,如何划拨这些关联关系是目前领域建模关键所在,Eric Evans也没有提出一条准则,总是谈直觉,具体情况具体研究,这些就有赖于有经验的建模咨询专家的介入。

>我想如果我们也来搞开源框架,不如搞一个Application/business Framework,可能更好吧

非常好的事情,如果你有时间,我们可以一起策划一下。

Evans DDD目前在国外相关站点讨论也非常热闹,下面这篇文章是最近8月8日老外用微软的.NET架构和Evans DDD比较的文章:

In this article we compare the Microsoft Three-Layered Services Application [Microsoft TLSA] architecture against one by Domain Driven-Design architecture [Evans DDD] for organizing domain logic. For this purpose we use the Microsoft .NET Pet Shop 4 application as an example to explain the difference between these two approaches. It then gives some comments on what Microsoft has in store to better support the latter.

This article is aimed at developers and architects who are trying to find better ways to capture the abstraction of the domain in their designs. It will help you if you have some knowledge in building enterprise applications on the .NET platform.

http://weblogs.asp.net/pgielens/archive/2006/08/08/Organizing-Domain-Logic.aspx

实体模型中的属性、和值对象。他们作用都是描述实体,只不过前者描述的是实体的特征。后者描述的是实体的状态。但是值对象有没有可能是另一个实体那?
比如一个考试实体,有考试ID 考试名称 及监考教师3个属性
当指派监考教师时这个监考教师应该算考试的状态,属于值对象。这么理解对吗?那么存在监考这个实体吗?

监考的实体可能有属性,考试ID、监考教师ID、监考确认等…… 这不又出现另一个实体了吗

是否有监考这个实体,主要取决于当前需求,如果是一个监考系统,无疑监考是一个实体,如果只是一般考试,监考老师只是考试这个活动的一个参与角色。