책임과 메시지
객체지향 패러다임이 전통적인 패러다임에 비해 우월한 이유는 뭘까?
객체지향에서는 명확한 책임을 가진 객체들이 협력에 참여해야 한다. 그러나 책임은 ‘어떻게’가 아닌 ‘무엇을’ 이라는 형태로 나타나야 하며, 객체가 책임을 수행하는 방식의 자율성을 보장해주어야 한다.
객체는 메세지를 전송하여 다른 객체에게 접근할 수 있다. 이 메시지에 추가적인 정보가 필요하면 인자(argument)로 이를 표현할 수 있다.
메서드
객체에게 메시지를 전송하면 결과적으로 메시지에 대응되는 메서드가 실행된다. 어떤 메서드를 호출할 지 실행 시간에 결정할 수 있는 것은 객체지향의 핵심이다.
다형성
다형성은 서로 다른 타입에 속하는 객체가 동일한 메시지를 수신할 경우, 서로 다른 메서드로 이를 처리할 수 있는 메커니즘을 의미한다.
송신자는 수신자가 누구인지 모르고 전송할 수 있으며, 메시지를 처리하는 방식 역시 수신자 마음이다. 이는 책임을 수행하는 객체의 대체 가능성을 의미한다. 즉 송신자가 메시지를 보내기만 하면 이를 처리할 수 있는 어떤 객체와도 협력할 수 있다는 것이다. 다형성을 이용하면 수신자의 종류를 캡슐화 할 수 있기 때문이다.
다형성을 사용했을 때의 장점은 아래와 같다.
- 협력이 유연해진다.
- 협력이 수행되는 방식을 확장할 수 있다.
- 협력이 수행되는 방식을 재사용할 수 있다.
메시지를 기반으로 얇게 결합하여 유지되는 협력 덕분에 이렇게 유연하고 확장 가능한 설계가 가능해지는 것이다. 따라서 시스템을 설계할 때는 객체 간의 협력 관계를 우선시하고, 그들 간의 메시지를 중심으로 생각한다.
책임-주도 설계
객체들은 책임을 완수하기 위해 메시지를 기반으로 협력한다. 즉 메시지는 수신자의 책임을 결정한다. 따라서 필요한 행위를 먼저 결정하고 이 행위를 수행할 객체를 선택하는 과정을 What/Who 사이클이라고 한다. 중요한 건 어떻게 책임을 수행할 지 구체적으로 묻는 것이 아니라 그저 ‘시키는 것’에 그친다는 것이 핵심이다.
메시지 중심의 설계는 시스템의 변경이 더 자유롭고 유연해지도록 돕는다. 메시지를 기반으로 객체들이 협력 과정에 참여할 수 있기 때문에 재사용성이 보장되기 때문이다.
인터페이스
인터페이스는 아래와 같은 특징이 있다.
- 인터페이스의 사용법을 익히면 내부 구조나 동작 방식으르 몰라도 대상을 조작할 수 있다.
- 내부 구성이나 작동 방식을 변경해도 인터페이스는 동일하게 동작한다.
- 사용하는 주체가 변경되어도 인터페이스를 제공하면 상호작용할 수 있다.
객체의 인터페이스는 객체가 수신할 수 있는 메시지의 목록으로, 객체를 사용하기 위한 가이드북이라고 볼 수 있다. 외부 객체들은 한 객체의 공용 인터페이스를 통해 그 객체와 메시지를 주고 받는다.
인터페이스와 구현은 분리되어야 한다. 외부에 드러난 인터페이스는 정적이고, 구현은 동적이다. 인터페이스와 구현을 분리함으로써 외부에 영향을 주지 않고도 메서드를 자유롭게 변경할 수 있다. 이러한 원칙을 수행하기 위한 객체 설계 방법을 캡슐화라고 한다.
자율성을 보장하는 이유
메시지를 보낼 때 How가 아닌 What을 요청한다고 했다. 그리고 수신자는 메시지를 처리하는 방식에 있어 자율적이다. 이렇게 자율성을 보장하는 이유는, 책임이 자율적일수록 협력이 이해하기 쉬워지고 유연하게 변경 가능해지기 때문이다. 자세하게 설명해보자.
- 자율적인 책임은 협력을 단순하게 한다.
- 자율적인 책임은 외부와 내부를 명확하게 분리한다.
- 메시지를 전달 받는 외부와 책임을 수행하는 방식인 내부가 분리된다.
- 책임을 수행하는 내부 방식을 변경하여도 외부에 영향을 끼치지 않는다.
- 협력의 대상을 다양하게 선택할 수 있는 유연성을 제공한다.
- 책임이 자율적일수록 객체의 역할을 이해하기 쉽다
- 객체의 존재 이유가 메시지를 처리하는 행동 방식에 드러나기 때문에 객체의 응집도를 높게 유지할 수 있다.
객체 지도
이 장은 프로그램의 기능과 구조에 대한 설명을 한다.
핵심적인 내용은 기능이 아닌 구조를 기반으로 모델을 구축하는 것이 변경에 안정적이다라는 것이다. 요구사항은 계속 변하기 때문에 안정적인 구조를 중심으로 기능을 종속시키는 접근법이 유연한 모델을 만들 수 있다.
설계의 일차적인 목표는 변경에 소요되는 비용을 낮추는 것이다. 객체지향은 객체의 구조를 중심으로 시스템의 기능이 동작하기 때문에 시스템 기능의 책임은 적절한 객체의 책임으로 분배된다. 따라서 기능이 변경되더라도 객체 간의 구조는 유지된다.
구조와 기능
구조는 사용자가 도메인에 관해 생각하는 개념들과 그 관계들로 표현된다. 이를 표현하기 위한 기법을 도메인 모델링이라고 한다.
반면 기능은 사용자의 목표를 만족시키기 위해 책임을 수해앟는 시스템의 행위를 의미하고, 유스케이스 모델링으로 이를 표현한다.
우리는 도메인 모델을 기반으로 코드를 작성해야한다.
- 사용자와 실제 시스템의 표현적 차이를 줄일 수 있다.
- 표현적 차이란 현실 세계의 객체와 소프트웨어 객체 사이의 의미적 거리를 뜻한다. 우리는 도메인 객체를 은유하여 소프트웨어 객체를 설계해야한다. 이 과정을 통해 표현적 차이를 줄일 수 있고, 사용자가 도메인을 바라보는 관점을 코드에 반영할 수 있게 된다.
- 도메인 모델이 제공하는 구조가 더 안정적이다.
- 사용자들이 도메인의 본질적 특징을 더 잘 안다. 본질적 특징은 변경이 적기 때문에 이를 기반으로 코드를 설계하면 변경에 더 쉽게 대처할 수 있다.
유스케이스는 사용자의 목표를 달성하기 위해 시스템과 사용자 간의 이루어지는 상호작용을 텍스트로 정리한 것이다. 유스케이스는 여러 시나리오의 집합이다. 각각의 시나리오를 유스케이스 인스턴스라고 한다. 유스케이스는 단순 기능 목록과는 다르게 이야기를 통해 연관된 기능들을 기술할 수 있다. 이는 사용자 인터페이스와 관련된 세부 정보를 포함하지 않고, 오로지 시스템의 행위에만 초점을 맞춘다. 역시 내부 설계와 관련한 정보를 포함하지 않는다.
따라서 사용자가 시스템을 통해 원하는 기능을 얻는 넓은 관점에서 그 과정을 정리해보자면,
- 시스템은 사용자에게 특정 기능을 제공할 책임을 가진다. (유스케이스 모델링)
- 시스템은 이 책임을 더 작은 크기의 객체들의 협력으로 구현한다.
- 도메인 모델에 포함된 개념을 은유하는 소프트웨어 객체를 선택하여 시스템의 기능을 완성한다. (도메인 모델링)
이러한 일련의 과정을 책임-주도 설계라고 통칭하는 것이다.
연결완전성
안정적인 도메인 모델을 기반으로 구현한 경우 시스템의 기능이 변경되더라도 전체적인 구조가 흔들리지 않는다. 객체지향에서는 도메인 모델링에서 사용한 객체와 개념을 프로그래밍 설계에서 객체와 클래스로 변환할 수 있다. 이를 연결 완전성이라고 하며, 반대 개념인 가역성 역시 성립한다.
'DEV book > 객체지향의 사실과 오해' 카테고리의 다른 글
[OOP] 객체지향의 사실과 오해 3, 4장 리뷰 - 역할, 책임, 협력 (0) | 2024.02.02 |
---|---|
[OOP] 객체지향의 사실과 오해 1, 2장 리뷰 - 객체지향의 본질 (0) | 2024.01.31 |