Don’t Repeat Yourself,Repeat Yourself

Don’t Repeat Yourself,Repeat Yourself

Don't repeat yourself (DRY, or sometimes do not repeat yourself) 是一个旨在减少软件模式重复的软件开发原则,使用抽象或使用数据规范化来代替它以避免冗余。

平时工作中都会尽量避免写重复代码,但真的就不可以写重复的代码吗?

上代码

public class UserAuthenticator {
  public void authenticate(String username, String password) {
    if (!isValidUsername(username)) {
      // ...throw InvalidUsernameException...
    }
    if (!isValidPassword(password)) {
      // ...throw InvalidPasswordException...
    }
    //...省略其他代码...
  }

  private boolean isValidUsername(String username) {
    // check not null, not empty
    if (StringUtils.isBlank(username)) {
      return false;
    }
    // check length: 4~64
    int length = username.length();
    if (length < 4 || length > 64) {
      return false;
    }
    // contains only lowcase characters
    if (!StringUtils.isAllLowerCase(username)) {
      return false;
    }
    // contains only a~z,0~9,dot
    for (int i = 0; i < length; ++i) {
      char c = username.charAt(i);
      if (!(c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.') {
        return false;
      }
    }
    return true;
  }

  private boolean isValidPassword(String password) {
    // check not null, not empty
    if (StringUtils.isBlank(password)) {
      return false;
    }
    // check length: 4~64
    int length = password.length();
    if (length < 4 || length > 64) {
      return false;
    }
    // contains only lowcase characters
    if (!StringUtils.isAllLowerCase(password)) {
      return false;
    }
    // contains only a~z,0~9,dot
    for (int i = 0; i < length; ++i) {
      char c = password.charAt(i);
      if (!(c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.') {
        return false;
      }
    }
    return true;
  }
}

代码中有两处明显重复的代码,isValidUserName() 函数和 isValidPassword() 函数,代码完全相同,为了移除重复我们重构一下上面代码

public class UserAuthenticatorV2 {

  public void authenticate(String userName, String password) {
    if (!isValidUsernameOrPassword(userName)) {
      // ...throw InvalidUsernameException...
    }

    if (!isValidUsernameOrPassword(password)) {
      // ...throw InvalidPasswordException...
    }
  }

  private boolean isValidUsernameOrPassword(String usernameOrPassword) {
    //省略实现逻辑
    //跟原来的isValidUsername()或isValidPassword()的实现逻辑一样...
    return true;
  }
}

​ 重构后去除了代码的重复,但是否意味着更好呢?合并之后的 isValidUserNameOrPassword() 函数,负责两件事情:验证用户名和验证密码,违反了“单一职责原则”和“接口隔离原则”。 isValidUserName() 和 isValidPassword() 虽然从实现逻辑上看起来是重复的,但是从语义上并不重复,一个是校验用户名,另一个是校验密码。尽管目前两个校验完全相同,如果未来修改其中一个校验逻辑,合并后的代码还得重新拆开。

​ 之前工作中就遇到过这种问题,5个功能初始时完全相同,后来慢慢发生改变,开始时还尝试通过参数,状态来控制试图挣脱焦油坑,但最后不得不壮士断腕,重新拆开,瞬间神清气爽。

​ 在程序设计中可以使用同样的方法做多件事,但应该杜绝同一件事由不同方法去做。

​ 生活中亦是如此,避免重复,不惧重复,总结归纳,以终为始。

参考:设计模式之美

猜你喜欢

转载自www.cnblogs.com/singworld/p/12072824.html
今日推荐