面向领域设计不流行的原因猜测

我的个人看法:我觉得之所以现在面向领域的软件设计模式不盛行,是有一定原因的,而传统设计应用的长盛不衰,经久不疲也是有一定原因的,两者不可避免都有一定的局限性,将不会存在谁被谁替代。对于传统的mvc架构程序,典型的特点是,同步,锁,关系数据库,高并发支持性不好,但是安全性强,数据一致性高(间接导致代码不够优雅),但是三层结构还是比较清晰的,分层也直接导致了web项目的高产和繁荣。传统的应用程序设计在面向企业级应用时,通常是把高安全性,数据高准确性放在第一位,而把对高并发的支持放到了第二位。有人说,传统应用真正需要高安全性,高数据一致性的仅仅是很小一部分,这个是很难界定的,也很难说清楚的,业务和业务之间的联系,数据对数据的影响,可能错综复杂,牵一发而动全身,谁敢做此保证呢?

反过来,新的面向领域设计,并发事件编程,读写分离,加入场景角色,确实和传统的应该设计有点不同,但也并不是完全新的事物。

面向领域是针对传统编程的一点改变,实际上是想把面向对象的思想重新融入到架构中。传统架构的设计是摒弃了OO思想的,就是简单明了的三层,在这一点上,是有原因的,三层结构清晰明显,解耦设计也提高了程序的扩展性,且重要的一点是高产(在目前的市场经济下,或者说是商业模式下,高产就代表着高效益高利润,这往往比其它更重要)。在这一点上,面向领域未必就占优势。面向领域了提出聚合根,高聚合的概念,这也是真正面向对象的思想,以面向对象的思维去解决问题。但是很多企业级应用的模型,无法或很难提炼出一个高聚合的结构,或者仅能提炼出很扁平的聚合结构,而大部分业务也是由这些扁平的聚合体积木式的积聚而成,它们并不需要面向对象的思想。这并不像论坛程序,或者局部小范围内的某些应用能提炼出高度聚合的结构,同时使用这种聚合结构就能实现全部或大部分业务行为。面向领域还提出一个失血模型概念,这个概念本身也是以应用中能提炼出聚合结构为依据的,但传统的企业级应用可能根本就没有提炼聚合结构,三层架构中来回传递的实体(包括持久层持久化的实体),只能算是一个简单的dto(不称为实体也许更合适,但是状态可变性未被大多数人所重视,并且不名避免的可能会引发一些意想不到的问题)而已,简单的传输对象dto,就是对一些数据碎片的封装,是不需要充血的。充血就意味着有行为,要维护状态,而传统应用设计中的这种实体是完全不需要的,因为本质是就没有领域实体的概念。面向领域,认为所有的业务或者大部分的业务都是这些聚合结构的职责,由这些聚合结构实现层层事件传递和接力。而传统应用设计,无须这些聚合结构(或者可能也根本提炼不出来),认为所有的业务职责都是操作者(人)的职责,直接由操作者发出命令,然后,三层结构以同步的方式完成命令并持久化。而面向领域,变成了操作者发出命令给聚合根,聚合根再把命令层层传递给聚合结构,最后牵出事件,异步持久化事件及最终状态。在这点上,两者无法谈孰优孰劣,也不可能是一边压倒一边。

加入场景角色,以角色驱动行为,也就是所谓的dci。这个思想或者说设计,能更好的站在人的思维的角度(或者说哲学的角度)去诠释,解决问题。就好像当初面向对象的思想更好的站在人的思维的角度去诠释,解决问题。但是,面向对象替代不了面向过程,面向对象的编程也替代不了函数式编程。同样,dci也替代不了传统的无角色oo。就目前的情况来说,dci更适合于有聚合结构,并且聚合结构能驱动全部或大部分业务行为,且存在多场景且场景可能频繁变化的应用。这种应用说实话很少,像生物仿真,人工智能,自然语言理解与合成等应用算是此种。更多的企业级应用,往往不是面向通用场景的,仅仅是仅针对一个或少数几个领域,也就是说,场景和角色默认是已经确定了的,或者极少改变,还不至于要用到dci来解决反复大量的场景角色变化问题。

读写分离最早是体现在数据库上,到现在为止还很少体现在架构设计上,原因可能是dao设计还没有达到需要高度抽象到读写分离的程度。也就是说,读写分离并不难于理解,只是应用到了一定程度,持久化类为了解决各自职责高度抽象的结果,最终导致读写的职责解耦,分离。

