tags: 重构,优雅代码,读书笔记
在《重构》一书中,列举了一些代码的坏味道,同时以举例方式讲解了重构代码的一些手法,本文是读书后的关于如何写好代码的笔记,主要包括可读性、代码职责、面向对象思维方面。
可读性
下面是一些提升代码可读性的手段、方法。
Extract Method
当一个方法比较复杂、行数较多时,读起来令人费解,这时应该抽取出一个个小段代码的方法,且合理的命名方法,主方法中调用这些方法完成它所做的事情。
当然也不只是方法复杂时需要抽取方法。
优势:
1、通过方法命名,让主方法调用这些方法就能清晰表达主方法的流程,不需要通过注释来解释代码作用
2、方法小了,代码简洁清晰,易于复用
引入解释性变量
代码逻辑繁杂时,或一些复杂运算,可以引入变量,并通过对变量的命名来提升可读性。
如:
methodB(ClassX.methodC(methodA(a, b)))
可以改为:
int someValue = ClassX.methodC(methodA(a, b));
methodB(someValue);
不要对方法参数重新赋值
如
void method(Object A){
A = new Object();
}
引入参数对象
当方法参列表较长时,提取对象进行包装。一般建议参数个数≤3。
Rename Method/Class
根据代码的功能职责合理命名,便于理解
用对象取代直接使用数组
用常量取代特殊意义的数字
其目的引入解释性变量类似
分解复杂条件表达式
将复杂的表达式拆分成多个简短的表达式,每一个明确其意义。
如:
if(a.status != null && a.status = true && date > XXX && date < YYY){
......
}
取代为:
if(validStatus(a.status) && valiadDate(date) ){
......
}
可以更清楚的表达出条件判断的含义
以特殊检查取代嵌套的if else
if与else本身表达的是平级的关系,如果是某些特殊罕见条件特殊处理,采用if return的形式予以重视。
这样能够清晰的体现代码的主流程,不被一些特殊的处理掩盖,读起来更顺畅。
如:
boolean flag;
if(conditionX){
flag = false;
} else{
if(conditionY){
flag = false;
} else{
do something……
flag = calculate();
}
}
return flag;
改为:
if(conditionX) return false;
if(conditionY) return false;
do something……
flag = calculate();
return flag;
以异常取代错误码
服务内部不要采用错误码来表示错误,如return -1表示失败,而应该抛出异常表达
后端与前端服务间的交互可采用errorCode的方式。
关于异常可参考本人另一篇文章: https://my.oschina.net/hebaod...
代码职责
我们经常说面向对象的单一职责原则,大到一个系统、模块的职责边界划分,小到一个类、一个方法的职责。
清晰的划分类、方法的职责,保持其单一、稳定的功能,能避免日后代码越来越臃肿。
下面是关于代码职责的处理方法。
Move Method/Field
某个方法不应该属于这个类或package,移动方法到合适的地方。
某个属于不应该属于该对象,移动之。
Extract Class
类越来越大,如某个Service的public方法越来越多,功能混杂,考虑抽取不同的class维护这些方法或属性。
面向对象的思维
用多态取代条件表达式
代码中出现多个if或switch case语句根据不同的条件,采取不同的行为时,应该采用多态的思想。
如:
switch(var){
case v1:
behavior1();
break;
case v2:
behavior2();
break;
defalut:
behavior3();
}
可以提炼一个interfa Behavior,根据不同var创建不同的实现类,最后只需要调用behavior.method即可,也是一种策略模式的体现。
但是,上述说法还没彻底解决switch case的问题,因为要创建不同实现类,一种方法是定义一个map存储映射关系。
Method/Field 上移到超类/下移到子类
采用继承时,需要区分出某些属性,方法到底是共性还是特性,共性就应该上移到超类中。特性即仅某些子类才具有,应该下移到子类。合理的进行抽象。
提炼超类/接口/子类
发现代码中有一些共同或类似的行为属性时,要考虑提炼超类or接口。定义好抽象的关系,使代码保持内聚。
关于抽象类与接口参考:https://www.zhihu.com/questio...
组合与继承的选择
一般来说组合优先于继承,组合表达的是has a的关系,继承表达的是is a的关系。
组合的扩展性更强,且java不支持多继承。更多关于组合与继承的讨论自行Google吧。
ps:个人blog地址:https://my.oschina.net/hebaod...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。