快速改善代码质量的20条编程规范
1.关于命名
- 命名的关键是能准确达意(不要刻意选择一些缩写命名 不好理解)
- 借助类的信息来简化属性、函数命名
//优化前 public class User { private String userName; private String userPassword; private int userAge; } //优化后 public class User { private String name; private String password; private int age; }
- 命名要可读、可搜索
- 比如查询方法统一用
getxxx()
方便输入.get的时候联想搜索 - 统一规范,比如统一用
addxxx()
而不是insertxxx()
来表示插入一条数据
- 比如查询方法统一用
- 接口和抽象类特殊命名
- 接口:一种是在接口中带前缀”I”,另一种是在接口的实现类中带后缀”Impl”
- 抽象类:可以加上”abstract”前缀
//接口命名1 public interface IUserService{} public class UserService implements IUserService{} //接口命名2 public interface UserService{} public class UserServiceImpl implements UserService{}
2.关于注释
- 注释需要写什么内容?
- 做什么
- 为什么
- 怎么做
- 如何用(针对较复杂的类和接口)
- 注释是不是越多越好?
- 注释太多,会影响代码的阅读
- 注释太多,会影响后期的维护成本(改代码需要同步修改注释,否则会对不上)
- 哪里写注释比较好?
- 类和函数一定要写注释(尽可能全面、详细)
- 函数内部注释相对少一点(依赖好的命名、提炼函数等提高代码可读性)
3.函数、类多大才合适?
- 尽量不要超过一个屏幕大小
4.一行代码多长最合适?
- 尽量不要超过IDE显示的宽度(否则得左右拉不方便看)
- 也不要太短,不然一句代码容易被拆成多长,也不利于阅读(也不整洁)
5.善用空行分割单元块
- 长函数里不同独立逻辑的代码块可以用空行分割(简洁、清晰,方便阅读也方便后续维护)
- 其他场景也可加空行分割
- 类的成员变量和函数之间
- 类的静态成员变量和普通成员变量之间
- 类的各函数之间
- 类的各个成员变量之间
public class UserService { @Autowired private UserMapper userMapper; @Autowired private NoticeService noticeService; public boolean login(int id) { //获取用户信息 User user = userMapper.selectById(id); if(user == null) { return false; } //登陆成功下发消息 boolean result = noticeService.sendLoginSuccess(user); return result; } }
6.四格缩进还是两格缩进?
- 推荐用两格缩进(节省空间,Java倾向于两格)
- 取决个人喜好/团队统一即可
7.大括号是否要另起一行?
- 不另起一行:节省代码行数(推荐)
- 另起一行: 左右括号可以垂直对齐(代码块一目了然)
8.类中成员的排列顺序
- 类:成员变量->函数
- 成员变量/函数:静态成员变量/函数->普通函数/函数
- 个人习惯:比较喜欢把成员变量放前面,函数放后面(每个public和依赖的private方法放一起)
9.把代码分割成更小的单元快
- 背景:我们一般看某个函数都是先看这个函数整体是什么功能,再看步骤(如果一行行看容易浪费时间而且不一定看得懂)
- 建议:拆分成多个独立功能的小函数
- 优点:方便阅读、易扩展
//优化前 public class UserService { public void bigMethod(){ //逻辑1 第一行 //逻辑1 第二行 //逻辑1 第三行 //逻辑1 第四行 //逻辑2 第一行 //逻辑2 第二行 //逻辑2 第三行 //逻辑3 第一行 } } //优化后 public class UserService{ public void bigMethod() { this.smallMethod1(); this.smallMethod2(); this.smallMethod3(); } public void smallMethod1(){ //逻辑1 第一行 //逻辑1 第二行 //逻辑1 第三行 //逻辑1 第四行 } public void smallMethod2(){ //逻辑2 第一行 //逻辑2 第二行 //逻辑2 第三行 } public void smallMethod3(){ //逻辑3 第一行 } }
*10.避免函数参数过多
根据不同逻辑拆分多个函数
public class UserService { //优化前 User getUser(String username, String phone); //优化后 User getUserByUsername(String username); User getUserByPhone(String phone); }
将函数参数封装成对象
public class UserService { //优化前 boolean register(String username,String password,int sex,String phone,String email); //优化后 boolean register(User user); } public class User{ private int id; private String username; private String password; private int sex; private String phone; private String email; }
11.勿用函数参数来控制逻辑
- 不要用boolean值控制内部逻辑(true走一个逻辑、false走另一个逻辑)
//例子:根据男女生做不同逻辑处理(分场景,不一定适用其他场景) public class UserService { //优化前 void login(String username, boolean isMale); //优化后 void loginForMale(String username); void loginForFemale(String username); }
12.移除过深的嵌套层次
- 去掉多余的if/else语句
- 使用continue、break、return等提前退出嵌套
- 调整执行顺序来减少嵌套(如提前判空再执行正常逻辑)
- for循环独立逻辑可抽出为一个个函数(参考自
《重构改善既有代码的设计》
)
13.学会使用解释性变量
常量取代魔法数字
public class UserService { //计算不同单位的毫秒值 public static final long ONE_DAY = 24 * 60 * 60 * 1000; public static final long ONE_HOUR = 60 * 60 * 1000; public static final long ONE_MINUTE = 60 * 1000; }
使用解释性变量来解释复杂表达式
//比如该例子的isToday就是解释性变量 public class UserService { public void test() { //判断是否当天 boolean isToday = this.isBefore(24) && this.isAfter(0); //... } } public class Time { public boolean isBefore(int hour) { //... } public boolean isAfter(int hour) { //... } }