在《系统架构设计之 平台建设思路》和《系统架构设计之 以软件为鉴,可以知兴替》两篇文章里,我阐述了分层、业务模型化分解、标准化接口对于解决复杂度,增加可扩展性的强大作用。
跟业务模型化分解有个类似的概念叫做领域驱动设计。
在此之前我是不太关心这些测试驱动设计、领域驱动设计什么的概念的,都是扯犊子。但是跟业务模型化分解沾点边了,所以拿出来说一说。
有很多朋友问我关于业务模型化分解这个具体怎么操作,认为我只讲道而不讲术。为什么不讲术呢,因为术讲不好,很大程度上需要一事一议。
而DDD(领域驱动设计)就试图将道转化为术,很显然它转化的并不成功。所以从业者对DDD的评价也有很大差别,算是毁誉参半,为什么DDD会造成这个结果呢?
因为能够深入领会DDD的人,不会拘泥于他的规则;而拘泥于它的规则的人,用不好DDD;
实际上领域驱动设计和我所说的分层、业务模型化分解、标准化接口是一个意思。很多讲DDD的人一下子带来一串名词,搞得人云里雾里的,没有抓住其核心。
核心就是怎么降低大型业务系统的复杂性和可扩展性。
让我来举个例子:
我们要开发一个描述人类夜生活的程序,如果是简单的demo,可能我会记个流水账;
1、吃饭。吃的什么……巴拉巴拉
2、打游戏。打dota……遇到了一群xx队友,怒喷他们20分钟……巴拉巴拉
3、洗洗睡觉。巴拉巴拉……
如果这个程序没有需求变更,这么写有毛病么?没毛病,要面向对象、设计模式、面向接口编程么?要DDD么?都不需要。
那么问题来了,既然是大型复杂系统,细节就很多很杂。
吃饭,在哪儿吃,吃的啥,跟谁吃,会有很多变化,还有可能很多人不吃饭,只喝酒。
打游戏,打的什么游戏,跟谁打的,结果咋样,一定打游戏么,不能看电视么?
洗洗睡这个内涵就更多了,你懂的。
你会发现,需要改的地方太多了,而且需要做很多判断。
那怎么办呢?
你需要把你客户的夜生活形成一个稳固的模型,这就是我所说的模型化分解。假设我们定义的模型是,补充能量、娱乐、休息。这个时候就牵扯到你对业务的掌握程度了,它决定了抽象的层次和粒度。什么意思呢?就是如果你的客户,就是吃饭,那么就没必要抽象到补充能量这个层次,如果你的客户洗洗睡这两个动作要分开,比如东北客户可能需要去洗浴一条龙之后再睡,那洗洗和睡可能是不同的领域。
然后就是面向接口编程。模型化分解了之后,那就产生了接口及接口的输入输出参数。
应用层的代码就变成了:
补充能量(大白,固定参数,可扩展参数……);
娱乐(大白,固定参数,可扩展参数……);
洗洗睡(大白,固定参数,可扩展参数……);
如果你业务模型抽象的合理,那么这部分代码就可以做到永远不变。
然后就是实现补充能量、娱乐、洗洗睡这些接口,这些接口的内部实现还是要做一些抽象的。
我们总结来讲就是,当预测到某些部分的实现会有一些变化,那么就面向接口而不要跟具体实现绑定。
某个动作是接口,未来的实现可能会各种各样,实际上,这个时候已经分了层。因为这一层对外是一致的,里面可以变化。
会有一些固定的大的分层,比如说业务层和数据层。
因为软件系统不可避免的要跟持久化层打交道,而随着持久化层技术的丰富多样,业务层和持久化层的中间层的需求也日益显现。这中间还有一个数据表示和数据持久化的转化问题。什么意思呢?还是举个例子。
如果你业务层是这么写的:
把今天吃的东西存到mysql的每日进食表里。
那么就确定了得是mysql,得是关系型的表里。
如果你是这么写的:
save(吃的东西,大白);
那持久化层就可以是redis、mysql、ES等等,因为是啥都不影响存起来这个接口。
数据转化的问题,就是你做业务的实体和你存库里的实体,可能没办法直接对应,需要做可能的拆、和、关联等等的操作,这部分由一个统一的工厂来处理。
你看,其实哪有什么高深的东西,无非就是将不变的稳定下来,将变的抽象出来。
说破大天,就是分层、模型化分解、面向接口编程。
理解它的原理,其实无需遵循它的规则,不理解它的原理,遵循了也用不对地方。












网友评论