并发事件编程模型,这个思想早已有之,只是没有对高速发展的硬件(多cpu,以及多核cpu)提供支持并进行优化。并发事件编程在过去,也应用到了很多领域,但之所有在web领域的mvc中没有盛行,我想是有一定原因的。传统的企业级应用追求高安全性,高稳定性,高数据一致性准确性,这个只有使用同步和锁能解决的最简单,最好。现在的很多并发事件编程模型(包括本站的),都是把高并发性,高性能放在第一位,而高安全性,高稳定性,高数据一致性准确性放到了第二位。但这个是有风险的,大多数企业级应用不允许你这样。并发事件编程模型,确实实现了高并发的支持,解决了大访问量性能瓶颈。但我觉得,这只是在一定程度上解决了高并发访问性能瓶颈,或者可以这样说,在某种程度上,这个性能瓶颈是转移到了事件持久化及回放的复杂度上。为什么这么说呢?因为传统企业应用保存的是实体的最终状态,也就是说,我只关注结果,而不关注过程。事件编程,则必须记录事件的全过程,否则不敢对结果作出最终的正确性保证。问题是,一个很复杂的业务可能仅对一个状态做出简单的改变,或者大量复杂的业务仅改变了少数状态(也有可能最终状态没有改变)。也就是说,同等情况下,保存一个事件过程要比保存实体的状态复杂得多,可能要花费更多的空间和时间,同时还要花费更多的精力来保证这些事件能及时被持久化不丢失,保证能正确的回放,保证回放最终能真正的还原到历史上的时间点。要想完美的实现这些保证,几乎是不可能的。同时,有些企业级应用一旦发生事件,是不可逆转的,异步事件提前更改的实体状态,可能造成永久的的更改,无法抹去,也无法回放,很多金融应用都属于此类。还有一些企业级应用,涉及的领域范畴太多,一个事件,可能如蝴蝶效应般快速传染扩散到其它应用或网络服务,这种应用回放的难度太大,几乎可以认为是不能回放。除此之外,还可能有一些实时性很强的应用压根就不允许你回放。这最终导致了两个最大的难题,并发事件如何解决即时持久化大量的事件问题,如何解决异常时的回滚或者说是回放,对于那些难以回放或者不允许回放的,又如何保证其状态改变的安全性和准确性,这是否可以说是解决一个瓶颈的同时带来了一个新的瓶颈呢?


我想,这大概就是为什么面向领域的设计,并发事件编程模型未能普遍,盛行的一些原因吧

传统开发模式经久不衰,
DDD叫好不卖座,
相信这其中是有原因的。
楼主比较得非常好!

楼主分析得有一定道理,但我觉得还有两点应该补充:
1、传统的面向过程分工容易,对于大型团队开发,完全可以根据分工的不同切分;而领域驱动,在分工方面就没有太大的优势;
2、基础氛围不够,即多数人学习的还是传统的开发模式,这需要革命,至少在国内多数开发团队的领导已经习惯了传统的模式,新的东西要使之接受是个很艰难的过程。

我一直在给我的开发人员灌输面向事件和场景编程的思想,但非常费劲。

我觉得我的偶像楼主有点过分担心了,今晚太晚,明天抽时间回复。呵呵

技术革命本身就是一个长期过程,不是什么卖座不卖座的问题。新东西总是先从一个点开始发展的,凭什么一出现就否定一个面?

企业考虑的是收益,不是技术的深度,还要考虑风险和资本问题。当企业考虑到企业的招人问题时,企业很大程度上向传统方式靠拢;当就业人员考虑到找工作问题时,也是向传统企业考虑。这是一个死循环

以上才是主要原因,DDD技术在国外得到很好发展,DCI提出也得到很好重视,REST出现使到程序员重新反省。在中国若果连像jdon这些小社区都发展不来的话,中国软件只会越来越像一坨屎。回想下中国的WEB技术的失败案例,例如高铁订票系统,个案?哈哈,真正的问题不是传统技术,而是程序员除了传统技术其他啥都不知道。
[该贴被SpeedVan于2013-05-31 07:08修改过]

我与楼主想法正好相反,我并不是从现状结果去推导原因,我看到的是山雨欲来风满城。

当初2003年时我在Jdon倡导设计模式,国内没几个人搭理的,十年过去了,设计模式已经得到普遍认可,至少是软件工程的一项基础。

如果前几年业界都是在讨论消化DDD,讨论落地机制,随着异步并发Actor模型到来,DDD走向普及的技术障碍已经消除,这两天有两个振奋人心的消息:
Actor模型的Akka框架成为开源Github下载量第一

Spring也刚刚推出Actor模型的Reactor框架。

