Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

快速改善代码质量的 20 条编程规范 下 #27

Open
NewBrandSTONE opened this issue Feb 17, 2020 · 0 comments
Open

快速改善代码质量的 20 条编程规范 下 #27

NewBrandSTONE opened this issue Feb 17, 2020 · 0 comments

Comments

@NewBrandSTONE
Copy link
Owner

  1. 把代码分割成更小的单元块。

  2. 优先处理异常情况。

  3. 避免函数参数过多。

    • 考虑函数是否职责单一。
    • 将函数参数封装成对象。
  4. 勿用函数参数来控制逻辑。

    • 示例

      public void buyCourse(long userId, long courseId, boolean isVip);
      
      // 将其拆分成两个函数
      public void buyCourse(long userId, long courseId);
      public void buyCourseForVip(long userId, long courseId);
    • 如果函数是 private 私有函数,影响范围有限,或者拆分之后两个函数经常同时被调用,可以酌情考虑保留标识参数。

    • 根据参数是否为 null 来控制逻辑的情况。也可以拆分成多个函数。

      public List<Transaction> selectTransactions(Long userId, Date startDate, Date endDate) {
        if (startDate != null && endDate != null) {
          // 查询两个时间区间的transactions
        }
        if (startDate != null && endDate == null) {
          // 查询startDate之后的所有transactions
        }
        if (startDate == null && endDate != null) {
          // 查询endDate之前的所有transactions
        }
        if (startDate == null && endDate == null) {
          // 查询所有的transactions
        }
      }
      
      // 拆分成多个public函数,更加清晰、易用
      public List<Transaction> selectTransactionsBetween(Long userId, Date startDate, Date endDate) {
        return selectTransactions(userId, startDate, endDate);
      }
      
      public List<Transaction> selectTransactionsStartWith(Long userId, Date startDate) {
        return selectTransactions(userId, startDate, null);
      }
      
      public List<Transaction> selectTransactionsEndWith(Long userId, Date endDate) {
        return selectTransactions(userId, null, endDate);
      }
      
      public List<Transaction> selectAllTransactions(Long userId) {
        return selectTransactions(userId, null, null);
      }
      
      private List<Transaction> selectTransactions(Long userId, Date startDate, Date endDate) {
        // ...
      }
  5. 函数设计职责要单一。

    public boolean checkUserIfExisting(String telephone, String username, String email)  { 
      if (!StringUtils.isBlank(telephone)) {
        User user = userRepo.selectUserByTelephone(telephone);
        return user != null;
      }
      
      if (!StringUtils.isBlank(username)) {
        User user = userRepo.selectUserByUsername(username);
        return user != null;
      }
      
      if (!StringUtils.isBlank(email)) {
        User user = userRepo.selectUserByEmail(email);
        return user != null;
      }
      
      return false;
    }
    
    // 拆分成三个函数
    public boolean checkUserIfExistingByTelephone(String telephone);
    public boolean checkUserIfExistingByUsername(String username);
    public boolean checkUserIfExistingByEmail(String email);
  6. 移除过深的嵌套层次

    • 考虑 if 判断合并在一起,移除不需要的 else 语句。

      // 示例一
      public double caculateTotalAmount(List<Order> orders) {
        if (orders == null || orders.isEmpty()) {
          return 0.0;
        } else { // 此处的else可以去掉
          double amount = 0.0;
          for (Order order : orders) {
            if (order != null) {
              amount += (order.getCount() * order.getPrice());
            }
          }
          return amount;
        }
      }
      
      // 示例二
      public List<String> matchStrings(List<String> strList,String substr) {
        List<String> matchedStrings = new ArrayList<>();
        if (strList != null && substr != null) {
          for (String str : strList) {
            if (str != null) { // 跟下面的if语句可以合并在一起
              if (str.contains(substr)) {
                matchedStrings.add(str);
              }
            }
          }
        }
        return matchedStrings;
      }
    • 使用编程语言提供的 continue、break、return 关键字提前退出嵌套。

      // 重构前的代码
      public List<String> matchStrings(List<String> strList,String substr) {
        List<String> matchedStrings = new ArrayList<>();
        if (strList != null && substr != null){ 
          for (String str : strList) {
            if (str != null && str.contains(substr)) {
              matchedStrings.add(str);
              // 此处还有10行代码...
            }
          }
        }
        return matchedStrings;
      }
      
      // 重构后的代码:使用continue提前退出
      public List<String> matchStrings(List<String> strList,String substr) {
        List<String> matchedStrings = new ArrayList<>();
        if (strList != null && substr != null){ 
          for (String str : strList) {
            if (str == null || !str.contains(substr)) {
              continue; 
            }
            matchedStrings.add(str);
            // 此处还有10行代码...
          }
        }
        return matchedStrings;
      }
    • 调整执行顺序来减少嵌套。

      // 重构前的代码
      public List<String> matchStrings(List<String> strList,String substr) {
        List<String> matchedStrings = new ArrayList<>();
        if (strList != null && substr != null) {
          for (String str : strList) {
            if (str != null) {
              if (str.contains(substr)) {
                matchedStrings.add(str);
              }
            }
          }
        }
        return matchedStrings;
      }
      
      // 重构后的代码:先执行判空逻辑,再执行正常逻辑
      public List<String> matchStrings(List<String> strList,String substr) {
        if (strList == null || substr == null) { 
          //先判空
          return Collections.emptyList();
        }
      
        List<String> matchedStrings = new ArrayList<>();
        for (String str : strList) {
          if (str != null) {
            if (str.contains(substr)) {
              matchedStrings.add(str);
            }
          }
        }
        return matchedStrings;
      }
    • 将部分逻辑嵌套封装成函数调用。

      // 重构前的代码
      public List<String> appendSalts(List<String> passwords) {
        if (passwords == null || passwords.isEmpty()) {
          return Collections.emptyList();
        }
        
        List<String> passwordsWithSalt = new ArrayList<>();
        for (String password : passwords) {
          if (password == null) {
            continue;
          }
          if (password.length() < 8) {
            // ...
          } else {
            // ...
          }
        }
        return passwordsWithSalt;
      }
      
      // 重构后的代码:将部分逻辑抽成函数
      public List<String> appendSalts(List<String> passwords) {
        if (passwords == null || passwords.isEmpty()) {
          return Collections.emptyList();
        }
      
        List<String> passwordsWithSalt = new ArrayList<>();
        for (String password : passwords) {
          if (password == null) {
            continue;
          }
          passwordsWithSalt.add(appendSalt(password));
        }
        return passwordsWithSalt;
      }
      
      private String appendSalt(String password) {
        String passwordWithSalt = password;
        if (password.length() < 8) {
          // ...
        } else {
          // ...
        }
        return passwordWithSalt;
      }
    • 除此以外,常用的还有通过使用多态来替代 if-elseswtich-case 条件判断的方法。

  7. 学会使用解释性变量

    • 常量取代魔法值。

      public double CalculateCircularArea(double radius) {
        return (3.1415) * radius * radius;
      }
      
      // 常量替代魔法数字
      public static final Double PI = 3.1415;
      public double CalculateCircularArea(double radius) {
        return PI * radius * radius;
      }
    • 使用解释性比那辆来解释复杂表达式。

      if (date.after(SUMMER_START) && date.before(SUMMER_END)) {
        // ...
      } else {
        // ...
      }
      
      // 引入解释性变量后逻辑更加清晰
      boolean isSummer = date.after(SUMMER_START)&&date.before(SUMMER_END);
      if (isSummer) {
        // ...
      } else {
        // ...
      } 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant