关于模块化

模块化是迄今为止对付复杂软件系统的最好的办法。
问题并不在于上面这句话。问题在于怎么模块化。这儿的“怎么模块化”并不是说不知道模块化是把系统分拆成几个模块,组合而成系统。而是说不知道以什么规则指导我们进行模块分拆。
当然,关于模块化,有很多非常著名的指导原则,最著名的莫过于“高内聚,低耦合”。可是这个原则有点太过空泛。即便如此,我们也很有必要研究一下这个原则。高内聚的好处是什么?为什么要高内聚?我个人的感觉是,高内聚降低了模块的理解成本,同时潜在的降低了模块组合的困难程度,因为高内聚比较倾向于产生一致性好的接口。低耦合呢?低耦合有一个非常直接的目的,就是为了降低模块的相互依赖程度,以便于:一、更容易替换模块和重用模块;二、强迫模块的接口简单直白。
有了这些铺垫,我准备暂时岔开话题,说说分层体系。
分层逻辑上是把同类【注意:这里是同类而不是同种,以后这儿的差别会被区分的非常清楚】的模块放置到一个叫做层的逻辑模块容器中的一种分拆方式。举例来说:把所有数据库访问类的模块放入到DAL,所有的业务逻辑放入Logical,所有的用户交互放入UI,就是一个经典的分层模式。
对于分层体系,我最大的质疑就是它简直就是低耦合,高内聚的完美反例。首先,它是低内聚的,同一层的子模块,除了逻辑上的同类性,没有别的任何需要聚合在一起的理由。其次,它是高耦合的,层与层之间的耦合关系显然典型的比层内子模块的内聚程度还要高。
那为什么分层模式是如此的流行呢?理由如下:
一、分层给了老板一个完美的项目延期的理由。也因而受到广大的受剥削受压迫的程序的大力吹捧。
二、分层流行的,所以采用分层的风险是小的,所以一定要采用分层,否则自己得全部承担反抗分层的后果,有可能是失败的后果。
三、分层在一定程度上确实解决了某些复杂性问题。
在我看来,第三个理由才是真正的好理由,虽然第一和第二个理由才是最强有力的分层理由。我说说第三个。
我要举ISO的OSI模型为例。OSI是开放系统互联的意思。先假设我们没有任何相关的背景。我们需要制作出一个可扩展的机器系统互相通信的系统。我们可以参考人类已经有的通信系统,当时已经有了语言、电话、电报、IP等等系统可供参考。通信方式从线路交换到包交换都有。问题很快区分出来了。有定址问题,有路由问题,有会话的建立和拆除等控制问题,传输问题,流量控制问题,差错控制问题,进一步还有编码问题,表示问题等等。
所有的这些问题纠缠在一块,并不很容易解决,其复杂度也超出了人类处理复杂度的极限。这时候模块化就来救驾了。由于所有的这些模块是为了一个共同的问题,所以区分出来的模块难免会有很强的耦合。而为了能够控制耦合的强度,采用了分层这种模式,用于限制模块之间任意的耦合,只允许部分模块与另部分模块耦合,也就是所谓的分层。分层就是限制了耦合关系的模块系统,只允许模块跟其上层模块和下层模块有耦合。
所以,分层,模式是为了控制耦合度的一种模块化系统。因此,它确实拥有模块化应该拥有的好处,同时还强迫系统中的模块耦合关系不能是任意的,只能是规定的。
但是,任何把分层模式推往极限的做法都不一定再是对的了。真理往前再走一小步就是谬误了。现在好多系统都是为了分层而分层,结果导致本来该存在于一个模块中的东西却被硬生生的拆分成多个模块,分布在多个层中。形成一种很强的耦合关系,而为了减轻或者消弭这种人为造成的耦合,不断的加入更多的层次,比如我们经常见到的关于VO和DAL,贫血和充血之类的争论就是这方面的争论,这不仅是搬石头上山,而且严重的降低了开发和运行效率。
再岔开一步,我们说说OO。
OO有很多有点,也有一些缺点,当年OO很火很拉风的时候,人人以OO为尊为荣,现在OO成了主流,在理论家或者先行者眼中就成了落魄者了,所以开始很批OO,以OO为卑为耻。其实无论是崇尚还是鄙夷,OO还是OO,它的优点依然存在,跟刚刚被提出来一样有效。而其缺点也依然存在,也跟其刚刚被提出来一样有害。
OO是一种模块化方式。其基本思路就是希望尽可能自然的表达模块,对象作为一个有状态有功能的模块,确实比以前更容易处理模块化这个高深的技术活了。
上面关于OO的讨论,其实可以套用到OB上【或者也叫做ADT】,OO还有个核心的思想是“分类”。其实对于OO的批判主要集中在这个分类上。由于人类思维的飘忽性,昨天认可的分类方式今天却发现不适合,所以OO的分类提供了“继承”来完成这个所谓的思维进化。可是问题是继承只是子类化,只是在类【或者在数学上叫做集合】分拆出一部分作为子类【或者在数学上叫做子集合】。由于人人都有自己的观点,这样就难免会有见仁见智的问题。而且最大的问题就是其实这个所谓的继承根本没有办法完成思维进化,只能在一定程度上完成概念精化的模拟。后来就引入了接口【或者叫做契约、概念】之类的方式{《这儿我并不准备区分编译时还是运行时等等细节问题,所以Cpper也不要吹毛求疵了》},允许多继承,也就是允许了从多个维度进行分类。比如从大小这个维度进行分类,分出:大、中、小三个类别,从颜色这个维度进行分类,分出:红、绿、蓝三个类别,组合这两个维度【多继承】就能得到一个新的类别出来。有了多继承的引入,OO已经比较完善了。
OO就是上面说的那样。其实OO还有一个比较强的隐含假设,那就是,作为一个Object,它是自足的。也就是说,它要能自我存在而不需要强依赖于别的实体。或者换一句话说:它要是完备的。
那么,我们结合OO和分层就能看出,现在UI、Logical、Data这样的分层机制跟OO机制是冲突的。从OO角度来说,订单就是订单,产生订单,收集订单信息,检验订单,签署订单,订单相关交易【现金和商品】,订单完成等等都是订单的功能,订单有其自身的状态,比如:货物的数量、单价、约定时间等等。从分层角度来说,订单的填写属于UI层,订单的处理属于Logical层,订单的永久化属于Data层。
现在,Java界的业务对象慢慢的获得重视,就是要把各个层次的东西组合起来形成一个完备的自足的对象。而Ruby这类语言由于类的动态可扩充性,自然而然的更能采用OO的思路来思考问题。C#语言也提供了扩展类和扩展方法以便于支持LINQ,同时也自然的提供了类Ruby的解决思路。Java界有一个项目叫做Qi4j,就完全是基于组合开发软件的思路,提供的是纯Java接口,而不是JRuby,Jython,Groovy之类新语言【它们都算是Java界的】,对于坚持咬定Java不放松的那些Programmer来说,应该有些吸引力吧。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值