关于楼主提出面向对象不适合现实中大多数系统的观点,我觉得这可能关乎哲学或方法论问题,本站讨论也很多,面向对象本质是分析划分边界。

“世界”两个字中有一个“界”,何为界?边界,也就是说,人们认识世界是可以通过划分边界实现的,多层结构也是一种分界方法,不过多层粒度太粗了,还需要对穿越多层的数据对象进行分界划分,DTO只是一堆没有逻辑关系的数据,而领域模型是通过行为保证数据的逻辑性,比如这些数据之间有大小约束,你如何表达这种逻辑呢?命名为min和max就可以吗?

那么为什么大多数人对这些人的基本分析方法和逻辑没有意识到呢?那是因为没有人告诉他们。正如明清之前老百姓没有见识过西方科学,怎么能让他们去掌握呢?现在的大学或培训学校的软件工程教育已经严重脱节。

没有接受过最新的软件工程教育,不知道设计编写软件应该怎么做,那么这些学生毕业后就不会编程吗?当然否定的,结果就造成如今的现状。而一旦自己思维被自己的朴素经验束缚,再让他们用面向对象好的方式去编程就很难了。

事件驱动编程主要是针对传统CRUD系统的一种升级优化,如果说CRUD增删改查只是把系统的基本功能完成了,那么如果要设计出更加互动更好用户体验的系统,上升到事件驱动是必然。

事件驱动在传统系统中已经大量存在,比如系统的操作日志其实是一种domain日志,特别是重要的系统,都要跟踪保存操作者的操作。

我还有另外一种观点,如果说CQRS是事件驱动的out of box方案,那么NoSQL其实是事件驱动的in box方案。NoSQL将CQRS读写分离封装起来,只提供方便的REST接口,这种做法类似传统关系数据库的做法,当然提供了很多简便性,但是随着系统复杂提高,我们还是希望自己打破这个盒子限制,自己来直接面对事件进行详细灵活的定制处理,当然这样做带来复杂性。

总之,面向领域驱动设计不是想完全替代传统CRUD,而是提供系统更灵活更复杂的解决方案。相信随着大家对软件知识日学越益,为道日损,到达一定程度后,就会觉得DDD很简单,正如现在我们已经把设计模式踩在脚下,未来十年后我们会把DDD也踩在脚下。

更多观点见我的事件驱动编程视频演讲

[该贴被admin于2013-06-02 16:54修改过]

DDD的学习成本太高,现在还在初生阶段。我也曾经试过想使用DDD的模式来重构当前的一个项目,但是最终是因为上面的压力而被迫放弃重构改而推进度。
当前中国注重软件质量的并不多,他们只注重一个字——“快”,谁最快就谁能占据先机,抢占市场,质量还是后话。
TDD的开发模式已经被证明是保证软件质量的一个可靠手段了吧,看现在有多少企业在用?今天交个任务给你明天要你交货,交不了货就滚蛋,谁敢写测试用例?DDD其实也一样,别人SmartUI一下就出来的东西你分析个半个月?大家都知道上头从不管质量的问题,下次铁定叫你换上SmartUI那套方案。

不是很同意'快'而不重'质'的说法,DDD,DCI,Color,pattern都是方法论,目的是让我们能在分析,设计,开发过程中能更好的全局的做事;如果你的老板告诉你‘明天要交货,交不了就滚蛋’的时候,你作为一个leader,职责是分析出可行性,包括人,产品,时间,特别是质量,各自的风险和存在的问题。这种快,最大的一个风险,还不是加班,而是质量,而保证质量的一个方法就是测试用例,那么如果你能接下来这个工作,说明了你一定有别的方法能保证质量,比如能力强的开发人员,比如现场客户直接参与测试,等等。但是,他们不冲突,举个简单例子,测试用例也分很多种,很多级别,如果没有时间写很详细的,那么关键的测试用例是不是也可以保证80%的质量?这些都是方法,不是对立的。
回过头来,谈谈快和质的问题,常常被人用来诟病某方法论是否可行,其实这是2个问题,方法论是方法论,就像法律不一定在各种场合,都是合人情的。

其实不是面向领域的设计不流行,而是“设计”根本就不流行!
至于说什么“快”的东西质量会有问题,完全不是这回事,真正问题搞清楚了,肯定会很又快又好的。

