단일 책임 원칙이 기능에 적용 가능합니까?


17

Robert C. Martin에 따르면 SRP는 다음과 같이 말합니다.

수업 이 바뀌어야 하는 이유는 하나 이상이어야 합니다.

그러나 그의 책 Clean Code , 3 장 : Functions에서 다음 코드 블록을 보여줍니다.

    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);
        }
    }

그리고 다음과 같이 말합니다.

이 기능에는 몇 가지 문제가 있습니다. 첫째, 규모가 크며 새로운 직원 유형이 추가되면 커질 것입니다. 둘째, 그것은 하나 이상의 일을 매우 명확하게 수행합니다. 셋째, SRP (Single Responsibility Principle)가 하나 이상의 변경 이유가 있기 때문에 SRP를 위반합니다 . [강조 광산]

첫째, SRP가 클래스에 대해 정의되었다고 생각했지만 함수에도 적용 가능하다는 것이 밝혀졌습니다. 둘째로,이 함수 어떻게 변경 해야합니까? 직원이 변경되어서 만 변경되는 것을 볼 수 있습니다.


5
이것은 다형성에 대한 교과서 사례처럼 보입니다.
wchargin

이것은 매우 흥미로운 주제입니다. 이 문제에 다음 해결책을 추가 할 가능성이 있습니까? 나는 각 직원 클래스에 calculatePay 기능을 넣었다는 것을 알았지 만 이제는 각 직원 클래스가 다음과 같이 변경 될 수 있습니다. 지불 계산. 2. 클래스 등에 더 많은 속성 추가.
Stav Alfi

답변:


13

단일 책임 원칙에 대해 자주 놓친 세부 사항 중 하나는 "변경 이유"가 유스 케이스 액터별로 그룹화되어 있다는 것입니다 ( 여기 에서 자세한 설명을 볼 수 있음 ).

따라서 귀하의 예에서는 calculatePay새로운 유형의 직원이 필요할 때마다 방법을 변경해야합니다. 한 유형의 직원이 다른 직원과 아무 관련이 없을 수 있으므로 변경 사항이 시스템의 다른 사용자 그룹 (또는 유스 케이스 행위자)에 영향을 미치므로이를 함께 유지하면 원칙을 위반하게됩니다.

이제 원리가 함수에 적용되는지 여부에 대해 : 하나의 메소드에서만 위반이 발생하더라도 여러 가지 이유로 클래스를 계속 변경하므로 여전히 SRP 위반입니다.


1
링크 된 YouTube 동영상을 보려고했지만 유스 케이스 행위자별로 그룹화하는 것에 대한 언급없이 10 분이 지나면 포기했습니다. 처음 6 분은 명백한 이유없이 엔트로피에 관한 문제입니다. 비디오에서 그가 토론하기 시작하는 위치를 알려 주면 도움이 될 것입니다.
Michael Shaw

@MichaelShaw 10:40부터 시청 해보십시오. Bob 아저씨는 코드는 "사람마다 다르기 때문에 다른 이유로 변경 될 것"이라고 언급했습니다. 나는 그것이 MichelHenrich가 우리를 지적하려는 것일 수 있다고 생각합니다.
Enrique

전체 50 분짜리 YouTube 동영상 시청을 마쳤습니다. 대부분은 명확하게 설명하지 않았습니다. 나는 16:00 마크에서 그가 이미 그 주제를 넘어 섰다는 것을 알아 차리고 다시는 그 주제로 돌아 오지 않았습니다. "설명"은 본질적으로 다음과 같이 요약됩니다. SRP의 "책임"이 "변화의 다른 이유"를 의미하는 것은 아니며, "실제로 다른 사람들의 요청에 따른 변화"를 의미합니다. 사람들이하는 다른 역할의 요청 ". "설명"은 아무것도 명확하게하지 않으며, 모호한 단어를 다른 단어로 대체합니다.
Michael Shaw

2
@MichaelShaw는 책에서 인용 한 것과 같이 다른 직원 유형을 소개해야하는 경우 Employee 클래스를 변경해야합니다. 다른 역할은 다른 직원 유형의 지불에 책임이있을 수 있으므로이 경우 직원 클래스는 둘 이상의 역할에 대해 변경되어야하므로 SRP 위반입니다.
MichelHenrich

