상용구에 대한 방어?


14

나에게, 상용구 코드는 분명히 나쁘다. 그러나 나는 상용구를 줄이기 위해 저항을 표시하는 개발자를 만났습니다. 나는 시간이 지남에 따라 내가 개발 한 혐오에 대한 논쟁을 생각하면서 쉽게 형성되지 않았다는 것을 깨달았다.

덜 상용구를 선호한다는 설득력있는 주장을 할 수 있도록 몇 가지 반론은 무엇입니까? 다시 말해서, 상용구에 찬성하는 주장은 무엇입니까?

(저는 일반적으로 상용구가 의미한다고 생각하지만 좋은 예는 Java의 getter 및 setter입니다.)


7
중복 코드에 대한 인수 (가정 보일러 복사 / 붙여 넣기입니다) : stackoverflow.com/a/2490897/1583
오디드

1
@Oded : 맞습니다. 그러나 당신은 질문을 잘못 읽습니다. :) 그는 상용구 코드에 대해 할 말이 있는지 알아 보려고합니다 . 내 생각에 그는 단점에 대해 잘 알고 있습니다.
Steven Jeuris

3
@StevenJeuris-나는 질문을 완벽하게 읽었습니다. 그렇기 때문에 답변을 게시하지 않았습니다. 나는 논쟁의 반대편에만 추가하고 있습니다. 그래서 OP는 다음 번에 "시간이 지남에 따라 개발 된 혐오를 지나서 쉽게 형성되고, 잘 생각 된 논쟁"을
내놓았다

2
보일러 플레이트는 심미적으로 즐거울 수 있습니다. en.wikipedia.org/wiki/This_Is_the_House_That_Jack_Built
SK-logic

서로 보완하는 몇 가지 좋은 답변과 의견 ... 어떤 것을 받아들이 기가 어렵다.
추상화

답변:


15

기억해야 할 중요한 점은 일반적으로 불필요한 컨텍스트를 제거하여 코드를 더 작게 만든다는 것입니다. 컴파일러가 무언가를 알아낼 수 있다면 인수가 나오고 명시 적으로 작성할 필요가 없습니다.

컴파일러만이 그것을 읽으려는 의도라면 좋을 것입니다. 그러나 "사람들이 읽을 수 있도록, 프로그램은 기계가 실행할 수 있도록 프로그램을 작성해야합니다." (철자 적으로,이 인용문은 보통의 사람들이 읽을 수있는 모든 언어 중 가장 어려운 언어 중 하나에 헌신 된 교과서에서 나옵니다 .

작성하는 동안 지루하고 반복적 인 상용구 모양은 1 년 (또는 5 년) 후에 코드를 유지해야하는 다른 사람에게 귀중한 컨텍스트가 될 수 있습니다.

이 짧은 모두 무언가로 대체 할 수 있기 때문에 WRT는 자바 예를 구체적으로, 나는 나쁜 보일러의 좋은 예입니다 그 것을 동의합니다 속성 : 읽기 쉽고, 또한보다 유연. 그렇다고 모든 언어의 모든 상용구 구문 요소가 Java 및 C ++의 게터 및 세터만큼 낭비 적이라는 것은 아닙니다.


7
물론이 주장은 두 가지 방식으로 작동합니다. 많은 양의 상용구 코드가 컴파일러를 진정시키고 인간이 이해하는 데 도움 이 되지 않습니다. 게터 / 세터를 유지하기 위해서는 수십 줄을 완전히 읽어야합니다. 속성 당 하나의 짧은 줄을 읽는 것이 아니라 단순히 속성임을 나타냅니다.

6
상용구는 인간 독자에게도 유해 하다고 생각 합니다. 우리는 반복적이고 의미없는 텍스트를 강제로 작성함으로써 다른 사람들로부터 코드의 관련 부분을 가리고 있습니다. 도움이된다면, 정의상 상용구가 아닙니다.
Andres F.

1
@Giorgio : 반대로, 그것은 단지 내 의견 이상의 것입니다. 그것을 연구하려고 시도한 대다수의 사람들의 의견입니다. 그리고 "읽기 어려운"이 본질적으로 처음에 의견의 문제 일 때, 의견이 그렇게 널리 공유된다는 사실은 그것을 거의 사실로 만듭니다.
메이슨 휠러

1
@Mason Wheeler : 사람들이 프로그래밍 언어를 인식하는 방법은 종종 과거 경험에 영향을받습니다. Scheme에서 프로그램을 배운 사람들은 C 또는 Pascal 서투른 읽기가 어렵습니다. 반면에 대다수의 사람들은 주류 언어로 프로그래밍하는 법을 배웠습니다.
Giorgio

2
좀 더 문맥이 인간가 가지고있는 유일한 수단 일이 일어나고있는 모든 물건의 더 큰 정신적지도를 유지하는 것을 상용구를 제거하여 프로그래머로부터 숨겨진 의견 해요 뒤에서 보이지 않는 그리고 가에 올 때 더 큰 손해입니다 제작할 때 약간의 시각적 공간을 절약하는 것보다 디버깅.
Patrick Hughes

7

상용구 코드를 선호하는 한 가지 주장은 한 곳에서 변경하면 코드의 한 흐름에만 영향을 미친다는 것입니다. 이것은 종종 변경 사항을 사용하는 모든 코드에 영향을 미치기를 원한다는 사실과 균형을 이루어야합니다. 그러나 나는 논쟁을 뒷받침하는 드문 예를 보았습니다.

다음과 같은 코드가 있다고 가정 해 봅시다.

public ForTheBar(Foo foo)
{
    Bar bar = foo.bar();
    return bar.BeFooed();
}

이것은 코드에서 약 2 곳에서 사용됩니다.

어느 날 누군가가 와서 이렇게 말했습니다.

그리고 당신은 "이것은 간단하다"고 생각합니다.

public ForTheBar(Foo foo, bool shouldIGrommit)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    return bar.BeFooed();
}

