이 글을 Nick Bull의 When DRY Doesn’t Work, Go WET을 번역한 글입니다.

원문은 When DRY Doesn’t Work, Go WET 에서 확인하실 수 있습니다.

DRY가 먹히지 않으면, WET하게

반복해도 좋습니다.

저는 이런 실수를 많이 보았고, 또한 스스로도 저질러보았습니다.

여러분은 DRY 프로그래밍 개념을 처음 보았을 때, 아마 오해를 했을 겁니다.

여러분의 머릿속은 다음과 같았을겁니다.


위키피디아: DRY는 동일한 코드를 두 번 반복하지 않음을 의미합니다.

당신: 흠, 그래. 모든 중복을 추상화로 대체하겠어.


좋은 해결책으로 보이지만, 그렇지 않습니다.

우린 종종 잘못된 방법으로 추상화하곤 합니다.


그 과정은 다음과 같습니다.

  1. 중복된 코드가 보입니다.
  2. 중복된 코드를 새로운 추상화(메소드, 클래스)로 추출합니다.
  3. 중복을 새 추상화로 바꿉니다.
  4. 코드가 완벽하다고 생각합니다.
  5. 시간이 흐릅니다.
  6. PM이 새로운 요구사항을 가져옵니다. 우리가 만든 추상화는 그 요구사항에 거의 완벽하게 들어맞습니다.
  7. 새로운 요구사항을 구현하기 시작합니다.
  8. 작지만 중요한 포인트가 있었습니다: 그 요구사항에 거의 완벽하게 들어맞습니다. 무슨 소리일까요? 새로운 요구사항은 추상화로 추출한 이전 코드의 95%에만 들어맞습니다. 나머지 5%에는 영향을 받지 않습니다. 따라서, 당신은 현재 코드에서 95%정도 복사된 코드로 새로운 추상화를 만드는 대신, 추상화 코드를 수정하기로 결정합니다. 예를 들어, if..else 와 같은 조건문을 추가하거나, 매개 변수를 전달하여 추상화가 다른 결정에 대해 다른 작업을 수행할 수 있도록 합니다.
  9. 이제 추상화는 조건에 따라 다르게 동작합니다.
  10. 또 다른 새로운 요구사항이 생겼습니다. 또 다른 추가적인 매개변수. 또 다른 조건문 (코드를 이해하고 유지하기가 매우 어려워질 때 까지 반복해보세요.)
  11. 축하합니다. 잘못된 추상화를 만들어내었습니다.


코드는 더이상 추상화를 나타내지 않습니다. 단지 조건부 절차일 뿐이죠. 이해하기 어렵고 깨지기 쉽습니다. 새로운 기능을 추가하는 것이 매우 어렵고, 모든 새로운 기능들은 코드를 더욱 복잡하게 만듭니다.

무한 루프입니다.

어떻게 해야할까요?

모든 것을 두 번 써보세요.


WET

WET(Write Everything Twice) 는 DRY의 반대 개념입니다.

새로운 시스템을 막 개발하기 시작했을 땐, 미래의 모든 요구사항을 알 수 없습니다.

그러니 바로 추상화를 진행하지 마세요.


중요한 문장입니다: 복제는 잘못된 추상화보다 훨씬 저렴하다.


예를 들면, 여러분은 웹 앱을 만들고 있고 현재 모든 페이지에 대한 UI 디자인이 없다고 가정해봅시다.

다만, 굉장히 많은 버튼들이 있고, 이 버튼들은 모든 페이지에서 비슷하게 생겼습니다.

당신은 Button 이라는 컴포넌트를 만들고, 모든 페이지에서 이 컴포넌트를 재사용하기로 결정했습니다.

아주 논리적으로 보입니다.


“저기요, 저기요!” 새로운 페이지 디자인을 PM이 가져왔습니다.

당신은 디자인을 살펴보다가, 페이지의 하단에 새롭고 멋진 버튼을 하나 찾았습니다.

기존의 버튼과 비슷해보이지만, “한가지 작은 특별한 기능”을 가지고 있습니다.

이 멋진 버튼을 구현하기 위해선, Button 컴포넌트의 10%를 새롭게 작성하고, 추가적인 조건문과 파라미터를 하나 추가해야합니다.


자, 이제 딜레마에 빠졌습니다.

  1. Button 컴포넌트를 변경한다. 추상화 코드의 10%를 재작성해야 한다. (새로운 멋진 버튼의 로직을 지원하기 위해 논리적인 조건들을 추가해야 합니다.)
  2. 두 개의 추상화를 만든다: FancyButtonButton . FancyButton 로직의 90%는 Button 으로부터 복붙하게 됩니다.


여러분이 첫 번째 옵션을 선택하고 싶다는 것을 알고 있습니다.

여러분은 아마 이 정도는 감당할 수 있다고 생각할 것입니다.

여러분은 스스로 잘못된 추상화를 만들지 않을 것이라고 생각할 것입니다.


슬픈 진실은, 여러분은 그럴거라는 점입니다.(경험이 풍부한 프로그래머, 그리고 스스로 무엇을 하고 있는지 아는 경우는 제외하구요.)


코드를 복사하세요. 두려워하지 마세요


시간이 조금 더 흐르면, 여러분은 미래의 버튼이 어떻게 생겼는지 알게 될 겁니다.

그런 다음 현재 코드베이스를 분석하고, 버튼 구성 요소에서 중복된 코드를 찾아 낸 뒤, 좋은 추상화를 진행할 수 있습니다.


너무 늦었다면

잘못된 추상화를 처리하기에 너무 늦었다고 생각된다면, 앞으로 나아가는 가장 빠른 방법은 다시 되돌아오는 것입니다.

다음과 같이 해보세요.

  1. 추상화된 코드를 되돌립니다.
  2. 다른 결정에 대해 다른 행동을 수행하게 만든, 이젠 더이상 쓰이지않는 파라미터들을 삭제합니다.
  3. 사용하지 않는 로직들을 제거합니다.

이렇게하면 각 호출자에 대한 추상화 및 조건문이 제거됩니다.


결국엔…

파라미터를 전달하거나 추가적인 조건문들이 코드 내부에서 동작하고 있다면, 여러분의 추상화는 잘못된 것입니다.

잘못된 추상화보다는 복제를 선호하세요.

읽어주셔서 감사합니다!