007. (The Essence of Object-Orientation) 7. 객체지향 설계의 세 가지 관점

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

마틴 파울러는 객체지향 설계 안에 존재하는 세 가지 상호 연관된 관점에 관해 아래와 같이 분류하였다.

각각 개념 관점(Conceptual Perspective), 명세 관점(Specification Perspective), 구현 관점(Implementation Perrspective) 이며 각각 살펴보도록 하자.

7.1. 개념 관점 / 명세 관점 / 구현 관점

7.1.1. 첫 번째 관점 - 개념

개념 관점에서 설계는 도메인 안에 존재하는 개념과 개념들 사이의 관계를 표현한다.

도메인이란 사용자들이 관심을 가지고 있는 특정 분야나 주제를 뜻하고, 소프트웨어는 이 도메인에 존재하는 문제를 해결하기 위해 개발된다.

즉, 개념 관점에서의 설계는 사용자가 도메인읇 바라보는 관점을 반영하며, 실제 도메인의 규칙와 제약을 최대한 유사하게 반영하는 것이 핵심이다.

객체지향의 세계에서 클래스가 현실 세계를 은유하는 것이 이 개념 관점이다.

7.1.2. 두 번째 관점 - 명세

명세 관점에서 설계는 도메인 영역을 벗어나 개발자의 영역인 소프트웨어로 초점이 옮겨진다.

명세 관점은 도메인이 아닌 소프트웨어 내 객체들의 책임에 초점을 맞추기 때문에 객체의 인터페이스를 바라보게 된다.

즉, 명세 관점에서의 설계는 객체가 협력을 위해 무엇을 할 수 있는가를 집중적으로 본다.

이를 통해 인터페이스와 구현을 분리하는 객체지향의 기본적인 원칙을 준수한다.

객체지향의 세계에서 클래스가 구현하는 공용 인터페이스가 이 명세 관점이다.

7.1.3. 세 번째 관점 - 구현

구현 관점에서의 설계는 개발자에게 가장 익숙한 관점으로, 실제 작업을 수행하느 코드와 관련이 있다.

구현 관점에서는 객체들이 책임을 수행하는 데 필요한 동작을 코드로 작성하는 데 초점을 두며,

객체의 책임을 어떻게 수행할 것인가에 집중하여, 인터페이스를 구현하는 데 필요한 속성과 메서드를 클래스가 작성하게 된다.

객체지향의 세계에서 클래스의 속성과 메서드의 작성이 이 구현 관점이다.

7.1.4. 클래스의 설계 방향

위의 세 가지 관점은 클래스를 어떻게 설계해야하는지 그 방향성을 제시한다.

클래스는 세 관점을 모두 수용할 수 있도록 개념과 인터페이스 그리고 구현을 함께 표현해야 하며

코드 레벨에서도 세 가지 관점을 쉽게 식별할 수 있도록 분리해야할 필요성이 있다.

우리는 지금까지 객체의 인터페이스를 식별하기 위해 역할, 책임, 협력을 이용해 식별해왔다.

협력에 참여하기 위해 객체가 수신해야하는 메시지를 결정하고, 메시지들이 모여 객체의 인터페이스를 구성해야 한다.

따라서 협력 안에서 메시지를 선택하고 메시지를 수신할 객체를 선택하는 것은 객체의 인터페이스, 즉 명세 관점에서 객체를 바라보는 것이다.

7.2. 설계와 구현

객체지향 설계의 첫 번재 목표는 훌륭한 객체를 설계하는 것이 아닌 훌륭한 협력을 설계하는 것이다.

훌륭한 객체는 훌륭한 협력을 설계할 때만 얻을 수 있기때문이다.

협력을 설계할 때는 객체가 메시지를 선택하는 것이 아닌, 메시지가 객체를 선택하도록 해야 한다.

메시지를 수신할 객체는 메시지를 처리할 책임을 맡게 되고, 객체가 수신하는 메시지를 객체가 외부에 제공하는 공용 인터페이스에 포함된다.

7.3. 코드와 세 가지 관점

상술했듯 코드 레벨에서도 세 가지 관점을 쉽게 식별할 수 있도록 분리해야할 필요성이 있다.

개념 관점 에서는 소프트웨어를 구성하는 클래스들이 소프트웨어가 제공하고자 하는 도메인의 개념과 관계를 반영한다.

클래스가 도메인 개념의 특성을 최대한 수용할수록 변경을 관리하기 쉽고 유지보수성을 향상시킬 수 있다.

또한 소프트웨어 클래스와 도메인 클래스의 갭이 적을 수록 기능을 변경하기 위해 파악해야할 코드의 양도 감소한다.

명세 관점 에서는 클래스의 인터페이스를 바라본다.

외부에서 접근 가능한 클래스의 공용 인터페이스를 파악하고, 이 인터페이스의 수정이 해당 클래스의 객체와 협력 관계에 있는 모든 객체에게 영향을 줄 수 있으므로, 인터페이스의 수정은 난이도가 있는 편이다.

최대한 변화에 안정적인 인터페이스를 만들기 위해서는 인터페이스를 통해 구현 세부 사항이 드러나지 않도록 외부에서 식별 가능한 동작만을 표현해주어야 한다.

변화에 탄력적인 인터페이스를 만드는 것이야말로 객체지향 설계자의 수준을 가늠하는 중요한 척도이다.

구현 관점 에서는 클래스의 내부 구현 자체를 바라본다.

클래스의 메서드와 프로퍼티는 구현에 속하며, 공용 인터페이스의 일부가 아니다.

따라서 메서드의 구현과 프로퍼티의 변경은 원칙적으로 외부 객체에 영향을 주지않도록 캡슐화되어야 한다.

7.4. 인터페이스와 구현의 분리

인터페이스와 구현은 꼭 분리되어야 한다.

명세 관점과 구현 관점이 뒤섞이면 코드의 파악이 더욱 어려워지기 때문이다.

명세 관점은 클래스의 안정적인 측면을, 구현 관점은 클래스의 불안정한 측면을 표현하도록 하여

인터페이스가 구현 세부 사항을 노출하지않도록 설계해야 한다.