[객체지향의 사실과 오해] 7장

2020. 4. 28. 20:40책/객체지향의 사실과 오해

7장 함께 모으기

코드와 모델을 밀접하게 연관시키는 것은 코드에 의미를 부여하고 모델을 적절하게 한다. -에릭 에반스

 

객체지향 설계의 세가지 관점

마틴 파울러는 객체지향 설계안에 존재하는 세가지 관점을 각각 개념 관점, 명세 관점, 구현 관점이라고 부른다. 

그리고 이것은 곧, 개발자가 소프트웨어를 개발하는데 있어서 클래스를 어떻게 설계해야 하느냐에 대한 힌트가 될 수 있다.

각 관점에 대해 설명하자면,

  • 개념 관점은 도메인 안에 존재하는 개념과 개념들 사이의 관계를 표현하는 것을 의미한다. 이때 도메인이 의미하는 것은 사용자들이 관심을 가지고 있는 특정분야나 주제를 말하며 소프트웨어는 도메인에 존재하는 문제를 해결하기 위해 개발된다;
  • 명세 관점은 사용자의 영역인 도메인을 벗어나 개발자의 영역인 소프트웨어로 초점이 옮겨지는 것이다. 명세 관점에서 프로그래머는 객체가 협력을 위해 '무엇'을 할 수 있는가에 초점을 맞춘다. 즉, 인터페이스에 대한 관점이다.
  • 구현 관점은 우리에게 가장 익숙한 관점으로, 실제 작업을 수행하는 코드와 연관돼 있다. 구현 관점의 초점은 객체들이 책임을 수행하는 데 필요한 동작하는 코드를 작성하는 것이다. 따라서 프로그래머는 객체의 책임을 '어떻게'수행할 것인가에 초점을 맞추며 인터페이스를 구현하는 데 필요한 속성과 메서드를 클래스에 추가한다.

위의 세 관점의 순서대로 소프트웨어를 개발하는 것은 아니다. 각 관점은 동일한 클래스를 세 가지 다른 측면에서 바라보는 것을 의미한다.

클래스는 세가지 관점을 모두 수용할 수 있도록 개념, 인터페이스, 구현을 함께 드러낼 수 있어야한다.

동시에 코드 안에서 세 가지 관점은 쉽게 식별할 수 있도록 분리되어야 한다. 

 

 

코드와 세가지 관점

코드는 세가지 관점을 모두 제공해야 한다.

 

개념관점에서 코드를 바라보면 여러가지 클래스가 보인다. 이 클래스들을 자세히 살펴보면 도메인 모델을 구성하는 중요한 개념과 관계를 반영한다는 사실을 쉽게 알 수 있을 것이다. 소프트웨어 클래스가 도메인 개념의 특성을 최대한 수용하면, 변경을 관리하기 쉽고 유지보수성을 향상시킬 수 있다. 예를들어, 커피를 제조하는 과정을 코드로 옮겼을때 Customer,Menu,MenuItem,Barista,Coffe클래스가 있다고 해보자. 이 클래스들을 보면 커피 전문점 도메인을 구성하는 개념과 관계를 쉽게 파악할 수 있을 것이다.

이때, 커피를 제조하는 과정을 변경하기 위해서는 어떤 클래스를 수정해야할까? 현실 세계와 동일하게 소프트웨어 안에서도 Barista클래스가 커피를 제조할 것이라고 쉽게 유추할 수 있을 것이다. 소프트웨어 클래스와 도메인 클래스 사이의 간격이 좁을수록 기능을 변경하기 위해 뒤적거려야 하는 코드의 양도 줄어들 것이다.

 

명세 관점은 클래스의 인터페이스를 바라본다. 클래스의 public 메서드는 다른 클래스가 협력할 수 있는 공용 인터페이스를 드러낸다. 

공용 인터페이스는 외부의 객체가 해당 객체에 접근할 수 있는 유일한 부분이다. 인터페이스를 수정하면 해당 객체와 협력하는 모든 객체에게 영향을 미칠 수 밖에 없다. 객체의 인터페이슨느 수정하기 어렵다는 사실을 명심해야겠다. 최대한 변화에 안정적인 인터페이스를 만들기 위해서는 인터페이스를 통해 구현과 관련된 세부사항이 드러나지 않도록 해야 할 것이다. 변화에 탄력적인 인터페이스를 만들 수 있는 능력은 객체지향 설계자의 수준을 가늠하는 중요한 척도가 될 것이다.

 

구현 관점은 클래스의 내부 구현을 바라본다. 클래스의 메서드와 속성은 구현에 속하며 공용 인터페이스의 일부가 아니다. 따라서 메서드의 구현과 속성의 변경은 원칙적으로 외부의 객체에게 영향을 미쳐서는 안된다. 이것은 메서드와 속성이 철저하게 클래스 내부로 캡슐화 되어야 한다는 것을 의미한다. 메서드와 속성은 클래스 내부의 비밀이다. 외부의 클래스는 자신이 협력하는 다른 클래스의 비밀 때문에 우왕좌왕 해서는 안된다. 

 

인터페이스와 구현을 분리하라

이 책은 마지막 부분에 인터페이스와 구현을 분리할 것을 다시한번 강조하고 있다.

 

이것은 즉, 명세관점과 구현관점이 뒤섞이는 것을 막자는 것이다. 명세 관점은 클래스의 안정적인 측면을 드러내야 한다. 구현 관점은 클래스의 불안정한 측면을 드러내야 한다. 인터페이스가 구현 세부 사항을 노출하기 시작하면 아주 작은 변동에도 전체 협력이 요동치는 취약한 설계를 얻을 수 밖에 없다. 

 

프로그래머의 입장에서 가장 많이 접하게 되는 것은 코드이므로 구현 관점을 가장 빈번하게 사용하겠지만 실제로 훌륭한 설계를 결정하는 측면은 명세 관점인 객체의 인터페이스다. 명세 관점이 설계를 주도하게 하면 설계의 품질이 향상될 수 있다는 사실을 기억하자.

 

느낀점

중요한 것은 클래스를 봤을 때 내 자신이 클래스를 명세 관점과 구현 관점으로 나눠볼 수 있어야 한다는 것이다. 캡슐화를 위반해서 구현을 인터페이스 밖으로 노출해서도 안되고, 인터페이스와 구현을 명확하게 분리하지 않고 흐릿하게 섞어놓아서도 안된다. 결국 세가지 관점 모두에서 클래스를 바라볼 수 있으려면 훌륭한 설계가 뒷받침 되어야 하는 것이다.

OOP스터디를 진행하면서 나의 설계가 이러한 세 가지 관점에서 보았을때 어떠한 평가를 내릴 수 있을지를 항상 생각하면서 개발에 임해 보아야겠다. 

부록내용이 있지만 정식 내용은 7장에서 이 책은 끝이난다. 

이 책을 만난건 정말이지 행운이라고 생각할 수 있겠다. 

객체지향 프로그래밍이라는 과목의 성적이 좋았고, 자바 어플리케이션을 이것저것 개발해보면서 나는 내가 객체지향 프로그래밍을 할 줄 안다고 생각했었다. 하지만, 이 책을 읽고 난 후 나는 진짜 객체지향이 무엇인지를 알게 되었다. 클래스 중심의 설계와 코딩을 했던 과거의 습관은 버리고, 이 책을 통해 얻게된 진짜 객체지향적 설계를 계속해서 연습해봐야겠다.