• 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个功能初始时完全相同,后来慢慢发生改变,开始时还尝试通过参数,状态来控制试图挣脱焦油坑,但最后不得不壮士断腕,重新拆开,瞬间神清气爽。

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

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

    参考:设计模式之美

    -------------------------------------------------------------------------
    ## 极客时间全网最便宜最优惠购买方式,优惠券返现 百度网盘 微信关注公众号“选门好课”
    扫描下方二维码关注我的公众号"选门好课",与我一起交流知识
  • 相关阅读:
    ORM查询相关的操作
    分享一些珍藏和网上搜集的一些接码平台
    DRF: serializers ModelSerializer的序列化中model在有外键的情况下显示name代替显示id的几种方式
    Django Rest framework中序列化A表时怎么获取B表的数据
    10步入门Django Rest framework后端接口框架
    Django Rest framework后端接口框架,常用的子类视图
    redis学习(九)——数据持久化
    Java8之lambda表达式
    Java多线程(九)—— interrupt()和线程终止方式
    redis学习(八)——redis应用场景
  • 原文地址:https://www.cnblogs.com/singworld/p/12072824.html
Copyright © 2020-2023  润新知