그런 다음 사용자는 몇 가지 새로운 기능을 추가하고 FooTheBar와 잘 어울립니다. 그리고 당신은 당신이 Foo 그것을하기 전에 그 막대기를 Grommit해야하는지 정중하게 그들에게 물었다.

따라서 위의 방법을 호출하면됩니다.

그러나 사용자는 "알겠습니다. 세 번째 경우 BeFooed에 전화하기 전에 Bar를 낙서하길 원합니다."라고 말합니다.

문제 없습니다. 그렇게 할 수 있습니다.

public ForTheBar(Foo foo, bool shouldIGrommit, bool shouldIDoodle)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    if (shouldIDoodle)
    {
        bar.BeDoodled();
    }

    return bar.BeFooed();
}

갑자기 코드가 덜 상용화되고 있습니다. 아마도 두 줄의 반복되는 코드를 수락했을 것입니다. 이제는 각각 2-3 줄 길이의 코드가 3 개 더 이상 반복되지 않습니다.

이 모든 것, 나는 "이것은 일반적인 경우가 아니며, 일어날 때 리팩토링 할 수 있습니다."

내가 최근에 들었던 또 다른 주장은 상용구 코드가 때로는 코드 탐색에 도움이 될 수 있다는 것입니다. 우리가 논의한 예제는 수많은 상용구 매핑 코드를 제거하고 AutoMapper로 대체 한 곳입니다. 이제는 모든 것이 규칙 기반이기 때문에 IDE에 "이 속성 집합이 어디에 있습니까?"라고 말할 수는 없습니다.

사람들이 IoC 컨테이너에 대해 비슷한 것을 주장하는 것을 보았습니다.

내가 그들에게 동의한다고 말할 수는 없지만 그럼에도 불구하고 공정한 논쟁입니다.


2
나는 당신의 대답의 두 번째 부분을 선호했습니다. ; p +1
Steven Jeuris

그냥 내 예가 당신과 매우 비슷하다는 것을 깨달으십시오. 상식이 아니라고 생각하더라도 그것은 꽤 조금 발생하는 것처럼 보입니다 :)
kritzikratzi

6

효율성의 진화

이것으로 시작하십시오 :

<p>
    <label for="field">My field</label>
    <input type="text" id="field">
</p>

그런 다음 성가신 보일러 플레이트를 모두 제거하고 함수에 넣으십시오.

  1. createFieldHtml( id, label )

    이것은 좋습니다, 나는 너무 많은 줄을 저축하고 있습니다!

  2. createFieldHtml( id, label, defaultValue )

    그렇습니다. 추가하기 쉬운 기본값도 필요합니다.

  3. createFieldHtml( id, label, defaultValue, type )

    멋지다, 지금도 확인란에 사용할 수 있습니다

  4. createFieldHtml( id, label, defaultValue, type, labelFirst )

    UX 디자이너는 레이블이 체크 박스 뒤에 있어야한다고 말했다.

  5. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate )

    이제 필요할 때 날짜 선택기를 렌더링합니다. 흠 .. 매개 변수가 조금 손을 잡고있다

  6. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses )

    CSS 클래스를 추가 해야하는 경우가있었습니다.

  7. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses, fieldCssClasses, disabled, clearAfter, helpText, uploadPath )

    아 아아아 아아아 아아아

