在清洁代码示例中理解单一责任主体SRP

时间:2014-10-14 12:39:16

标签: oop design-patterns coding-style single-responsibility-principle

目前我正在阅读以下示例中的功能部分中的Uncle Bob的清洁代码书: -

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);
    }
}
鲍勃叔叔说: -

  

此功能有几个问题。首先,它很大,而且   添加新员工类型时,它会增长。第二,非常   显然不止一件事。第三,它违反了Single   责任原则7(SRP)因为有多个原因   它改变了。第四,它违反了开放封闭原则8(OCP)   因为每当添加新类型时它必须改变

他提出了如下解决方案: -

public abstract class Employee {
    public abstract boolean isPayday();
    public abstract Money calculatePay();
    public abstract void deliverPay(Money pay);
}
-- -- -- -- -- -- -- -- -
public interface EmployeeFactory {
    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}
-- -- -- -- -- -- -- -- -
public class EmployeeFactoryImpl implements EmployeeFactory {
    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
        switch (r.type) {
            case COMMISSIONED:
                return new CommissionedEmployee(r);
            case HOURLY:
                return new HourlyEmployee(r);
            case SALARIED:
                return new SalariedEmploye(r);
            default:
                throw new InvalidEmployeeType(r.type);
        }
    }
}

我无法从示例中完全理解这个想法,在我的脑海中有一些问题,我无法找到答案: -

添加新员工时,第一个代码中的

1-将会增长。是的,但这也发生在解决方案中,那么有什么区别呢?

2-第一个例子如何做多个事情。它只计算支付“在同一抽象层次上的功能”的注意事项,如果我们考虑抛出错误是另一回事,那么解决方案也是如此。

2 个答案:

答案 0 :(得分:3)

First, it’s large, and when new employee types are added, it will grow.

你是对的,解决方案并没有真正缩短整体代码的大小,而且当添加新的员工类型时,它仍会整体增长。

Second, it very clearly does more than one thing.

原始文件都处理调度到正确的付款计算功能并计算付款。建议的解决方案解决了这个HourlyEmployee.calculatePay()现在只计算HourlyEmployee等的付费,EmployeeFactoryImpl根据其返回的Employee实施处理调度。

Third, it violates the Single Responsibility Principle (SRP) because there is more than one reason for it to change.

如果薪资计算逻辑需要更改,则原始calculatePay需要更改。如果添加了新的员工类型,还需要更改。添加新员工类型时,解决方案不需要更改为calculatePay。因此,只有一个责任和一个改变的理由。

Fourth, it violates the Open Closed Principle (OCP) because it must change whenever new types are added

返回1,添加新员工类型时,整体代码长度仍会发生变化。但是,只有与处理员工类型相关的部分必须更改。专门用于计算薪酬的代码根本不需要改变。因此,需要扩展的部分是开放的,与扩展无关的部分是关闭的。

答案 1 :(得分:0)

1)更多代码更难理解,调试和维护。当然,这个例子并不是那么大,但你明白了。保持课程的小巧和重要性有助于可维护性,可扩展性和可重用性。更重要的是,如果您更改代码,为新员工类型添加新部分,则可能会破坏旧代码。

2)每次计算中的逻辑都会有所不同。因此,班级正在做三件事。如果将每个计算拆分为自己的类,则可以获得1中提到的好处,而且解决方案更加可测试。