코드 반복과 다중 책임 방법


11

SRP (Single Responsibility Principle)를 따르고 코드 반복을 생략하려고합니다. 그러나 종종 코드 반복이 적어도 의미있는 명명 된 메소드로 추출하기 어려운 호출 코드 블록에 불과한 곳이 종종 있습니다.

DoAction1();
DoAction2();

if (value)
    DoAction3();

DoAction4();

그러한 코드를 메소드로 추출하는 가장 좋은 방법은 무엇이며 어떻게 이름을 지정합니까?


1
그것들이 다른 의미있는 방법으로 추출되는 것에 저항하는 이유는 무엇입니까?
Chandranshu

모든 행동은 관련이없는 일을합니다. 다음과 같이 작성해야합니다 void MethodThatDoAction1ThenAction2AndAction3IfValueAndThenAction4(). 오히려 더 많은 의미를 볼 수 있습니다 : CodeBlock1().
yBee

4
그렇다면 추출 된 방법의 이름을 올바르게 지정하는 것입니다. 보편적 인 해결책이없는 것이 두렵습니다. 사례별로이 작업을 수행해야합니다. 이 똑같은 코드를 1 개 이상의 장소에서 반복한다면, 당신의 행동에 의미가있을 것이므로 그 의미를 찾아서 그 이름을 밝히기 위해 열심히 살펴볼 필요가 있습니다.
Chandranshu

1
위안이 있다면 긴 클래스 이름의 Spring 우승자 AbstractInterruptibleBatchPreparedStatementSetter는 방법보다 약간 작습니다.
Chandranshu

1
@Chandranshu 귀하의 의견이이 질문에 대한 답변으로 잘 작동 할 것이라고 생각합니다.
Simon Forsberg

답변:


13

추출 된 방법의 이름을 올바르게 지정하는 것의 문제 일뿐입니다. 보편적 인 해결책이없는 것이 두렵습니다. 사례별로이 작업을 수행해야합니다. 이 똑같은 코드를 1 개 이상의 장소에서 반복한다면, 당신의 행동에 의미가있을 것이므로 그 의미를 찾아서 그 이름을 밝히기 위해 열심히 살펴볼 필요가 있습니다.

위안이 있다면 긴 클래스 이름의 봄 우승자 AbstractInterruptibleBatchPreparedStatementSetter는 49 자입니다.


11

사실 당신은 고통 받고 프로그래머가해야 할 가장 어려운 상단 작업 - 것들 명명 . 그런 미숙 한 답변에 대해 죄송하지만 저항 할 수 없었습니다. 인터넷에서도 많은 사람들이이 문제를 겪고 있음을 알 수 있습니다 . 심지어 인터넷에서도 이러한 유형의 에세이를 찾을 수 있습니다 .

이제 반복 코드가 모두 하나의 작업을 수행하고 해당 메소드가 다른 메소드에서 사용되지 않는 경우 단순히 도우미 메소드 이며 결과 메소드의 이름을 doXXX또는 로 지정할 수 있습니다 makeXXX.

으로 Chandranshu가 말했다 "당신은 [...]이 의미와 이름을 지정 반복하는 경우." 요점과 적절하다.

여기에 이미지 설명을 입력하십시오

Pic courtesy : CodeChef 페이스 북 페이지 사진


2

코드 반복 원칙을 너무 멀리 잡고 있다고 생각합니다. 코드 반복을 피하는 요점을 생각해보십시오. 요점은 논리에 변화가있을 때 확인해야 할 코드의 양을 줄이고, 비슷한 의도의 블록을 배제하여 이해력을 높이는 것입니다.

반복을 피하기 위해 인수 분해의 단점은 공유 블록 중 하나를 변경 해야하는 경우 훨씬 더 복잡한 상속 또는 표준과 비표준 구현 간의 전환이 필요하다는 것입니다.