상용구 방어

최근에 주목 한 것이기 때문에 이것을 말로 표현하기가 어렵 기 때문에 목록을 만들 것입니다.

  1. 약간 뻗어있는 중복 줄을 갖는 것에 대한 두려움이있는 것 같습니다. 단지 몇 줄이면 전혀 문제가되지 않을 수 있습니다. 어떤 것들은 본질적으로 "거의 반복적"입니다 (위의 예처럼). 장기적으로 최적화 할 가능성이 거의 없습니다.
  2. 사람들은 기능을 어딘가에 캡슐화하는 것을 좋아합니다. 만약 당신이 객관적으로보고 그것이 단지 "엉망을 숨기고있는 것"처럼 보인다 – 의심 스럽다! 좋은 오래된 상용구를위한 시간일지도 모른다
  3. 점점 더 강력 해지는 기능이있을 때; 입력에 따라 다양한 실행 경로가 필요하고 궁극적으로 거의 수행되지 않습니다. 보일러 플레이트 시간 일 수 있습니다!
  4. 다른 추상화 계층 위에 추상화 계층을 추가 할 때 코드를 더 짧게 만들려면 (기본 계층은 변경되지 않음)-상용구 시간!
  5. 너무 많은 매개 변수를 사용 하여 실제로 매개 변수 이름을 지정 해야하는 기능 이있는 경우 보일러 플레이트 시간 일 수 있습니다.

내가 최근에 항상 자신에게 묻는 것 중 하나는 이것입니다.
아무것도 변경하지 않고 다른 프로젝트에 복사하여 붙여 넣을 수 있습니까? 그렇다면 라이브러리를 캡슐화하거나 라이브러리에 넣는 것이 좋습니다. 그렇지 않으면 상용구 시간입니다.

상용구는 복사 및 붙여 넣기 코드라는 일반적인 인식과는 매우 반대입니다. 나에게 상용구는 복사 및 붙여 넣기에 관한 것이지만 항상 조금씩 조정해야합니다.


업데이트 : 방금 실제 이름 위에 "too DRY anti-pattern"이라는 예제를 제공하는 기사를 보았습니다.

이 기능은 더 많은 매개 변수를 가져오고 다른 경우에 동작을 제어하기 위해 점점 더 복잡한 내부 논리를 갖습니다. 너무 건조한 기능은 쉽게 발견 할 수 있습니다. 여기에는 다양한 용도를 다루는 복잡한 if-then 논리가 많이 있습니다. [...] 또한 코드가 작고 불연속 기능을 수행하는 경우 코드 반복이 항상 나쁜 것은 아닙니다.

짧고 흥미로운 글입니다. 여기에서 기사를 찾을 수 있습니다. 너무 건조한 안티 패턴


1
"다른 추상화 계층 위에 추상화 계층을 추가 할 때 코드를 더 짧게 만들려면" 재사용 할 수있는 경우에만 추상화 계층을 추가해야합니다.
Steven Jeuris

4
+1. 자신을 반복하지 말고 자신을 거의 반복 하지 않도록 어색한 길이로 가지 마십시오 .
Julia Hayward

4

나는 경멸 상용구 코드를하지만, 항상이 갈 수있는 가장 좋은 방법 의미하지 않는다 상용구 코드를 제거 할 수있는.

WPF 프레임 워크에는 종속성 속성이 있으며, 이는 엄청난 양의 상용구 코드를 포함합니다. 여가 시간 동안 작성해야 할 코드의 양을 크게 줄이는 솔루션조사했습니다 . 1 년이 지난 후에도 여전히이 솔루션을 개선 하고 있으며 기능을 확장하거나 버그를 수정해야합니다.

무엇이 문제입니까? 이것은 새로운 것을 배우고 대안 솔루션을 모색하기 위해 훌륭하지만 아마도 가장 상업적인 결정 은 아닙니다 .

WPF 프레임 워크는 잘 문서화되어 있습니다. 그것은 제대로 당신의 상용구 코드를 작성하는 방법을 설명합니다. 이 상용구 코드를 제거하려고 시도하는 것은 좋은 운동이며, 반드시 살펴볼 가치가 있지만 msdn이 제공하는 것과 동일한 수준의 '광택'을 달성하는 데 오랜 시간이 걸리며 항상 그렇지는 않습니다.


그러나, 나는 지금 당장 가지고있는 결과에 여전히 만족하며 여가 시간 프로젝트에 기꺼이 사용합니다. :)
Steven Jeuris