1
@MichaelShaw 예, 맞습니다. SRP는 조직의 구성 방식에 따라 다릅니다. 이것이 바로 모든 의견에 "may"또는 "may"를 추가하는 이유입니다. :). 그러나 이러한 경우에도 코드가 SRP를 위반하지는 않지만 OCP를 위반하는 것은 아닙니다.
MichelHenrich

3

176 페이지의 12 장 : 출현, 이 책은 최소 클래스 및 방법 섹션에서 다음 같이 설명하여 약간의 수정을 제공합니다.

클래스와 메서드를 작게 만들기 위해 너무 작은 클래스와 메서드를 만들 수 있습니다. 따라서이 규칙은 우리의 기능과 클래스 수를 낮게 유지하도록 제안합니다

높은 계급과 방법 수는 때때로 무의미한 교리의 결과입니다.

분명히 그는 calculatePay()위와 같이 완벽하게 훌륭한 무고한 작은 방법을 분해하기 위해 SRP를 따르는 독단주의에 대해 이야기하고 있습니다.


3

Martin 씨가 SRP를 기능에 적용하면 SRP에 대한 정의를 내재적으로 확장합니다. SRP는 일반적인 원칙에 대한 OO 고유의 표현이므로 함수에 적용 할 때 좋은 아이디어이므로 문제가 발생하지 않습니다. 정의).

나는 하나 이상의 변화 이유를 보지 못하고 "책임"또는 "변화 이유"라는 관점에서 SRP를 생각하는 것이 도움이된다고 생각하지 않습니다. 기본적으로 SRP는 소프트웨어 엔터티 (함수, 클래스 등)가 한 가지 일을하고 잘 수행해야합니다.

내 정의를 살펴보면 SRP의 일반적인 표현보다 모호하지 않습니다. SRP에 대한 일반적인 정의의 문제점은 너무 모호하다는 것이 아니라 본질적으로 모호한 것에 대해 너무 구체적으로 노력한다는 것입니다.

당신이 무엇을하는지 보면 calculatePay, 분명히 한 가지 일을하고 있습니다 : 유형에 따라 발송하십시오. Java에는 형식 기반 디스패치를 ​​수행하는 기본 제공 방법이 calculatePay있으므로 우아하고 비 아이디어 방식이므로 다시 작성해야하지만 명시된 이유로 다시 작성해야합니다.


-2

당신은 맞습니다 @Enrique. SRP가 클래스의 함수 또는 메소드인지에 관계없이 SRP는 해당 코드 블록에서 한 가지 작업 만 수행함을 의미합니다.

'변경 이유'문은 때때로 약간 오해의 소지가 있지만 변경 calculateSalariedPay하거나 calculateHourlyPay열거 형 Employee.type을 변경하면이 방법을 변경해야합니다.

귀하의 예에서 기능 :

  • 직원의 유형을 확인합니다
  • 유형에 따라 돈을 계산하는 다른 함수를 호출합니다.

내 의견으로는 직원을 생각하고 방법이 이미 존재한다면 스위치 케이스와 통화를 더 짧게 작성할 수 없기 때문에 직접 SRP 위반이 아닙니다. 어쨌든 직원 유형을 추가하는 경우 'case'문을 추가해야하므로 명백한 공개 폐쇄 원칙 (OCP) 위반이므로 잘못된 구현입니다. 리팩터링.

우리는 '돈'을 어떻게 계산해야할지 모르지만, 가장 쉬운 방법은 Employee인터페이스를 사용하고 getMoney메소드를 사용 하여 구체적인 구현을 하는 것입니다. 이 경우 전체 기능이 필요하지 않습니다.

계산하기가 더 복잡하다면 방문자 패턴을 사용할 수도 있습니다. 방문자 패턴은 100 % SRP는 아니지만 스위치 케이스보다 OCP입니다.


2
함수가 수행하는 두 가지 작업을 나열하는 방법을 모르지만 SRP 위반이 아니라고 말하십시오.
JeffO

@JeffO : 그것은 두 가지가 아니라 한 가지의 두 부분입니다. 유형에 따라 적절한 함수를 호출하는 것입니다.
Michael Shaw
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.