마치며: 나아가기

앨리스터 코어번은 사람들이 새로운 기술을 학습하기 위해서는 일반적으로 세 가지 단계를 거치게 된다고 설명한다. 코어번은 이 세 가지 단계를 ‘따라 하는 수준’, ‘분리 수준’, ‘거침없는 수준’이라고 부른다.

어떤 기술을 처음 학습하려는 사람은 ‘따라 하는 수준’에서 시작한다. 이 단계에 있는 사람은 제대로 활용할 수 있는 단 하나의 절차를 찾는다. 적합한 열 가지의 절차가 있더라도 모든 절차를 한번에 습득하는 것은 불가능하기 때문에 가장 쉽게 배울 수 있는 단 한 가지 절차를 학습하고 그대로 모방한다. 이 단계에서 학습자에게 중요한 것은 절차를 모방했을 때 얻어지는 성공의 달콤함이다.

다음 단계인 ‘분리 수준’의 사람들은 오직 단 하나의 절차만으로 모든 문제를 해결할 수 없다는 사실을 깨닫고 다양한 절차를 학습하고 트레이드오프한다. 이 단게는 절차의 한계를 배우는 수준이라고 할 수 있다. 이 단계에서는 모든 절차를 배우게 되고 어떤 절차가 어떤 상황에 적절하고 어떤 상황에는 적절하지 않은지를 배운다.

‘분리 수준’ 단계를 거친 학습자들은 모든 경우에 올바른 절차란 존재하지 않는다는 사실을 이해하고 각 상황에 따라 적절한 절차를 적용할 수 있는 판단력과 유연함을 익힌다.

마지막 단계인 ‘거침없는 수준’에 이르면 이제 절차는 중요하지 않게 된다. ‘거침없는 수준’에 이른 사람은 많은 학습과 경험을 통해 즉시 적절한 해법을 직관적으로 떠올릴 수 있을뿐만 아니라 때로는 자신만의 방법에 따라 문제를 해결하기도 한다. 이 단계에 이르면 특정한 절차나 방법을 따르는지 여부는 개의치 않는다. 단지 무엇을 해야 하는지를 이해하고 그것을 달성하기 위한 자신만의 절차와 방법을 적용한다.

이 단계에 이르면 과거에 익혔던 모든 절차를 트레이드오프하는 수준을 벗어나 자신에게 가장 적합한 절차를 정하게 된다.

이 책은 학습의 첫 번째 단계인 ‘따라 하는 수준’이라고 가정하고 가장 이상적인 절차와 방법을 통해 객체지향 설계를 증명했다. 중간중간 설계 트레이드오프에 관해 언급하기도 했다. 실무에서는 또 다른 문제를 직면하게 될 것이고 그 문제에서 트레이드 오프할 수 있는 능력을 길러야 한다.

소프트웨어 설계를 설명하기 어려운 이유는 설계 방법이 다양할뿐만 아니라 설계 절차를 정형화된 단계로 설명하는 것이 어렵기 때문이다. 소프트웨어 설계는 머리로 고민하고, 고민한 결과를 스케치하고, 스케치한 결과를 코드로 옮기는 논리적인 단계를 따르지 않는다. 설계자는 머릿속에 얽히고설킨 다양한 가능성의 실타래를 풀기 위해 다양한 방법을 시도한다.

실제로 완성된 설계는 절차에 따라 매끄럽게 진행된 것이 아니라 다양한 시행착오와 실패가 누적된 결과물이다.

소프트웨어를 설계하는 단 하나의 방법이란 존재하지 않는다. 동일한 요구사항이라도 소프트웨어를 설계하는 절차와 방법, 결과물은 수행하는 사람마다 다르며, 사람이 동일하다고 하더라도 환경과 도메인에 따라 달라진다. 한마디로 설계를 설명하는 것은 어렵다. 실무자들은 학습의 마지막 단계인 ‘거침없는 수준’에 이른 상태이기 때문에 정해진 절차를 따르지 않는다. 단지 결과물을 완성한 후에 미리 정해진 절차와 방법에 따라 작업한 것처럼 논리적으로 설명하는 것이다.

이 책을 읽고 능숙하게 객체지향 설계를 할 수 있을 것이라고 생각할 수 있지만, 안타깝게도 그렇지 않을 것이다. 따라하는 수준에서 머무르기에 실제 문제를 만나고 트레이드오프를 해야 하는 상황에서 어떤 방법을 선택해야 하는지 판단할 수 있는 능력을 길러야 한다. (많은 시간을 들여야 함)

따라서 다음과 같은 방법들을 통해 다양한 설계 기법을 익히고 통찰력을 길러 ‘분리 수준’을 향해 나아가기 바란다.

  • 디자인 패턴: 반복적으로 발생하는 문제와 해법을 쌍으로 담고 있기 때문에 문제에 적합한 디자인 패턴을 고른다면 고품질 설계를 짧은 시간에 얻을 수 있는 지름길을 제공한다. 실무에서는 생각 이상으로 다양한 디자인 패턴이 존재한다. 이를 적용해보고 설계를 트레이드오프할 수 있는 능력을 기를 수 있는 가장 좋은 방법인 동시에 훌륭한 객체지향 설계의 특징을 배울 수 있는 훌륭한 참고 자료다.
  • 리팩터링: 리팩터링은 코드의 행동은 변경하지 않은 채 코드의 구조를 개선하는 활동을 의미한다. 설계는 코드의 배치이므로 코드의 구조를 개선한다는 것을 곧 설계를 개선하는 것을 의미한다. 따라서 리팩터링 관점을 ‘구현 전에 설계하기’에서 ‘항상 설계하기’로 바꾼다. 결국 리팩터링은 구현 전에 설계를 완성해야 한다는 강박에서 해방시켜준다.
  • 테스트-주도 개발: 테스트 주도 개발은 마지막 거침없는 수준에 이른 사람들이 제시한 동창적인 설계 방법 중 하나다. 테스트-주도 개발은 전통적인 설계-구현-테스트의 순서로 수행되는 구현절차를 테스트-구현-설계의 순서로 바꾼다. 결국 메시지를 먼저 선택하고 메시지가 객체를 선택하게 한다는 책임-주도 설계 방법과도 잘 어울린다.

책임 주도 설계가 ‘따라 하는 수준’에 있는 사람들을 위한 가이드라면 위의 기법들은 책임 주도 설계를 벗어나 ‘분리 수준’으로 나아가는 사람들을 위한 기법이다. 다양한 기법을 적용하고 실험해봄으로써 실력을 향상시켜 나가기 바란다.

가장 중요한 점은 어떤 기법도 홀로 존재하지 않는다는 것으로 책임 주도 설계에서 제공하는 다양한 책임 관점의 시각을 테스트 주도 개발에 적용할 수 있다. 책임 주도 설계에서 이야기하는 올바른 역할, 책임, 협력의 분리를 향해 리팩터링해 나아갈수 있다. 디자인 패턴은 역할, 책임, 협력에 관한 일종의 탬플릿 집합이다.

다양한 기법들을 혼합하라. 스스로만의 절차와 기법을 찾아라. 가장 중요한 것으로 코드를 작성하는 매 순간마다 끊임없이 고민하고 트레이드오프하라.

댓글남기기