【问题标题】:Understanding the Single Responsibility Principle理解单一职责原则
【发布时间】:2016-01-21 10:34:52
【问题描述】:

我很困惑如何确定一个方法是否有一个职责,就像清洁代码一书中的以下代码一样

public Money calculatePay(Employee e) throws InvalidEmployeeType {
        switch (e.type) {
            case COMMISSIONED:
                return calculateCommissionedPay(e);
            case HOURLY:
                return calculateHourlyPay(e);
            case SALARIED:
                return calculateSalariedPay(e);
            default:
                throw new InvalidEmployeeType(e.type);
        }
    }

正如作者在这段代码 sn-p 中所说:“...显然不止一件事。 第三,它违反了单一职责原则(SRP),因为有多个 改变它的原因。”。乍一看代码,我在想,为什么该方法违反了 SRP,因为如果代码发生变化,只有当有一种添加的员工类型,但当我尝试进一步理解该方法时,我想出了一个假设,说明它为什么违反了上述原则。

我的假设是,由于该方法的名称是calculatePay(Employee e),因此该方法的唯一职责是支付计算,正如该方法的名称所暗示的那样,但是由于在该方法内部有一个过滤员工类型的开关过滤现在是一种不同的或另一种责任,因此违反了 SRP。不知道我说的对不对。

【问题讨论】:

    标签: java design-patterns single-responsibility-principle


    【解决方案1】:

    "...显然不止一件事。第三,它违反了 Single 责任原则 (SRP) 因为不止一个原因 让它改变。”

    这就是你的答案。每次添加新的Employee.Type 时,该方法都必须更改。此外,每个Employee.Type 的计算也可能发生变化。

    更好的解决方案是为 Employee 创建一个 Abstract Factory,并且 Employee 的每个派生都有自己的 CalculatePay 实现。这样,当计算更改或添加新的Employee.Type 时,只需更改一个类。

    这是来自 Clean Code 的另一个摘录,其中更详细地解释了 -

    这个问题的解决方案(见清单 3-5)是把开关埋起来 ABSTRACT FACTORY 地下室的声明,9 绝不让 任何人都可以看到它。工厂将使用 switch 语句创建 Employee 的衍生物的适当实例,以及各种 函数,例如calculatePay、isPayday 和deliverPay,将 通过 Employee 接口多态地分派。我的将军 switch 语句的规则是,如果它们可以被容忍 只出现一次,用于创建多态对象

    【讨论】:

    • 感谢您的输入,我想在Also, the calculation for each Employee.Type might change too 上发言。员工的计算将如何影响方法?由于每种类型都只是调用一种方法来执行计算,我认为,并且根据您的回答和书中给出的陈述,我是否可以假设我关于如何理解原理的假设是正确的?
    • Single Responsibility Principal 应该在类的上下文中看到,而不一定在方法级别。这就是为什么我说如果任何计算发生变化,你需要更新这个类。如果您将此方法移动到 Employee 的派生类,那么如果计算需要更改,则只需更改该类。
    • @anathema 也可以,例如我们想以不同的方式计算每小时付款(假设周末工作对工资有影响)然后我们可能会更改 calculateHourlyPay 函数签名(添加布尔标志或日期时间),因此也需要更改 calculatePay 函数。跨度>
    【解决方案2】:

    我通常在班级级别应用 SRP。它可以防止类变得太大并承担太多角色。

    我将“责任”视为概念性的。因此,我认为你的方法只有一个职责:计算工资。

    我尝试关注 Google 的 guidelines 并寻找这些表明您正在远离 SRP 的警告信号:

    • 总结类所做的工作包括单词“and”。
    • 对于新团队成员或缺乏经验的开发人员来说,课程将具有挑战性 阅读并快速“理解”。
    • 类具有仅在某些方法中使用的字段。
    • 类具有仅对参数进行操作的静态方法。

    但另一方面,您的代码包含一个 switch 语句,表明您可能正在远离 OCP...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      相关资源
      最近更新 更多