代码是团队沟通方式

工作的沟通,不只是电子邮件或者面对面语言交流,代码也是沟通方式之一。用代码实现需求,只是万里长征走完了第一步,必须让代码表达自己的设计思想。试想一下,你负责的功能被另外一个同事接手,如果你的代码结构清晰、注释合理,他就不用频繁的询问代码疑点,不用打断你的工作。编写代码的时候,应该考虑到别人的阅读感受,减少阅读障碍,为整个团队创造代码,而不是你自己。

让营地比来时更干净

这是美国童子军规的谚语,美国童子军相当于半军事化管理的青少年夏令营。夏令营结束后孩子们离开营地,要打扫卫生保持整洁,让营地比来时更干净。在软件开发过程中,可以理解为不要破坏规则,不要引入混乱。如果团队已经制定了代码规范,比如类名必须有子系统前缀比如BiOrderService(Bi指BI业务部门),就继续遵循下去;再比如,团队已经提供了公共库比如MD5的加密,那就不要再次引入新的MD5库。很多新手程序员接活儿后,看到不喜欢的规范就另起炉灶,需要某些工具类也不询问老司机公共库有没有,直接引入自己熟悉的库,造成兼容性或者其他问题。

合适的命名

合适的命名是头等大事,正如给新生儿起个好名字那样重要。不合适的命名通常是词不达意、误导观众、过度缩写等,由于英文并非我们的母语,找个合适的单词命名似乎真的很难。我建议是先把业务弄清楚,组织会议定下常用业务领域的单词,禁止组员各自发明。比如代码里使用canteen表示饭堂,那就不要再发明DinnerHall,既啰嗦又误导同僚。

  1. // 手机号
  2. String phone = 13421800409”;
  3. // 获取地址
  4. private String getDiZhi();
  5. //修改密码
  6. private void modifyPassword(String password1 ,String password2)
  1. // 手机号 mobileNo比phone更精确
  2. String mobileNo= 13421800409”;
  3. // 避免英文拼音混杂
  4. private String getAddress();
  5. // 参数的命名要区分意义
  6. private void modifyPassword(String oldPassowrd,String newPassword)

短小的方法

方法有多短小才合适没有定论,但是长达500行的一个方法,绝对让阅读者起杀人之心。过长的方法,让阅读者不知道从何看起,看了前面忘记后面。将复杂的方法,拆分成逻辑相对简单的短方法。

  1. // 获取个人信息
  2. private UserDTO getUserDTO(Integer userId)
  3. {
  4. //获取基本信息
  5. 此处写了10
  6. //获取最近的一次订单信息
  7. 此处写了30
  8. // 获取钱包余额、可用优惠券张数等
  9. 此处写了30
  10. return userDTO;
  11. }
  1. // 获取个人信息
  2. private UserDTO getUserDTO(Integer userId)
  3. {
  4. //获取基本信息
  5. UserDTO userDTO= getUserBasicInfo(userId);
  6. //获取最近的一次订单信息
  7. userDTO.setUserLastOrder(getUserLastOrder(userId));
  8. // 获取钱包、可用优惠券张数等
  9. userDTO.setUserAccount(getUserAccount(userId));
  10. return userDTO;
  11. }
  12. private UserDTO getUserBasicInfo(Integer userId);
  13. private UserLastOrder getUserLastOrder(Integer userId);
  14. private UserAccount getUserAccount(Integer userId);

减少if/else嵌套

