이 글은 오브젝트라는 책을 읽고 정리한 글입니다.
14장에서는 유사한 요구사항을 구현하기 위해 유사한 협력 패턴을 적용하면 시스템을 이애하기 쉽고 유연하게 만들 수 있다는 사실을 살펴봅니다.
객체지향 설계의 목표는 적절한 책임을 수행하는 객체들의 협력을 기반으로 결합도가 낮고 재사용 가능한 코드 구조를 창조하는 것이다.
객체들의 협력 구조가 서로 다른 경우에는 코드를 이해하기도 어렵고 코드 수정으로 인해 버그가 발생할 위험성도 높아진다. 유사한 요구사항을 계속 추가해야 하는 상황에서 각 협력이 서로 다른 패턴을 다를 경우에는 전체적인 설계의 일관성이 서서히 무너지게 된다.
객체지향 패러다임의 장점은 설계를 재사용할 수 있다는 것이다. 하지만 재사용은 공짜로 얻어지지 않는다. 재사용을 위해서는 객체 들의 협력 방식을 일관성 있게 만들어야 한다. 특정한 문제를 유사한 방법으로 해결하고 있다는 사실을 알면 문제를 이해하는 것만으로도 코드의 구조를 예상할 수 있게 된다.
가능하면 유사한 기능을 구현하기 위해 유사한 협력 패턴을 사용하라.
핸드폰 과금 시스템 변경하기
구간별 방식 구현하기
대부분의 사람들은 유사한 요구사항을 구현하는 코드는 유사한 방식으로 구현될 것이라고 예상한다. 하지만 유사한 요구사항이 서로 다른 방식으로 구현돼 있다면 요구사항이 유사하다는 사실 자체도 의심하게 될 것이다.
결론은 유사한 기능을 서로 다른 방식으로 구현 해서는 안 된다는 것이다. 일관성 없는 설계와 마주한 개발자는 여러 가지 해결 방법 중에서 현재의 요구사항을 해결하기에 가장 적절한 방법을 찾아야 하는 부담을 안게 된다.
유사한 기능은 유사한 방식으로 구현해야 한다. 객체 지향에서 기능을 구현하는 유일한 방법은 객체 사이의 협력을 만드는 것 뿐이므로 유지보수 가능한 시스템을 구축하는 첫걸음은 협력을 일관성 있게 만드는 것이다.
설계에 일관성 부여하기
일관성 있는 설계를 만드는 데 가장 훌륭한 조언은 다양한 설계 경험을 익히라는 것이다. 일관성 있는 설계를 위한 두 번째 조언은 널리 알려진 디자인 패턴을 학습하고 변경이라는 문맥 안에서 디자인 패턴을 적용해 보라는 것이다. 디자인 패턴은 특정한 변경에 대해 연관성 있는 설계를 만들 수 있는 경험 법칙을 모아놓은 일종의 설게 템플릿이다.
디자인 패턴이 반복적으로 적용할 수 있는 설계 구조를 제공한다고 하더라도 모든 경우에 적합한 패턴을 찾을 수 있는 것은 아니다. 따라서 협력을 일관성 있게 만들기 위해 다음과 같은 기본 지침을 따르는 것이 도움이 될 것이다.
- 변하는 개념을 변하지 않는 개념으로부터 분리하라
- 변하는 개념을 캡슐화하라
사실 이 두 가지 지침은 훌륭한 구조를 설게하기 위해 따라야 하는 기본적인 원칙이기도 하다.
조건 로직 대 객체 탐색
조건에 따라 분기되는 어떤 로직들이 있다면 이 로직들이 바로 개별적인 변경이라고 볼 수 있다. 객체지향에서 변경을 다루는 전통적인 방법은 조건 로직을 객체 사이의 이동으로 바꾸는 것이다.
객체지향에서 변경을 다루는 전통적인 방법은 조건 로직을 객체 사이의 이동으로 바꾸는 것이다. 다형성은 바로 이런 조건 로직을 객체 사이의 이동으로 바꾸기 위해 객체지향이 제공하는 설계 기법이다.
조건 로직을 객체 사이의 이동으로 대체하기 위해서는 커다란 클래스를 더 작은 클래스들로 분리해야 한다. 중요한 기준은 변경의 이유와 주기다. 간단하게 말해서 단일 책임 원칙을 따르도록 클래스를 분리해야 한다. 간단하게 말해서 단일 책임 원칙을 따르도록 클래스를 분리해야 한다는 것이다.
따라서 협력을 일관성 있게 만들기 위해 따라야 하는 지침은 다음과 같다.
- 변하는 개념을 변하지 않는 개념으로부터 분리하라.
- 변하는 개념을 캡슐화하라
변경에 초점을 맞추고 캡슐화의 관점에서 설계를 바라보면 일관성 있는 협력 패턴을 얻을 수 있다.
캡슐화 다시 살펴보기
많은 사람들은 객체의 캡슐화에 관한 이야기를 들으면 반사적으로 데이터 은닉을 떠올린다. 그러나 캡슐화는 데이터 은닉 그 이상이다.
캡슐화란 변하는 어떤 것이든 감추는 것이다. 캡슐화의 가장 대표적인 예는 객체의 퍼블릭 인터페이스와 구현을 분리하는 것이다.
캡슐화란 단순히 데이터를 감추는 것이 아니다. 소프트웨어 안에서 변할 수 있는 어떤 '개념'이라도 감추는 것이다.
다양한 종류의 캡슐화
- 데이터 캡슐화 : 클래스는 내부에 관리하는 데이터를 캡슐화한다.
- 메서드 캡슐화 : 클래스의 외부에서는 이 메서드에 직접 접근할 수 없고 클래스 내부와 서브 클래스에서만 접근이 가능하다. 따라서 클래스 외부에 영향을 미치지 않고 메서드를 수정할 수 있다. 다시 말해 클래스의 내부 행동을 캡슐화하고 있는 것이다.
- 객체 캡슐화 : 객체와 객체 사이의 관계를 캡슐화한다. 눈치가 빠른 사람이라면 객체 캡슐화가 합성을 의미한다는 것을 눈치챘을 것이다.
- 서브타입 캡슐화 : 서브타입의 종류를 캡슐화하고 있는 것이다. 눈치가 빠른 사람이라면 서브타입 캡슐화가 다형성의 기반이 된다는 것을 알 수 있을 것이다.
코드 수정으로 인한 파급효과를 제어할 수 있는 모든 기법이 캡슐화의 일종이다. 일반적으로 데이터 캡슐화와 메서드 캡슐화는 개별 객체에 대한 변경을 관리하기 위해 사용하고 객체 캡슐화와 서브타입 캡슐화는 협력하는 협력에 참여하는 객체들의 관계에 대한 변경을 관리하기 위해 사용한다.
협력을 일관성 있게 만들기 위해 가장 일반적으로 사용하는 방법은 서브타입 캡슐화와 객체 캡슐화를 조합하는 것이다. 서브타입 캡슐화는 인터페이스 상속을 사용하고, 객체 캡슐화는 합성을 사용한다.
일관성 있는 기본 정책 구현하기
변경 분리하기
일관성 있는 협력을 만들기 위한 첫 번째는 변하는 개념과 변하지 않는 개념을 분리하는 것이다.
변경 캡슐화하기
협력을 일관성 있게 만들기 위해서는 변경을 캡슐화해서 파급효과를 줄여야 한다.
협력 패턴 설계하기
변하는 부분과 변하지 않는 부분을 분리하고, 변하는 부분을 적절히 추상화하고 나면 변하는 부분을 생략한 채 변하지 않는 부분만을 이용해 객체 사이의 협력을 이야기할 수 있다. 추상화만으로 구성한 협력은 추상화를 구체적인 사례로 대체함으로써 다양한 상황으로 확장할 수 있게 된다. 다시 말해서 재사용 가능한 협력 패턴이 선명하게 드러나는 것이다.
추상화 수준에서 협력 패턴 구현하기
변하는 것과 변하지 않는 것을 분리하고 변하는 것을 캡슐화한 코드는 오로지 변하지 않는 것과 추상화에 대한 의존성만으로도 전체적인 협력을 구현할 수 있다. 변하는 것은 추상화 뒤에 캡슐화되어 숨겨져 있기 때문에 전체적인 협력의 구조에 영향을 미치지 않는다.
구체적인 협력 구현하기
유사한 기능에 대해 유사한 협력 패턴을 적용하는 것은 객체지향 시스템에서 개념적 무결성(Conceptual Integrity)을 유지할 수 있는 가장 효과적인 방법이다. 개념적 무결성을 일관성과 동일한 뜻으로 간주해도 무방하다. 시스템이 일관성 있는 몇 개의 협력 패턴으로 구성된다면 시스템을 이해하고, 수정하고, 확장하는 데 필요한 노력과 시간을 아낄 수 있다. 따라서 협력을 설계하고 있다면 항상 기존의 협력 패턴을 따를 수는 없는지 고민하라.
패턴을 찾아라
일관성 있는 협력의 핵심은 변경을 분리하고 캡슐화하는 것이다. 변경을 캡슐화하는 방법이 협력에 참여하는 객체들의 역할과 책임을 결정하고 이렇게 결정된 협력이 코드의 구조를 결정한다.
'📖 > 오브젝트' 카테고리의 다른 글
[오브젝트] 부록 A 계약에 의한 설계 (0) | 2024.03.19 |
---|---|
[오브젝트] 15장 디자인 패턴과 프레임워크 (0) | 2024.03.19 |
[오브젝트] 13장 서브클래싱과 서브타이핑 (0) | 2024.03.11 |
[오브젝트] 12장 다형성 (1) | 2024.03.07 |
[오브젝트]11장 합성과 유연한 설계 (0) | 2024.03.04 |