WHY:为什么需要领域模型
领域模型为解决软件的复杂性而生。
人月神话说:软件的复杂性是软件的本质属性之一。
2004年,Eric Evans写就了《领域驱动设计——软件核心复杂性应对之道》(注意书的副标题)
如果你的软件项目有如上问题,那么是时候考虑DDD了,如果没,不要XJB上DDD。(不要瞎引入复杂性,DDD本身比较耗费脑子)。比如写个代码几年不增加需求,别想太多,撸完就算了。
WHAT:如何做?
怎么解决复杂性问题?9年制义务数学教育告诉我们,不外两种方法:抽象、分治。
抽象:任何一个业务问题,都可以最终简化为一个或者几个基本原理的问题,这些个基本原理问题,就叫做领域问题。
领域问题是某一类问题的高度抽象。它关注的不是某一笔业务,某一个请求,而是所有类似的,具有同类属性的问题,是一个通用的解决方案。
是一个化繁为简的东西。他是真正简化问题的关键。
领域模型能不能简化问题,关键要看这个。
分治:任何一个业务问题,常常是几个领域的综合。如何去确定,区分到底划分为几个领域模型
(依据是什么呢?其实就是内聚和耦合)
在DDD中,形式上,它讲了一大堆层次模型和六边形模型。这些既不重要,也很重要。
不重要的是,他对于你对具体某个业务领域的抽象和分治毫无作用——这只能依赖于你对业务的理解,依赖你的思考方式和抽象——而这,才是DDD的核心。
重要的是,他从代码形式上抽象了几乎所有代码都必定符合的结构——并且研究了代码如何写才更科学——这对写出漂亮的代码很有帮助
举例LInux管道命令为啥如何灵活,如此强大
这是因为
1,抽象所有东西都是文件
2,所有文件都有输入 ,输出,错误输出,如果没定义,走标准输出入
3,管道是一个定义两个文件的之间的文件,作用是前者的的stdout作为后者的stdin
Netty也很强大,但是也很简单核心概念只有三个EventLoop,Channel,Handler
EventLoop定义了如何去调度线程和Io的方法
Channel定义了各种IO类型,可以实现各种情况下Nio,Upd……等Io协议
Handler是业务(线程)的抽象
可以看到,这里强大的根源和精髓的地方其实是LINUX的概念抽象,和概念之间的机制作用。而和用什么语言,用什么框架,3层模型还是六边形模型,代码写的好不好……等因素毫无关系
抽象是DDD的精髓。六边形,层次模型对代码实现比较有意义
用好DDD的关键是
1,深刻了解业务领域知识,了解业务概念,
2,根据业务模型,合理抽象建模(高度简化问题)
3,(操作实现层面)尽量少的引入复杂性(尽量少引入技术框架,用最简单的方式去解决问题)
不要在讨论业务的时候就考虑技术实现
所以这里强调一下我们的架构原则
1,业务和技术分离
2,技术和部署分离
3,变与不变分离
QA和回答纪要
1,老徐:DDD解决复杂性
2,翠翠:DDD关键是抽象
3,冯昌:TDD和DDD(跑题了)
TDD是测试驱动开发,要解决的问题和DDD(复杂性)没有关系。共通点是两个DD。
TDD的合理性和正确性成疑,不一定是一个好的方法。这个问题后续单独讨论。
4,徐康:DDD是一种最佳实践。
比如业界现在都怎么搞,大家都这么搞。
A:DDD是一种理念,而不是一种实践。理念是完美的,实践不一定是(举了某project2的例子)。
并且实践是时时刻刻在变化的,某一时完美,不代表下一时完美。要做到完美,开发人员必须有评价完美的标准——DDD,抄袭和采纳——那不可能铸就完美,因为我们自己的业务永远有特性。
5,刀刀:DDD和充血模型
Q:充血模型是对的,比较好的代码都会采用这种方式,他解决了什么问题?什么代码和逻辑应该放到充血模型中?
A:充血模型是对代码微观结构复杂度的治理。
系统划分、模块划分、对象设计、领域模型、充血模型……所有这些有一个想通之处:封装——耦合和内聚。
我们既然强调SOA是一种宏观结构的良好治理,DDD是一种概念领域结构的良好治理,那么就必然认为充血模型之一种代码微观结构的良好治理
那么哪些逻辑应该放到充血模型中?
1,自己的的数据的逻辑
2,两个模型之间的逻辑
这种逻辑两个模型中都可以放,看谁是少方。
比如人吃肉。一般eat放人里合适。但是如果业务是人吃肉,狗吃肉,猪吃肉……那么eat逻辑放肉里比较 好。
6,京其:领域划分的依据
内聚和耦合(本质是效率和复杂度)
以订单支付系统为例,什么情况下可以是同一个系统,什么情况下不可以。
创业的时候,很多创业公司订单和支付单是同一个。
公司业务更丰富,更多,他们就必须分开了。
分开的依据是耦合和内聚。