3
WPF와 해당 종속성 속성을 만질 때마다 항상 C #이 C ++의 매크로만큼 간단한 것을 원했습니다. 확실한 매크로는 잘못된 손에 남용되지만 여기에서 너무 많은 반복을 제거 할 수 있습니다. 다음에 매크로를 원할 때 AOP 프레임 워크를 살펴 봐야합니다. :)
DXM

@DXM 만일 그렇게한다면, 그것이 비참하게 충돌한다면, 나를 비난하고 오류를 게시하는 것을 잊지 마십시오. ; p
Steven Jeuris

코드 스 니펫은 종속성 속성에서 꽤 잘 작동했습니다.
Codism

@Codism : 글쎄, 그들은 이다 솔루션, 하지만 난 경멸 너무 사람들을 . :)
Steven Jeuris

1

상용구의 문제점은 건조를 위반한다는 것입니다. 본질적으로 상용구를 작성할 때 여러 클래스에서 동일한 코드 (또는 매우 유사한 코드)를 반복합니다. 해당 코드를 변경해야 할 때 개발자가 코드가 반복 된 모든 위치를 기억할지는 확실하지 않습니다. 이로 인해 이전 API 또는 이전 메소드가 사용되는 버그가 발생합니다.

상용구 또는 공통 클래스로 상용구를 리팩토링하는 경우 API가 변경 될 때 한 곳에서 코드 만 변경하면됩니다. 더 중요한 것은 예기치 않은 변경이 발생하면 코드가 곳 에서 중단되고 모든 작업을 다시 수행하기 위해 수정해야 할 사항을 정확히 알려줍니다. 한 번의 변경으로 수십 또는 수백 개의 클래스에서 오류가 발생하는 시나리오보다 훨씬 좋습니다.


2
이것이 상용구 에 유리한 주장 어떻습니까?
Chris Wesseling

0

나는 다른 전술을 취할 것입니다. 개발 일관성은 소프트웨어 디자인의 가장 중요한 기능 중 하나이며, 응용 프로그램을 확장 가능하고 유지 관리 할 수 ​​있도록하는 데 중요한 도구이지만 여러 사이트, 언어 및 시간대로 팀을 관리 할 때 달성하기 어려울 수 있습니다.

달성하면 일관성을 유지하면 코드를 "한 번 보았을 때, 모든 것을 보았을 때"훨씬 쉽게 액세스 할 수 있으며 유지 관리 및 리팩토링 비용이 훨씬 저렴하지만 무엇보다 쉽게 ​​확장 할 수 있습니다. 상용구와 함께 상용구가 필요한 라이브러리를 작성할 때 개발자에게 다음을 제공했습니다.

  • 시작점 은 기능에 대한 프리앰블 (보일러 플레이트)을 이해하며 대부분의 주요 클래스와 액세스 포인트는 일반적으로 상용구의 일부로 제공됩니다. 이를 통해 개발자는 설명서를 시작할 수 있습니다.
  • 기대는 당신이 설정 프리앰블의 일환으로 추적 객체가 개발자가 예외 정보를 기록 할 위치를 알 수있는 경우 개발자에 대한 당신의 배치 예를 들어, 명백해질 것이다
  • 개발자가 클래스를 인스턴스화하는 과정을 밟을 때의 암묵적인 이해 는 라이브러리의 나머지 부분에 액세스하는 데 필요한 기술을 유추하고 라이브러리 전체에서 사용한 규칙에 대해 소개 할 기회를 가질 수 있습니다.
  • 쉬운 확인 하여 상용구 코드는 일반적으로 매우 쉽게 이미 결함이 프로세스에 최선을 다하고 선 아래로 훨씬 더 갇히지에서 소비자를 방지, 예외 가드 조항 자체 유효성을 검사 할 수 있습니다 필요
  • 보일러 플레이트 코드가 필요한 라이브러리의 구성 은 단일 실행 경로에 대한 기능을 사용자 정의하기위한 명백한 구현 지점이 이미 있기 때문에 쉽습니다. 이것은 필요한 상용구 코드가 공장 또는 명령 패턴으로 개선 된 경우 특히 유용합니다

라이브러리의 소비자가 인스턴스화에 관심을 가지면 개인 / 확장 메서드, 부모 클래스 또는 템플릿을 만들어 상용구 코드를 쉽게 구현할 수 있습니다.


-3

상용구 코드의 유일한 실제 문제점은 버그를 발견 할 때 재사용 한 장소가 아니라 사용했던 모든 곳에서 수정해야한다는 것 입니다.

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