【问题标题】:SRP and DRY confusionSRP 和 DRY 混淆
【发布时间】:2023-01-31 10:30:43
【问题描述】:

我不熟悉开发干净的代码并尝试用原则来约束自己。我的应用程序有 3 个用户实体,每个用户实体都有不同的数据源。在身份验证逻辑方面,所有 3 个实体将使用相同的逻辑,除了来自数据源。我现在正在做的是,我将每个实体的逻辑分为 3 个不同的类(为了不同的数据源),感觉我违反了 DRY 原则。

我曾经这样做过(我只使用伪代码):

class Auth
loginFunction(dto,loginType){
connect to datasource for auth(datasource = loginType=A?datasourceA:loginTypeB?datasourceB:datasourceC)
}

我现在正在做的是:

class AuthA
loginFunction(dto){
}
class AuthB
loginFunction(dto){
}
class AuthC
loginFunction(dto){
}

对于第一种方法,我觉得我违反了 SRP,因为该类负责处理所有实体的身份验证。我可以争辩说它的责任只是处理身份验证,而不管实体的数量。但话又说回来,我觉得每个实体的身份验证都应该由它们各自的类来处理。因此,第二种方法。但是第二种方法在所有类中重复相同的逻辑,唯一的区别是数据源。

我觉得这两种方法都不对。有没有办法尽可能雄辩地处理这个问题?谢谢你们。

【问题讨论】:

    标签: oop dry solid-principles single-responsibility-principle


    【解决方案1】:

    我不知道我是否理解正确,但我认为你正在寻找继承,你有一个像 BaseAuth 这样的基类,它将针对每个特定的“Auth”类进行扩展,每个特定的类将实现自己的 @987654323 @.

    而且,将数据源连接到login 方法也不是一个好主意。您的Auth 类正在做两件事:连接到数据源和登录用户。

    所以你可以有类似这个例子的东西(我用过 Java):

    abstract class BaseAuth {
      protected DataSource dataSource;
      
      public BaseAuth(DataSource dataSource) {
        this.dataSource = dataSource;
      }
      
      public void login(LoginDTO dto) {
        // this.datasource.connect().login() or whatever
        // for testing I've added this line:
        System.out.println("DATASOURCE = " + this.dataSource.toString());
      }
    }
    

    每个特定的类都将实现自己的datasource,并且可以通过login方法访问。

    是这样的:

    class AuthA extends BaseAuth {
      public AuthA() {
        super(new DataSourceA());
      }
    }
    

    现在AuthA 创建了自己的DataSourceABC 的方式相同。所以 AuthX 类提供数据源,而基类提供登录逻辑。

    而来自BaseAuthDataSource可以是另一个抽象(接口或抽象类):

    interface DataSource { }
    

    其中每个DataSourceX 实现DataSource

    我创建了这个 DataSource 示例覆盖 toString() 来测试示例:

    class DataSourceA implements DataSource {
    
      public DataSourceA() {
        // here the specific implementation
      }
    
      @Override
      public String toString() {
          return "DataSource A";
      }
    }
    

    所以现在:

    1. BaseAuth 类允许您调用.login() 方法,无论它是从AuthAAuthBAuthC 调用的。登录不重复,此类仅负责登录。
    2. 创建每个“auth”类时,它还会创建自己的DataSource。所以每个 auth 只负责创建自己的数据源。
    3. .login() 将为特定类调用特定的DataSource

      然后,如果您这样做(从方法中删除 DTO 对象以更好地阅读):

      BaseAuth auth = new AuthA();
      auth.login();
      auth = new AuthB();
      auth.login();
      auth = new AuthC();
      auth.login();
      

      结果将是:

      DATASOURCE = DataSource A
      DATASOURCE = DataSource B
      DATASOURCE = DataSource C
      

      请注意您不必重复代码。您只有一个 login 方法将执行相应的 DataSource

      顺便说一下,我会记住你的另一个原则“Duplication is far cheaper than the wrong abstraction”。如果您不完全确定抽象是否正确......请不要尝试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-11
      • 2021-04-10
      • 2021-11-06
      • 2011-12-04
      • 2016-01-12
      • 2013-01-02
      • 2018-06-01
      • 2010-12-02
      相关资源
      最近更新 更多