对于大家分析的现象,我个人认为到现在为止,软件设计和开发还不是一项简单的工作,大家看到很多人好像都可以“设计”、“开发”软件,其实是因为现在的硬件、工具、信息(搜索引擎)比以前方便太多了,但是软件设计的本质并没有什么变化,banq可能觉得经过这么多年的发展,软件设计比以前简单了,我部分认同,我自己也觉得现在软件设计比以前简单了以下,但是那是因为我们个人已经花费了大量的时间在软件设计上了,对于没有花过相当多时间的人,其实软件设计可能更难了。

我看到的情况是大量软件设计根本没有入门的人在“设计”软件,照猫画虎,东拼西凑。其实没有必要对这样的设计要求太高,不要把他们当成专业的设计人员,当他们是普通用户自己玩的开心就行了,毕竟他们也能解决很多问题的。
[该贴被cxh于2013-06-03 14:00修改过]

2013-06-03 13:59 "@cxh
"的内容
而是“设计”根本就不流行 ...

你偏激了,虽然说的某些程度上不错。但是,那是个方向,找准了,慢慢来,我们的问题出在太急了,和中国大多数作坊式加工企业的做法一样,靠量取胜,可质却拿不出手。
我见过某企业的技术大牛,雄心勃勃的想给某行业做一个标准门户,可是知道他背景的都很清楚,他连基本该业务分析员的能力都没有,怎么就这么大雄心?
国外的大牛,为何能分析到如此,其实已经在做一些无聊的事情了,比如Color Modeling的发展,DNC其实已经是在做学问而不是做项目了,可是那是基于这些人都是几十年的经验总结下来的行业和技术知识积累,而不是我们某些天才大学生,校门还没出,就已经要成为中国未来BIll了,或者工作才2年,就不想做开发,想搞设计了,可是都没挨过客户骂,项目还没做失败过,,,这么急?呵呵

2013-06-03 14:52 "@ericyang
"的内容
你偏激了 ...

不好意思,可能很多人都会觉得我有点偏激了,但是我自己认为软件设计工作对于大多数人来说,都是要花费相当长时间才能掌握的,很久以前我自己最初是因为兴趣自学软件开发的,最少话费了10年以上的时间才搞清楚了很多东西该怎么做。以我对现在教育情况的了解,现在绝大多数人不太可能在自己期望的时间内掌握相对合理的软件设计方法。现在大家最缺乏的其实不是什么高深的理论,而是把最基本的东西搞清楚的“耐心”,但是我很少看到这种“耐心”。

还有就是软件设计是一项实践性很强的工作,如果没有比较复杂实际项目技术上从失败到成功的几个完整的生命周期,其实很难说掌握了什么东西。我的一位老上级说过何谓掌握:最起码是听过,见过,做过,错过,而且最后保证每次能做好。聪明到可以吸收别人犯错经验的人是很少的,所以对大多数人来说,软件设计还是通过自己的时间和客户的钱堆起来的。

啰嗦了这么多都不不知道我要说什么了,总的来说jdon社区还是有不少真心想做软件设计的人,希望大家坚持下去!
[该贴被cxh于2013-06-03 16:19修改过]

关注jdon有一段时间了,非常好的软件社区,Banq的风格比较犀利,是非常注重实践和思想的大牛,比较佩服。尤其是java实用指南里的那几个案例,一上来就是大部头,重量级,不是盖的。
对于从事通讯行业多年的技术人员来说,偶比较欣赏Banq,相比市面上那些培训机构,我只感慨没早接触jdon以及banq。

2013-06-03 16:18 "@cxh
"的内容
不好意思,可能很多人都会觉得我有点偏激了 ...

呵呵,这次你说的每一个字,我都可以表示同意了。。。话扯远点,从中国式过马路就能看出,这个朝气勃勃的国家有多么着急的想赶到前面去;可是,为什么我们没有很多自主的东西,就是因为着急,任何事都不能做细做精,那我做例,我在参与的几个项目,里面的技术点,哪怕一个小的功能,都需要很长时间的设计,开发,实践,以及失败,最后才能得到一个真正能展示和延续的方案,很遗憾,都是国外的项目。
哎,,,国内项目,难。。。努力吧。。。

我认为可能大多数人对软件的快速开发和质量有一种误区,按平常概念去理解,快了就好不了,好了就快不了,对立起来了。

其实软件的质量和开发效率是统一的,质量好是为了下次更快,如果不追求好,反而欲速则不达。

如下图对比,DDD虽然起步时比传统开发方式稍微费时,有些成本,但是磨刀不误砍柴工,随着软件开发不断深入,DDD方式的效率是平滑上升的,而其他两个方式开发效率则是陡然上升。

所以,我为什么说,为什么程序员跳槽频繁,因为他实在无法去维护拓展自己的老程序,付出努力加班熬夜实在不合算。