为什么要减少嵌套,难道嵌套看上去不时尚吗?我曾经看到某位同事的一段代码嵌套达到9层,他自己再去维护的时候都看晕了。代码过度嵌套的结果是只有原作者才能读懂,接盘侠一脸茫然。

  1. // 修改用户密码,这个例子只有3层嵌套,很温柔了
  2. public boolean modifyPassword(Integer userId, String oldPassword, String newPassword) {
  3. if (userId != null && StringUtils.isNotBlank(newPassword) && SpringUtils.isNotBlank(oldPassword)) {
  4. User user = getUserById(userId);
  5. if (user != null) {
  6. if (user.getPassword().equals(oldPassword) {
  7. return updatePassword(userId, newPassword)
  8. }
  9. }
  10. }
  11. }
  1. // 修改用户密码
  2. Public Boolean modifyPassword(Integer userId, String oldPassword, String newPassword) {
  3. if (userId == null || StringUtils.isBlank(newPassword) || StringUtils.isBlank(oldPassword)) {
  4. return false;
  5. }
  6. User user = getUserById(userId);
  7. if(user == null) {
  8. return false;
  9. }
  10. if(!user.getPassword().equals(oldPassword) {
  11. return false;
  12. }
  13. return updatePassword(userId, newPassword);
  14. }

正例采用卫语句减少了嵌套,但是并非所有场景都适合这样改写。如果不适合,可以将关联性高的逻辑抽取成一个独立的方法减少嵌套。

抽离try/catch

大家有没有见过一个超长的方法,从头到尾被一个try/catch照顾着?博主经历过的项目中,这种不负责的写法比比皆是。并非每行代码都会抛出错误,只要将会抛出错误的业务放在一个独立的方法即可。

  1. // 获取个人信息
  2. private UserDTO getUserDTO(Integer userId)
  3. {
  4. try {
  5. //获取基本信息
  6. ... 此处写了10
  7. //获取最近的一次订单信息.
  8. ...此处写了20
  9. // 获取钱包、可用优惠券张数等
  10. ...此处写了20
  11. }catch (Exception e) {
  12. logger.error(e);
  13. return null;
  14. }
  15. }
  16. return userDTO;
  17. }
  1. // 获取个人信息
  2. private UserDTO getUserDTO(Integer userId)
  3. {
  4. //获取基本信息
  5. UserDTO userDTO= getUserBasicInfo(userId);
  6. //获取最近的一次订单信息
  7. userDTO.setUserLastOrder(getUserLastOrder(userId));
  8. // 获取钱包、可用优惠券张数等
  9. userDTO.setUserAccount(getUserAccount(userId));
  10. return userDTO;
  11. }
  12. private UserDTO getUserBasicInfo(Integer userId);
  13. private UserLastOrder getUserLastOrder(Integer userId);
  14. private UserAccount getUserAccount(Integer userId){
  15. try{
  16. // TODO
  17. } catch ( Exception e)
  18. { //TODO }

封装多个参数

如果方法参数将超过3个,建议放在类中包装起来,否则再增加参数时,由于语义的强耦合会导致调用方语法错误。在后台管理中的分页查询接口,常常会有很多查询参数,而且有可能增加,封装起来是最好的

  1. // 分页查询订单 6个参数
  2. public Page<Order> queryOrderByPage(Integer current,Integer size,String productName,Integer userId,Date startTime,Date endTime,Bigdecimal minAmount ,Bigdecimal maxAmount) {
  3. }
  1. @Getter
  2. @Setter
  3. public class OrderQueryDTO extends PageDTO {
  4. private String productName;
  5. private Integer userId;
  6. private Date startTime;
  7. private Date endTime;
  8. private Bigdecimal minAmount ;
  9. private Bigdecimal maxAmount;
  10. }
  11. // 分页查询订单 6个参数
  12. Public Page<Order> queryOrderByPage(OrderQueryDTO orderQueryDTO) {
  13. }

第三方库

Lombok

Lombok组件通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法
举例如下:
@Setter 注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
@Getter 使用方法同上,区别在于生成的是getter方法。
@ToString 注解在类,添加toString方法。
@EqualsAndHashCode 注解在类,生成hashCode和equals方法。
@NoArgsConstructor 注解在类,生成无参的构造方法。
@RequiredArgsConstructor 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。
@AllArgsConstructor 注解在类,生成包含类中所有字段的构造方法。
@Data 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。

  1. Public class Order {
  2. private Integer userId;
  3. public Integer getUserId() {
  4. return userId;
  5. }
  6. public void setUserId(Integer userId) {
  7. return this.userId = userId;
  8. }
  9. }
  1. @Getter
  2. @Setter
  3. Public class Order {
  4. private Integer userId;
  5. }

Apache Commons系列

Apache Commons系列组件给我们提供了关于字符串、集合、IO操作等工具方法。这些组件是个大宝库,提供了不少轮子。

组件 介绍
beanUtils JavaBean进行各种操作,克隆对象、属性等等
codec 处理常用的编码方法的工具类包,例如DES、SHA1、MD5、Base64等.
collections java集合框架操作
configuration java应用程序的配置管理类库
io io工具的封装
lang Java基本对象方法的工具类包 如StringUtils、ArrayUtils等等.
logging 提供的日志接口
net 提供了客户端和服务器端的数据验证框架
  1. 1: 判断集合是否为空:
  2. CollectionUtils.isEmpty(null): true
  3. CollectionUtils.isEmpty(new ArrayList()): true
  4. CollectionUtils.isEmpty({a,b}): false
  5. 2: 判断集合是否不为空:
  6. CollectionUtils.isNotEmpty(null): false
  7. CollectionUtils.isNotEmpty(new ArrayList()): false
  8. CollectionUtils.isNotEmpty({a,b}): true
  9. 32个集合间的操作:
  10. 集合a: {1,2,3,3,4,5}
  11. 集合b: {3,4,4,5,6,7}
  12. CollectionUtils.union(a, b)(并集): {1,2,3,3,4,4,5,6,7}
  13. CollectionUtils.intersection(a, b)(交集): {3,4,5}
  14. CollectionUtils.disjunction(a, b)(交集的补集): {1,2,3,4,6,7}
  15. CollectionUtils.disjunction(b, a)(交集的补集): {1,2,3,4,6,7}
  16. CollectionUtils.subtract(a, b)(AB的差): {1,2,3}
  17. CollectionUtils.subtract(b, a)(BA的差): {4,6,7}