第十九计:避免类的臃肿
在我接触过的大部分项目中,总会有一个“大胖子“类特别惹眼,一般来说,这“大胖子“实际上是整个系统的核心类之一,之所以“胖“,主要原因是很多人都会把自己需要的函数加到这个类中,却没有人主动请缨来为它“减肥“。可以通过以下几种方式来为它“瘦身”:
1、按照某种特性(如功能、类型等)将这个类拆分成多个类。
2、合并冗余函数,保持函数粒度的最小化。
3、去除重复代码。
如果实在不能再“瘦”了,那就通过实现相应的接口,让它“看上去很瘦“,举个例子:
public class BigBoy{ public void foo1(); public void foo2(); public void foo3(); public void foo4(); public void foo5(); public void foo6(); public void foo7(); public void foo8(); public void foo9(); // 还有很多... }
这个类有很多函数,这让类的使用者很头疼,没办法,它不能再“瘦“了,不过,我们可以根据某种特性把这些函数抽象成多个接口,例如foo1、foo2、foo3可以抽象成一个接口:
public interface LittleBoy{ public void foo1(); public void foo2(); public void foo3(); }
然后让BigBoy实现这个接口,并提供一个将BigBoy变成LitterBoy的函数:
public class BigBoy implements LittleBoy{ public LittleBoy asLittleBoy{) return this; } public void foo1(); public void foo2(); public void foo3(); public void foo4(); public void foo5(); public void foo6(); public void foo7(); public void foo8(); public void foo9(); // 还有很多... }
这样,类的使用者得到将是“瘦版“的BigBoy,使用难度大大降低了,因此,对于需要使用该类所有函数中某个子集的用户,我们可以提供一个包含该函数子集的接口实现对象即可。
第二十计:保持代码风格的一致性
程序员或多或少都有各自的代码风格,当我们看和自己风格不同的人写的代码时都觉得有点别扭,甚至会影响读代码的流畅性,记得以前有个同事把for语句当if语句用,像下面这样,太个性了,看他的代码真有点头疼。
for(;value>10;){ ... }
整个程序保持一致的代码风格还是比较重要的,如果看着就像一个人写那就太到位了,所以,最好能在项目初期就统一程序的命名规范、通过逻辑处理规范、注释规范等。
第二十一计:成员变量要封装
大部分情况下,类中的成员变量都应该被声明为私有的,为那些需要被其他类访问的变量增加set或者get函数。如果成员变量声明为公有的,那么类就失去了对它们的控制权!封装成员变量有以下几个好处:
1、在为成员变量赋值时进行有效性校验或其他预处理操作。
2、在返回成员变量的值时进行二次包装,当该变量不可用或未初始化时返回默认值。
为成员变量分别增加set和get函数是一件挺繁琐的事情,很多人嫌麻烦,觉得公有成员变量更方便,不过从可维护性和可扩展性的角度看,添加set和get是值得的,Eclipse中可以自动生成set和get函数的,非常方便。
第二十二计:用自注释性变量代替复杂条件
嵌套层次较深的IF判断、没有注释的复杂条件大大增加了程序的逻辑复杂性,严重降低代码的可读性。对于子条件较多的条件判定,可以为各个子条件引入具有自注释性的临时变量来降低复杂性。例如下面是判断登录用户是否能进入网站的后台管理界面:
if(userName!=null && userName.equals(name) && (userState != INACTIVE || userState != DELETE) && userPassword!=null && userPassword.equals(password) && (userGroup == "Manager" || userGroup == "Root")){ ... }
下面是修改后的版本:
boolean isUserNameValid = userName!=null && userName.equals(name); boolean isUserActive = userState != INACTIVE || userState != DELETE; boolean isUserPasswordCorrect = userPassword!=null && userPassword.equals(password); boolean isUserHasAuth = userGroup == "Manager" || userGroup == "Root";
if(isUserNameValid && isUserActive && isUserPasswordCorrect && isUserHasAuth){ ... }
第二种方式不仅使条件判断更具有可读性,还能重用子条件。
第二十三计:避免重复代码
重复代码是破坏程序可维护性的重量级选手之一,大量的重复代码会使代码量膨胀,修改重复的代码也很繁琐,改了一处后必须同时修改和它重复的代码,因此非常引入Bug,当有人修改了某处代码而忘记修改其他除重复的代码,那么Bug就出现了。所以,一旦要拷贝某段代码,请先考虑把这段代码通用化。
第二十四计:增加注释
记得在第一个公司工作的时候,公司很多程序员的代码注释率在40%左右,一般都是先写注释,然后紧接着写代码,因为注释也是一种文档。很多人觉得写注释浪费时间或者没有必要,所以他们的代码中没有绿色,或者只是星星点点,如果代码有一定的复杂性,那么其他人看这部分代码可能会比代码作者要费劲的多,注释就是帮助别人快速理解自己写的代码。