编码坏味道列表

前言

在日常编码的过程中,大家要时刻警惕代码中存在的坏味道,要经常对原有的代码做重构,下面会列举一些代码中普遍存在的坏味道。


1、缺少业务含义的命名

1、 命名过于宽泛

这个在我的项目中其实存在很多,大家经常的命名大多都会以data、info、process、handle、build,manage等开头或者结尾,但其实这些命名过于宽泛,大家也不愿意花时间去想一个恰当的名字。

2、用技术术语命名

在这里插入图片描述

这种在我的项目中随处可见,就比如一个变量叫做bookList,原因就是它对应的类型是List,还有上面的Map,这种是基于实现细节命名的,编程的时候有一个重要原则就是面向接口而非实现,原因是接口是稳定的,而实现是易变的,就比如上面entityMap,我如果后续返回的改成了List,那它的名字也要相应做修改。

3、命名遵循的规范

  1. 描述意图,而非细节
  2. 面向接口编程,因为接口是稳定的,而实现是易变的
  3. 别用技术术语命名
  4. 好的命名,应该是体现业务含义的命名

2、乱用英文

1、命名规则

  1. 类名应该是一个名词,表示一个对象
  2. 方法名是一个动词,或者是动宾短语,表示一个动作
  3. 参数,属性是名词

2、英语使用不当

  1. 注意英语拼写错误
  2. 不准确的英语词汇
  3. 违反语法规则

3、解决办法

  1. 执行代码规范
  2. 建立团队词汇表
  3. 经常性进行代码review

3、重复代码

1、赋值粘贴的代码

现在在很多时候写代码仍然避免不了复制粘贴,基本的做法就是把代码复制过来,改动几个地方,然后泡一下就可以了。但是通常情况下,只要这些复制代码其中有一点逻辑要修改,就意味着所有复制粘贴的地方都要修改 ,所以一般可能只是一个简单的需求,可以改动的地方特别多。

2、结构重复的代码

有些代码虽然看起来命名不一样,但其实结构上执行的流程是一指定的,这个时候就需要把这个结构提取出来,这样后续有一些通用的调整就不用四处修改了。

3、if,else中的语句高度相似

如下面这段代码,只有最后一个参数不同,这也是一种代码冲突,下面优化的代码就是把变化的点提取出来了。

if (user.isEditor()) {
  service.editChapter(chapterId, title, content, true);
} else {
  service.editChapter(chapterId, title, content, false);
}

boolean approved = user.isEditor();
service.editChapter(chapterId, title, content, approved);

4、解决办法

不要重复自己,不要复制粘贴

4、长函数

1、长函数的产生

  1. 平铺直叙写代码,把不同层次不同逻辑的代码写到同一个方法中
  2. 一次增加一点点代码,日积月累就变成了长函数

2、消灭长函数的方法

  1. 定义好函数长度的标准
  2. 做好“关注点”分离,让每个函数的粒度尽量小,尽量只做一件事
  3. 坚守"童子军军规",让营地比你来时更干净

3、解决办法

提取函数

5、大类

1、产生大类的原因

  1. 指责不单一
  2. 字段未分组

2、解决办法

遵循软件设计的原则,单一指责原则,尽量把大类的职责拆分的更细,拆分成不同职责的小类。

6、长参数列表(方法中的参数列表特别长)

1、消灭长参数

  1. 参数数量多导致的长函数,把变化频率相同的封装成一个类,变化频率不同的多个变化频率的可以封装成多个类,静态不变的,可以成为软件结构的一部分
  2. 标记参数导致的长函数,可以根据标记参数把函数拆分成多个函数

2、解决办法

  1. 将参数列表封装成对象
  2. 移除标记参数

7、滥用控制语句

1、坏味道呈现形式

  1. 嵌套的代码
  2. else语句
  3. 重复的switch
  4. 循环语句

2、编程规则

  1. 函数至多有一层缩进
  2. 不使用else关键字
  3. 使用卫语句代替嵌套的条件表达式
  4. 使用多态代替switch

8、缺乏封装

1、坏味道呈现方式

  1. 连续的函数调用
  2. 基本类型偏执

2、编程规则

  1. 封装所有的基本类型和字符串
  2. 隐藏委托关系
  3. 使用对象代替基本类型
  4. 遵循迪米特法则
    每个单元对其它单元只拥有有限的知识,而且这些单元是与当前单元有紧密联系的;
    每个单元只能与其朋友交谈,不与陌生人交谈;
    只与自己最直接的朋友交谈。

9、可变的数据

1、坏味道呈现方式

  1. 暴露的细节(set)
  2. 可变的数据
  3. 全局数据

2、编程规则

  1. 限制变化
  2. 尽可能编写不变类
  3. 区分类的性质,实体对象要限制数据变化,而值对象要设计成不变类
  4. 移除设置函数。

10、变量的声明与赋值分离

1、坏味道呈现方式

变量的声明和赋值间隔很远,且赋值方式较为复杂。

2、编程规则

  1. 在声明前面加final,用不变性约束代码,能使用final尽量使用final,限制变量的赋值
  2. 变量最好一次性完成初始化
  3. 使用声明式的方式进行集合的初始化

11、依赖混乱

1、坏代码呈现方式

  1. 缺少防腐层,业务与外部接口耦合,如平时我们接受请求的request对象,他可能在对应的service也需要依赖这个对象,那么他属于哪一层,这就有些混乱了,所以可以引入防腐层,在service中添加对应的BO
  2. 业务代码中出现具体实现类

2、编码规则

  1. 引入防腐层,将业务与外部接口隔离
  2. 引入模型,将业务与具体实现隔离
  3. 高层模块不应该依赖于底层模块,二者应该依赖于抽象
  4. 抽象不应该依赖于细节,细节应该依赖于抽象

12、不一致的代码

1、坏味道呈现方式

  1. 命名中的不一致
  2. 方案中的不一致
  3. 代码中的不一致

2、编码规则

  1. 团队统一编码方案
  2. 提取函数,将不同层次的内容放到不同函数中,保持代码在各个层面上的一致性。

13、落后的代码风格

1、具体案例

  1. 函数时编程
  2. java8引入的Optional

2、 编程规则

  1. 声明式编程
  2. 写短小的函数,不要在lambda中写过多代码。
  3. 不断学习新的编码风格,不断改善自己的代码

14、代码评审

  1. 代码评审的本质是沟通反馈,尽可能多做代码评审,尽可能多暴露问题出来。
  2. 代码评审的角度应该从实现方案的正确性,算法的正确性,代码的坏味道
  3. 代码评审的极致是结对编程

15、新需求破坏原有代码

1、 坏代码呈现方式

  1. 增加新接口
  2. 改动实体字段

2、 编程规则

  1. 对外提供的接口越少越好
  2. 仔细分析实体扮演的角色,防止后续大量的改动
  3. 谨慎的对待接口和实体的变动。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值