高内聚与低耦合web
WHAT设计模式
"高内聚"与"低耦合"是软件设计和开发中常常出现的一对概念。它们既是作好设计的途径,也是评价设计好坏的标准。"高内聚"是说,一个业务应当尽可能把它所涉及的功能和代码放到一个模块中;"低耦合"则是说,一个业务应当尽可能减小对其它业务或功能模块的依赖。并发
“高内聚低耦合”也是这么成双成对地出现app
这一对概念其实不只适用于软件行业。若是你是宅男/宅女,高内聚就是吃喝拉撒睡都不用出门,低耦合就是不用跟人打交道。若是你是上班族,高内聚就是工做都由本身说了算,低耦合就是跨组/跨部门的沟通协做少。若是你常跟政府部门打交道,必定还记得以往去政府办一个证实要跑八九个部门、盖十几个章的麻烦,这其实就是政府服务"低内聚"的恶果——后来政府精简办事流程,一个窗口盖完全部章,这就是一种"高内聚"的服务。若是你是苹果的重度用户,必定对"封闭生态环境"体会深入:它当然能提供很好的服务,可是深陷其中以后——iPhone、iPad、macbook、iCloud等——那么,即便其中某项服务无觉得继了、或者知足不了需求了,也没法轻易地脱身而出、改换门庭。这就是"高耦合"带来的难题。ide
一只“高内聚低耦合”的喵……
性能
WHY & WHY NOT学习
高内聚低耦合的优势和缺点都是显而易见的。测试
优势优化
若是一个模块、一个系统可以作到高内聚、低耦合,那么,它就具备了很是高的可扩展性。可扩展性高意味着“将来有无限可能”:功能不知足新需求了,在模块内部简单扩展就能知足;性能上达不到要求了,系统内部挖潜就能达标;技术太过陈旧要更新换代了,本身就能完成新陈代谢……ui
这么说可能有些费解,咱们仍是举例子吧。
对宅男/宅女来讲,高内聚就是吃喝拉撒睡都不用出门,低耦合就是不用跟人打交道。这样一来,我想吃披萨就吃披萨,想喝两碗豆浆就喝两碗豆浆,彻底不用顾虑别人想吃什么、别人会说什么。这样的生活惬意不?
对上班族来讲,高内聚就是工做都由本身说了算,低耦合就是跨组/跨部门的沟通协做少。这样一来,我想用数据集A就用数据集A,想用数据集B就用数据集B;想用Excel用Excel,想写脚本写脚本;想用PPT汇报就用PPT汇报,想用demo汇报就用demo汇报。这样的工做快乐不?
我反正是……
技术上……我仍是举个例子吧。咱们系统中有一个模块,用于处理用户短信验证操做。签约验证成功后,针对具体的业务还须要作一些后续处理。随着业务的不断发展,后续业务处理从最初的一套逻辑增长到如今的五套逻辑。此外咱们还作了一些技术优化,如优化库表结构、增长并发处理等,最后的流程大概是这样的:
短信验证模块的基本流程
因为整个短信验证模块、以及后续业务处理模块都作到了高内聚、低耦合(自吹自擂脸),所以,不管是业务扩展仍是技术优化,都只影响到了各自对应的模块,其它模块、功能对此毫无感知。尤为是业务扩展、增长一个后续业务处理模块时,其它后续业务处理模块丝绝不受影响。没有影响意味着开发不用改代码、测试不用回归测试、上线时间能够缩短、老代码里不会引入新问题……
可见,高内聚低耦合的设计能带来多赢的结果。对开发来讲,改动的代码固然是越少越好——高内聚低耦合的设计能减小要修改的代码量。对测试来讲,测试范围固然是越小越好——高内聚低耦合的模块只须要测试新增功能而不须要回归原有功能。对产品来讲,需求上线的时间固然是越短越好——高内聚低耦合的设计能减小开发和测试的工做量,上线时间天然也就变短了。对用户来讲,系统问题固然是越少越好——高内聚低耦合的设计至少能保证老代码正常运行,不会由于新功能而莫名崩溃。
你好了不?
缺点
优势如此显而易见,为何实际工做中不多有人认真执行“高内聚低耦合”的设计要求呢?
若是你是一个政府部门,你是愿意本身只盖一个章、让用户去跑其它部门盖完剩下的十几个章,仍是愿意让用户只来你这一个部门、你去跑其它部门改完全部的章?若是你是一家商店,你是愿意让用户把钱全都花在你的店里,仍是愿意提供一堆服务让用户去别的店铺消费?作软件设计也要面对“投入产出比”的考虑。若是一个良好设计的成本过高而收益过低、甚至与主要目标背道而驰,那么人们天然就会用脚投票、不使用这种设计。
前几年这种漫画没少见吧
“高内聚低耦合”的设计就经常会陷入这样的困境中。首先,要严格作到高内聚、低耦合,一般多要付出不少精力来作设计,还经常会增长很多的开发工做量。而这些额外成本有时并不必定能带来指望的结果。之前面说的短信验证功能模块为例,若是五种业务逻辑的差别都只有一两行代码,那么全用if-else的方式放在一个类中会是一种更合适的方法。可是,若是业务逻辑自己比较复杂、或者彼此之间差别比较大,还用if-else处理的话,最后代码会变成一团乱麻、快速腐化。所以,尽管咱们的设计多了六个类(一个业务分发类、五个不一样的业务处理类),并致使了前期开发时多花了一天半天的时间,但整个模块的可维护性、可扩展性都有很大提升,能够说是“过当”了吧。
这是短信验证模块目前的类图
其次,“高内聚低耦合”是一种原则性的设计准则。在现实中,原则性的东西通常都会为灵活性——好比工期啦,历史遗留问题啦,部门关系啦——让步。我曾经常常听到“之前就是这么作的,此次也这样处理吧”、“他们的接口就是这样的,咱们也没办法”这样的话,也常常看到由于这些缘由而放弃更好的设计,甚至所以而再也不思考有没有更好的设计。有时真让人感叹技术其实什么都改变不了。另外,原则性的东西每每太务虚而没法落到实处。“这个模块不够高内聚”,“这段代码的耦合度过高了”,具体是怎么不够高内聚?要改为怎样才能下降耦合度?彻底叫人丈二金刚摸不着头脑。最后,法学上有种罪名叫作“箩筐罪”,当你以为一个东西有问题、但又说不清楚具体是什么问题时,就能够把它纳入“箩筐罪”中——也就是所谓“xx罪是个框,什么都能往里装”。“高内聚低耦合”能够说是软件设计界的“箩筐罪”,只要想往里装就能往里装。例如前面那个短信验证功能模块,它真的知足了“高内聚低耦合”了吗?虽然通过精心设计,可是若是要挑,也还能挑出一箩筐毛病来。因此,“高内聚低耦合”的度很难把握,过于执着甚至可能走火入魔。这也是为何“高内聚低耦合”不多在实际工做中说起和应用的缘由之一。
原则和实践……经常就是这么残酷
HOW
有些问题能够靠技术来解决。例如,开发成本高这个问题在团队开发水平提升到必定层次以后就迎刃而解了;太过务虚的问题也能够经过学习和掌握SOLID、设计模式等具体的设计技能来解决。这些具体的技术会在之后慢慢讨论。可是非技术的问题——例如历史包袱、部门关系等,我就心有余而力不足了。
高内聚低耦合与抽象
虽然高内聚低耦合有上面这些问题,可是,在作业务抽象的设计时,咱们仍是要认真考虑、并遵照这个原则。由于高内聚低耦合不只是作好设计的途径、也是评价设计好坏的标准:对于面向对象的业务抽象设计来讲更是如此。
一个好的业务抽象必须能表达出本身“是什么”或者“能作什么”、而隐藏本身“怎么作”。高内聚、低耦合的理念正适合用来让业务抽象隐藏本身的实现细节。若是一个业务抽象不够内聚或者过分耦合,它必定会过多地把本身的实现细节泄露出去。还记得在《抽象》一文中出现的QueryService吗?它把queryFromRemote和queryFromLocal暴露到业务抽象外部,致使了使用接口时的种种不便,这就是不够高内聚的结果。还有ExcelService,这个接口与2003版的Excel文件格式过分耦合了,结果没法顺利地升级到20007版Excel上。