很早就阅读过《代码整洁之道》(英文版Clean Code),当时博主是个青涩的菜鸟,正在为团队创造着混乱的代码。多年的工作中,屡次被别人的代码坑的苦不堪言,回想起当年我留下的代码,肯定也坑害了后来的同僚。当阅读JDK源码或者其他优秀开源工程时,叹服作者代码构建之精良,他们都有共同的特点:精确的变量名、恰到好处的设计模式、详细而不赘述的注释等等。如今重读本书,总结一下内容并加上自己的一些见解与大家分享。
代码是团队沟通方式工作的沟通,不只是电子邮件或者面对面语言交流,代码也是沟通方式之一。用代码实现需求,只是万里长征走完了第一步,必须让代码表达自己的设计思想。试想一下,你负责的功能被另外一个同事接手,如果你的代码结构清晰、注释合理,他就不用频繁的询问代码疑点,不用打断你的工作。编写代码的时候,应该考虑到别人的阅读感受,减少阅读障碍,为整个团队创造代码,而不是你自己。
让营地比来时更干净这是美国童子军规的谚语,美国童子军相当于半军事化管理的青少年夏令营。夏令营结束后孩子们离开营地,要打扫卫生保持整洁,让营地比来时更干净。在软件开发过程中,可以理解为不要破坏规则,不要引入混乱。如果团队已经制定了代码规范,比如类名必须有子系统前缀比如BiOrderService(Bi指BI业务部门),就继续遵循下去;再比如,团队已经提供了公共库比如MD5的加密,那就不要再次引入新的MD5库。很多新手程序员接活儿后,看到不喜欢的规范就另起炉灶,需要某些工具类也不询问老司机公共库有没有,直接引入自己熟悉的库,造成兼容性或者其他问题。
合适的命名合适的命名是头等大事,正如给新生儿起个好名字那样重要。不合适的命名通常是词不达意、误导观众、过度缩写等,由于英文并非我们的母语,找个合适的单词命名似乎真的很难。我建议是先把业务弄清楚,组织会议定下常用业务领域的单词,禁止组员各自发明。比如代码里使用canteen表示饭堂,那就不要再发明DinnerHall,既啰嗦又误导同僚。
看看反例: // 手机号 String phone = “13421800409”; // 获取地址 private String getDiZhi(); //修改密码 private void modifyPassword(String password1 ,String password2) 看看正例: // 手机号 mobileNo比phone更精确 String mobileNo= “13421800409”; // 避免英文拼音混杂 private String getAddress(); // 参数的命名要区分意义 private void modifyPassword(String oldPassowrd,String newPassword) 短小的方法方法有多短小才合适没有定论,但是长达500行的一个方法,绝对让阅读者起杀人之心。过长的方法,让阅读者不知道从何看起,看了前面忘记后面。将复杂的方法,拆分成逻辑相对简单的短方法。
看看反例: // 获取个人信息 Private UserDTO getUserDTO(Integer userId) { //获取基本信息 … 此处写了10行 //获取最近的一次订单信息 … 此处写了30行 // 获取钱包余额、可用优惠券张数等 ... 此处写了30行 return userDTO; } 看看正例: // 获取个人信息 Private UserDTO getUserDTO(Integer userId) { //获取基本信息 UserDTO userDTO= getUserBasicInfo(userId); //获取最近的一次订单信息 userDTO.setUserLastOrder(getUserLastOrder(userId)); // 获取钱包、可用优惠券张数等 userDTO.setUserAccount(getUserAccount(userId)); return userDTO; } Private UserDTO getUserBasicInfo(userId); Private UserLastOrder getUserLastOrder(userId); Private UserAccount getUserAccount(userId); 减少if/else嵌套为什么要减少嵌套,难道嵌套看上去不时尚吗?我曾经看到某位同事的一段代码嵌套达到9层,他自己再去维护的时候都看晕了。代码过度嵌套的结果是只有原作者才能读懂,接盘侠一脸茫然。
看看反例: // 修改用户密码,这个例子只有3层嵌套,很温柔了 public boolean modifyPassword(Integer userId, String oldPassword, String newPassword) { if (userId != null && StringUtils.isNotBlank(newPassword) && SpringUtils.isNotBlank(oldPassword)) { User user = getUserById(userId); if(user != null) { if(user.getPassword().equals(oldPassword) { return updatePassword(userId, newPassword) } } } } 看看正例: // 修改用户密码 Public Boolean modifyPassword(Integer userId, String oldPassword, String newPassword) { if (userId == null || StringUtils.isBlank(newPassword) || StringUtils.isBlank(oldPassword)) { return false; } User user = getUserById(userId); if(user == null) { return false; } if(!user.getPassword().equals(oldPassword) { return false; } return updatePassword(userId, newPassword); }