高扩展的诀窍:细粒度设计,只做一件事 ¶
作者:KK
发表日期:2016.4.8
这篇文章对三年以上的熟手来说我相信已经不是什么新鲜内容,可以跳过,我主要是告诫成长中的新手们的
正如标题所说,写代码时把代码封装起来,并且一个函数/方法只做一件事,那么这个函数/方法的重用率就会被提高,由于大家经常都在写对象和方法,后面我统一叫方法吧
为什么说重用率提高了呢?因为它做的事情就是那一件,那如果其它模块也需要做这样的事的时候,自然就可以重复利用这个方法的代码了
可是如果一个方法做的事情有2件,别的代码只需要它做其中1件事,不需要它去做另1件,这个函数非要捆绑销售2件事情的话,那别人就不调你算了,干脆另外造轮
所以不要搞捆绑销售才能被更多需求者接纳
直面粗粒度 ¶
但是通常这样细粒度设计的话,所有事情始终都要去做的,既然将A事情和B事情分别给两个方法实现了,那还是要有一个方法去调用AB两件事情的相关方法去全部做一通
那如果只用1个方法做2件事,那类就只有1个方法;可分成2个方法做2件事,再用1个方法调用这2个方法,这不共3个方法了吗?
新手们常常从代码成本上审视这些问题,觉得代码写多了就是麻烦事,第一意识就是不愿意去干,我认为这种价值观应该纠正过来
我们更应该考虑代码可维护性和可读性这些问题,个人阅读过好些开源项目的代码,人家都把一个类的各种事情很得很细去设计,读起来真的很顺利,而不是一大片臃肿的代码难以理解整体目的
回正题,有了细粒度设计,往往还需要一个粗粒度的方法调用这些细粒度的方法,所以粗粒度的方法通常还是要有的;而细粒度的存在价值在下面将会提及
细粒度设计的好处 ¶
提高重用性
这个前面说过了
提高可维护性
维护这部分代码逻辑时,你看到的代码范围将会是很小,并且很清楚它仅仅就在做这么一件小事情,你在里面定义的新变量很清楚有没有冲突
但是如果太多不同的程序逻辑都挤在一个方法里的时候,你在其中第3块逻辑增加新变量时,可能会存在命名冲突的问题(特别是脚本语言).再就是还有些错综复杂的逻辑交杂,造成了互相依赖,其实是可以互相分离的,这样发展下去会导致这个方法越来越难维护,每次修改后的风险率越来越高
方便做单元测试
单元测试就是针对单元做测试,如果这个方法已经不是"单元"级别,却因为增加了太多逻辑在里面变成了"功能"级别的话,那测试逻辑的复杂度会提高很多
保持细粒度设计,那针对这个方法的测试就好说很多了,这样写单元测试也不会让人厌倦,还能将更多其它细的方法分摊给其他人去写单元测试,而不是一个人针对一个粗粒度的方法进行超多逻辑的单元测试
满足未来可能的需求,不用修改直接用
一个类的粗粒度方法往往是在需求刚开始出来时的程序代码最先被调用的,如果保持了细粒度的设计,那么在未来有其它需求只需要用到其中一个功能时,那么新的功能调用代码块只要直接调用类的其中一个方法就可以,而不需要开发人员去增加方法,或者将原来的粗方法细分开来
说实话,这就是"提前做好细化设计,满足未来的需求"的样子,而且有些未来并不一定会发生,这样做值不?
我觉得还是值的,因为细粒度设计并不是单纯"为未来的变化做准备",而还是有它的其它方面的好处的
而当未来有新需求只要这一个粒度的方法时,只要直接调用就是了,根本不用改什么嘛;但是如果有的人说"到时候再改不也是一样?",那么根据我的经验看来,实际中的开发人员在需要细化的时候,很少有意识到把粗方法的代码提取出来封装,而是直接另开一个方法写了相似的代码.这是责任心的问题,实际上有责任心的开发人员并不是遍地都是,所以提前做好细粒度的开发,也是为了防这一点
这里就是关于"高扩展的诀窍"的一方面,扩展是未来的东西,前期准备好了,未来才好扩展,前期没做好准备,未来要扩展就拖拖拉拉,甚至难以扩展;这方面开源项目都很清楚,所以开源项目都是把对象方法分得很细,让开发者自由组合出自己需要的功能,可以说,框架整体设计得细的开源项目,那它的扩展性绝对差不到哪里
学会把握 ¶
我们的程序设计不能没有细粒度,但也不能完全细粒度,如果以最严格地训条来要求践行细粒度的程序设计,那么每一两行代码都可以封装成一个方法了
我们要学会把握,点到即止,是否再把某些代码再封装成一个方法,这通常不是按照行数来的,而是它所计算的事情跟当前方法的代码有多大关系,如果它独立又是否符合一个对象"应有的方法"
总的来说粒度设计是个很抽象的话题,希望大家用心领悟;简单点,你发现一个方法的代码快超过1个屏幕的时候,赶紧看看哪些代码可以封装起来作为一个独立的方法,返回数据提供给外面使用就行了
接下来在以后的编程工作中,不断地琢磨你项目中哪些代码可以封装起来重用的,哪些代码阅读起来混乱,封装一部分独立开去后阅读很清晰的,那就封装起来.做着做着自然就掌握了细粒度设计的一个合适的度了