파괴 지향 개발 방법론
이 글에서는 '파괴 지향 개발 방법론'을 소개하며, 변화에 유연하게 대처하는 코드 작성 전략과 기존 방법론과의 차이점을 살펴봅니다.
Contents
이 글은 이선협 님의 소프트웨어 파괴의 미학 을 읽고 개인적으로 정리해 본 글입니다.
사라질 수밖에 없는 코드들
아름다운 소프트웨어를 위해서 비즈니스의 정책들이 간단했으면 좋겠습니다. 하지만 비즈니스의 복잡도는 시간이 지날수록 점점 더 복잡해지곤 합니다. 이에 따라 우리의 코드들도 점점 복잡해지곤 합니다.
만약 엔지니어들이 복잡한 비즈니스들에 대해 모두 알고 있다면, 엔지니어들은 안정적이고 고도화된 코드들을 만들 수 있을까요 ? 왠지 아닐 것 같습니다. 왜냐하면 개발자들이 현재의 요구사항들을 잘 안다 하더라도, 요구사항은 항상 변화하기 때문입니다. 즉, 개발자들이 도메인 지식을 완전히 이해하고 코드를 작성한다 하더라도, 우리들이 작성한 코드들은 변화하거나 사라질 수밖에 없다는 것입니다.
  이러한 상황을 깨달은 개발자들은 크게 두 가지로 반응하곤 합니다. 먼저 디오니소스적인 방법으로 혼란에 익숙해지고 염세적인 태도를 취하는 것입니다. 어차피 바뀔테니 설계, 방법론같은 것은 무의미해 와 같은 생각으로 이어지기도 합니다. 또 다른 방식으로, 아폴론적인 방법이 있습니다. 소프트웨어 개발에 대한 이상향을 그리기도 하고, 이상적인 이데아를 향해 다가가려 노력합니다. 이러한 강박으로 인해 경직되고 획일화된 사고를 지니기도 합니다.
스스로를 돌아보았을 때에, 신입사원 때에는 아폴론적인 자세를 취했던 것 같습니다. 뛰어난 엔지니어가 되기 위해 많이 노력했지만, 디오니소스적인 비즈니스의 혼란은 외면하려 했습니다. 하지만 역설적이게도, 속한 팀이 더 성장하기 위해서는 디오니소스적인 혼란이 필요하다는 사실을 알게 되었습니다. 비즈니스의 성장에는 혼란이 도움이 될 때가 많습니다. 좋은 엔지니어가 되기 위해서는 아폴론적인 질서도 중요하지만, 반대로 디오니소스적인 혼란을 잘 다루는 방법도 중요하다는 사실을 깨닫게 되었습니다.
파괴 지향 개발 방법론
만약 소프트웨어 개발에서 혼란을 피할 수 없다면, 관점을 바꾸어서 코드를 작성할 때부터 파괴될 것을 염두하고 코드를 작성하는 것은 어떨까요 ? 위의 글에서 글쓴이는 다음의 세 가지 대원칙을 제시하며 파괴 지향 개발 방법론을 소개하고 있습니다.
* 불확실성이 있다면 가능한 만큼 불확실성을 줄인다.
* 여러 방법을 선택할 수 있다면 파괴하기 쉬운 쪽을 선택한다.
* 필요한 것만을 유지한다. 따라서 필요 없는 것은 전부 지운다.
  세 가지 대원칙을 읽어보니, 파괴 지향 개발 방법론과 일반적인 좋은 코드의 원칙이 꽤나 겹친다는 사실을 발견할 수 있습니다. 이 글을 읽고, 좋은 코드를 작성하기 위한 방법론은 비슷하지만, 코드 자체를 바라보는 관점이 많이 바뀌었다고 느꼈습니다. 기존의 코드 작성 방법론들을 파괴 지향 개발 방법론에서는 어떻게 해석할까요 ?
파괴 가능성
소프트웨어로 코드를 작성할 때, 어떻게 하면 파괴하기 쉬운 코드를 작성할 수 있을까요 ?
변경하기 쉽게 만들고, 쉽게 변경하라 - 켄트 벡
변경하기 쉬운 코드는 곧 파괴하기도 쉽습니다. 글쓴이는 독립성, 인지가능성, 통제가능성을 척도로 제시합니다.

