design-patterns - 单一职责原则是否适用于功能?

标签 design-patterns single-responsibility-principle

根据 Robert C. Martin 的说法,SRP 指出:

There should never be more than one reason for a class to change.



然而,在他的著作《清洁代码》第 3 章:函数中,他展示了以下代码块:
    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);
        }
    }

然后说:

There are several problems with this function. First, it’s large, and when new employee types are added, it will grow. Second, it very clearly does more than one thing. Third, it violates the Single Responsibility Principle (SRP) because there is more than one reason for it to change. [emphasis mine]



首先,我认为 SRP 是为类定义的,但事实证明它也适用于函数。其次,这个功能怎么会有不止一个改变的理由呢?我只能看到它因为员工的变化而变化。

最佳答案

您可以将上述方法视为属于以下类的对象:

class PaymentCalculator implements Function<Employee, Money> {
  Money apply(Employee) {
    switch (e.type) {
            case COMMISSIONED:
                return calculateCommissionedPay(e);
            case HOURLY:
                return calculateHourlyPay(e);
            case SALARIED:
                return calculateSalariedPay(e);
            default:
                throw new InvalidEmployeeType(e.type);
        }  
  }
}

那么我们来尝试找出这个类可能被修改的原因:
  • 员工类型工资变动
  • 计算逻辑的变化(新参数如员工职位、经验等)

  • 对于至少这两种类型的更改,您将被迫在此方法中进行更正。值得一提的是,SRP 的目标是实现低耦合和高内聚。为了理解这样做的好处,试着想象一下你有一个包含数百个这样的类和方法的大系统:calculatePay、calculateVacation、createDepartment 等。所有这些类和方法都有这样的代码。改变会很容易吗?

    附言一旦你看到长长的 if-else 或 case 语句,你就可以开始考虑 SRP。

    关于design-patterns - 单一职责原则是否适用于功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28929694/

    相关文章:

    java - Selenium 异常处理设计

    java - 设计模式恢复工具示例程序

    c# - 关于 Unity3D SOLID SRP 的建议

    php - 拆分一个大的 PHP 类

    c# - 遍历枚举是一项单一职责吗?

    agile - 帮助理解单一职责原则

    c++ - 初始化不可复制的成员

    c++ - protected 外部资源使用

    java - Scala/Java 中的编程语言抽象

    language-agnostic - SRP 不违反封装