따라서 이러한 공통성 중 하나를 고려하여 얻은 이해 이점에 대해 다른 블록 없이도 이러한 블록 중 하나 가 변경 될 수 있는 논리의 가능성을 신중하게 평가하십시오 . 하나의 구현이 다른 구현과 분리 될 수 있다면 단순히 코드를 반복하는 것이 좋습니다.

더 복잡하게하고 문제의 도메인이 더 정의되고,이 반복되는 코드를 유지하면서, 당신은 지금 더 복잡한 반복하지만, 요인에 더 적절한 찾을 수 있습니다 또한 더 정의 섹션 밖으로.

나는 보통 반복되는 것처럼 보이는 것이 고려할 가치가있는 것으로 판명 될 때까지 한동안 텍스트 편집기의 동일성을 유지하려고한다. 나는 반복을 유지하지만 나중에 텍스트를 쉽게 일치시켜 블록의 미래를 향한 시선을 끈다.

많은 시간, 동일성 및 가능한 팩토링은 실제적이고 변덕스러운 비즈니스 규칙과 의존도가 높고 종종 임의적 인 논리로 사라지기 시작합니다. 몇 가지 일반적인 데이터베이스 구현 (ANSI_NULLS 또는 이와 유사한 것을 염두에 두는 것)의 이상을 처리하는 것과 같이 추가됩니다. 순수한 논리처럼 보이는 것을 뒤틀린 혼란 에 빠뜨리고 , 산업 국가의 혼란에 직면했을 때 합리적이고 방어 가능한 결정 논리 를 제공하려고 노력했습니다 .

사람들이 당신이 팩토링하려고하는 것을 팩토링하려고 시도하면 Do1Then2If2False Do1IfTrueDo2와 같은 쓸모없는 구문의 전체 라이브러리를 갖게 될 것 같습니다.

블록을 제거하기 위해 블록이 변경되지 않는다는 것이 더 복잡하고 명확해야합니다.

그것은의 소프트웨어 . 돌아가서 지금 같은 블록 몇 개를 편집 할 수 있습니다. 5 분이 걸립니다. 또한 시간을 허비하면서 몇 시간을 낭비하고 상속 및 스위칭 개발에 몇 시간을 낭비하지 않고 RSI 키보드를 제대로 갖추 었는지 확인할 수 있습니다.


코드 반복의 본질을 추출하는 부분이 마음에 듭니다. 에 듭니다. 로직이 변경 될 때 확인
해야하는

1

진정한 단일 책임 원칙을 따르는 경우이 코드 블록에는 특정한 목적이 있어야합니다. 그렇지 않으면 이러한 메소드는 별도의 클래스에 있습니다.

그렇다면이 코드 블록의 목적은 무엇입니까? 그것을 결정하고 당신은 이름을 생각 해낼 수 있어야합니다.

여전히이 이름을 알 수 없다면이 방법들이 실제로 함께 속해 있지 않을 수도 있습니다. 즉,이 클래스 / 코드 블록에는 둘 이상의 책임이 있습니다. 이 경우 작업을 분할하기 위해 리팩토링하면 더 나은 목적을 나타내는 이름이 나타날 수 있습니다.


1

나는 당신과 비슷한 상황을 겪었습니다.

객체가 나타내는 기능을 정의하는 클래스가 있습니다.

class Functionality
{
protected:
void functionA();
void functionB();
...
void functionZ();
}

그런 다음 객체가 수행하는 고급 작업의 워크 플로를 정의하는 클래스가 있습니다.

class Workflows: private Functionality
{
    void WorkflowA()
    {
        functionA();

        if (m_bValue) {
            functionB();
        }

        functionC();
    }
    ...
    void WorkflowB();
}

비슷한 상황에 처해 있다면 어떤 수업 (이 경우 기능 / 워크 플로우에서) 표현하고 그에 따라 방법의 이름을 지정합니다.

면책 조항 :이 예제에서 사용 된 클래스 이름은 매우 정확하지 않지만 메소드 이름은 실마리를 제공합니다. 재량권 고.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.