- 독립성 : 결합도와 응집도의 정도, 단일 책임 원칙을 어느정도로 지켰는지로 판단할 수 있다. 코드는 독립적일 수록 파괴하기 쉽습니다.
 - 인지가능성 : 말 그대로 개발자가 코드를 보고 이해할 수 있는 정도를 말합니다.
 - 통제가능성 : 개발자가 통제할 수 있는 영역인지를 말합니다. 코드 오너십이 흐려져 그 누구도 관리하는 사람이 없다면 통제하기 힘든 코드가 됩니다. 그리고 작성된 코드가 문제가 있을 수도 있다면 마찬가지로 파괴하기 어렵습니다.
 
위의 특징들을 이해한 뒤, 파괴하기 쉬운 코드를 위해 노력해야 합니다.
복잡성 제거
사용하지 않는 코드는 제거해야 합니다. "혹시 사용할 지 모르니 남겨두자" 라는 생각은 하지 않아도 됩니다. 형상관리 시스템을 통해, 해당 코드가 필요한 상황이 오면 다시 복구할 수 있습니다.
단일 책임 원칙
단일 책임 원칙은 객체의 역할을 나눌 때에도 중요하지만, 파괴하기 쉬운 코드를 만들 때에도 도움이 됩니다. 책임이 명확하고 적은 객체는 파괴하기도 쉽습니다.
스트랭글러 무화과 패턴
스트랭글러 무화과 패턴 은 마틴 파울러가 제시한 레거시 코드 교체 방법론입니다. 동일하게 같은 방법으로, 코드를 파괴하는 과정에도 스트랭글러 무화과 패턴을 사용할 수 있습니다.
class LegacyObject {
  fun oldMethod1() {
    // ...
  }
  fun oldMethod2() {
    // ...
  }
}
class NewObject {
  private val legacyObject = LegacyObject()
  fun newMethod1() {
    // ...
  }
  fun oldMethod2() {
    legacyObject.oldMethod2()
  }
}
그렇다면 일반적인 프로그래밍 방법론에서는 소개하지 않지만, 파괴 지향 개발 방법론에서는 나온 방법론은 무엇이 있을까요 ?
메서드 전문화
보통 개발을 하다 보면, 공통적인 로직을 발견하면 공통화를 하려 노력합니다. 하지만 공통화된 코드는 파괴하기 힘든 코드이기도 합니다. 우리는 항상 저울질을 해가며 파괴하기 쉬운 코드가 무엇인지 고민해야 합니다. 예를 들어 아래와 같은 코드를 살펴봅시다.
// 일반화된 메서드
fun calculate(a: Int, b: Int, operator: String): Int {
  return when (operator) {
    "+" -> a + b
    "-" -> a - b
    "*" -> a * b
    "/" -> a / b
    else -> throw IllegalArgumentException("Unknown operator")
  }
}
// 메서드 전문화
fun add(a: Int, b: Int): Int {
  return a + b
}
fun subtract(a: Int, b: Int): Int {
  return a - b
}
fun multiply(a: Int, b: Int): Int {
  return a * b
}
fun divide(a: Int, b: Int): Int {
  return a / b
}
calculate 함수는 사칙연산을 모두 수행할 수 있는 공통화된 함수이지만, 복잡성이 늘어나고 제거하기 힘든 함수이기도 합니다. 일반화된 코드는 제거하기 힘든 코드임을 유념하며, 공통화 여부를 결정하도록 합시다.
중복 코드 작성하기
변화할 가능성이 높은 파일에서는 일부러 중복 코드를 작성하는 것도 좋은 방법입니다. 중복 코드 작성하기는 메서드 전문화와 마찬가지로, 개발자의 경험과 직관에 따라 선택할 수 있습니다. 개발자의 본능을 매우 거스르는 일이므로, 중복 코드의 비용과 편익을 잘 계산해야 합니다.
마치며
  조영호 님께서 작성하신 설계 트레이드오프 를 읽고, 완벽한 프로그래밍 방법론은 없다 라는 생각을 했었는데, 이 글 또한 같은 메세지를 전달해준 글이었습니다. 개인적으로는 파괴 지향 개발 방법론에 대해 많이 공감이 되었고, 앞으로는 설계에 대해 고민할 때 어떤 코드가 지우거나 변경하기 쉬운 코드일까 ? 라는 기준을 세워서 고민해보려 합니다. 
이것도 읽어보세요