본문 바로가기

기술서적 정리/오브젝트 - 코드로 이해하는 객체지향 설계

14 CHAPTER 일관성 있는 협력

https://wikibook.co.kr/object/

 

오브젝트: 코드로 이해하는 객체지향 설계

역할, 책임, 협력을 향해 객체지향적으로 프로그래밍하라! 객체지향으로 향하는 첫걸음은 클래스가 아니라 객체를 바라보는 것에서부터 시작한다. 객체지향으로 향하는 두 번째 걸음은 객체를

wikibook.co.kr

 

 

가능하면 유사한 기능을 구현하기 위해 유사한 협력 패턴을 사용하라.

지금 보고 있는 코드가 얼마 전에 봤던 코드와 유사하다는 사실을 아는 순간 새로운 코드가 직관적인 모습으로 다가오는 것을 느끼게 될 것이다.

 

일관성 있는 협력 패턴을 적용하면 여러분의 코드가 이해하기 쉽고 직관적이며 유연해진다는 것이 이번 장의 주제이다.

 

 

◈ 구간별 방식 구현하기.

개념적으로는 연관돼 있지만 구현 방식에 있어서 완전히 제각각인 구현은 설계에 일관성이 없다는 문제점이 있다.

 

비일관성은 두 가지 상황에서 발목을 잡는다.

1. 새로운 구현을 추가해야 하는 상황.

2. 기존 구현을 이해해야 하는 상황.

 

대부분의 사람들은 유사한 요구사항을 구현하는 코드는 유사한 방식으로 구현될 것이라고 예상한다.

하지만 유사한 요구사항이 서로 다른 방식으로 구현돼 있다면 요구사항이 유사하다는 사실 자체도 의심하게 될 것이다.

이 코드가 정말 유사한 요구사항을 구현한 것이라면 왜 이렇게 다른 방식으로 구현한 것일까?

유사한 요구사항을 구현하는 서로 다른 구조의 코드는 코드를 이해하는 데 심리적인 장벽을 만든다.

 

결론은 유사한 기능을 서로 다른 방식으로 구현해서는 안 된다는 것이다.

 

객체지향에서 기능을 구현하는 유일한 방법은 객체 사이의 협력을 만드는 것뿐이므로 유지보수 가능한 시스템을 구축하는 첫걸음은 협력을 일관성 있게 만드는 것이다.

 

 

 

 

◈ 설계에 일관성 부여하기.

일관성 있는 설계를 만드는 데 가장 훌륭한 조언은 다양한 설계 경험을 익히라는 것이다.

풍부한 설계 경험을 가진 사람은 어떤 변경이 중요한지, 그리고 그 변경을 어떻게 다뤄야 하는지에 대한 통찰력을 가지게 된다.

 

널리 알려진 디자인 패턴을 학습하고 변경이라는 문맥 안에서 디자인 패턴을 적용해 보아라.

디자인 패턴을 학습하면 빠른 시간 안에 전문가의 경험을 흡수할 수 있다.

 

협력을 일관성 있게 만들기 위해 다음과 같은 기본 지침을 따르는 것이 도움이 된다.

1. 변하는 개념을 변하지 않는 개념으로부터 분리하라.

2. 변하는 개념을 캡슐화하라.

 


조건 로직 vs 객체 탐색

절차지향 프로그램에서 변경을 처리하는 전통적인 방법은 조건문의 분기를 추가하거나 개별 분기 로직을 수정하는 것이다.

 

객체지향에서 변경을 다루는 전통적인 방법은 조건 로직을 객체 사이의 이동으로 바꾸는 것이다.

 

객체지향적인 코드조건을 판단하지 않는다.

단지 다음 객체로 이동할 뿐이다.

 

조건 로직을 객체 사이의 이동으로 대체하기 위해서는 커다란 클래스를 더 작은 클래스들로 분리해야 한다.

클래스를 분리하기 위해 어떤 기준을 따르는 것이 좋을까?

클래스는 명확히 단 하나의 여유에 의해서만 변경돼야 하고 클래스 안의 모든 코드는 함께 변경돼야 한다.

간단하게 말해서 단일 책임 원칙을 따르도록 클래스를 분리해야 한다.

 

큰 메서드 안에 뭉쳐있던 조건 로직들을 변경의 압력에 맞춰 작은 클래스들로 분리하고 나면 인스턴스들 사이의 협력 패턴에 일관성을 부여하기가 더 쉬워진다.

유사한 행동을 수행하는 작은 클래스들이 자연스럽게 역할이라는 추상화로 묶이게 되고 역할 사이에서 이뤄지는 협력 방식이 전체 설계의 일관성을 유지할 수 있게 이끌어주기 때문이다.

 

핵심은 훌륭한 추상화를 찾아 추상화에 의존하도록 만드는 것이다.

추상화에 대한 의존은 결합도를 낮추고 결과적으로 대체 가능한 역할로 구성된 협력을 설계할 수 있게 해준다.

 


캡슐화 다시 살펴보기.

GOF의 조언에 따르면 캡슐화란 단순히 데이터를 감추는 것이 아니다.

소프트웨어 안에서 변할 수 있는 모든 ‘개념’을 감추는 것이다.

 

객체와 협력하는 클라이언트의 개발자는 객체의 인터페이스가 변하지 않기를 원한다.

따라서 자주 변경되는 내부 구현을 안정적인 퍼블릭 인터페이스 뒤로 숨겨야 한다.

 

협력을 일관성 있게 만들기 위해 가장 일반적으로 사용하는 방법은 서브타입 캡슐화와 객체 캡슐화를 조합하는 것이다.

서브타입 캡슐화는 인터페이스 상속을 사용하고, 객체 캡슐화는 합성을 사용한다.

 

 



◈ 일관성 있는 기본 정책 구현하기.

일관성 있는 협력을 만들기 위한 첫 번째 단계는 변하는 개념과 변하지 않는 개념을 분리하는 것이다.



협력 패턴 설계하기.

변하는 부분과 변하지 않는 부분을 분리하고, 변하는 부분을 적절히 추상화하고 나면 변하는 부분을 생략한 채 변하지 않는 부분만을 이용해 객체 사이의 협력을 이야기할 수 있다.

 


추상화 수준에서 협력 패턴 구현하기.

변하는 것과 변하지 않는 것을 분리하고 변하는 것을 캡슐화한 코드는 오로지 변하지 않는 것과 추상화에 대한 의존성만으로도 전체적인 협력을 구현할 수 있다.

변하는 것은 추상화 뒤에 캡슐화되어 숨겨져 있기 때문에 전체적인 협력의 구조에 영향을 미치지 않는다.



구체적인 협력 구현하기.

변경을 캡슐화해서 협력을 일관성 있게 만들면 얻을 수 있는 장점.

1. 변하는 부분을 변하지 않는 부분으로부터 분리했기 때문에 변하지 않는 부분을 재사용할 수 있다.

2. 새로운 기능을 추가하기 위해 오직 변하는 부분만 구현하면 되기 때문에 원하는 기능을 쉽게 완성할 수 있다.

3. 코드의 재사용성이 향상되고 테스트해야 하는 코드의 양이 감소한다.

4. 기능을 추가할 때 따라야하는 구조를 강제할 수 있기 때문에 기능을 추가하거나 변경할 때도 설계의 일관성이 무너지지 않는다.

 

협력을 일관성 있게 만들면 공통 코드의 구조와 협력 패턴은 모든 기본 정책에 걸쳐 동일하기 때문에 코드를 한 번 이해하면 이 지식을 다른 코드를 이해하는 데 그대로 적용할 수 있다.

 


지속적으로 개선하라.

처음에는 일관성을 유지하는 것처럼 보이던 협력 패턴이 시간이 흐르면서 새로운 요구사항이 추가되는 과정에서 일관성의 벽에 조금씩 금이 가는 경우를 자주 보게 된다.

 

협력은 고정된 것이 아니다.

만약 현재의 협력 패턴이 변경의 무게를 지탱하기 어렵다면 변경을 수용할 수 있는 협력 패턴을 향해 과감하게 리팩터링하라.

요구사항의 변경에 따라 협력 역시 지속적으로 개선해야 한다.

중요한 것은 현재의 설계에 맹목적으로 일관성을 맞추는 것이 아니라 달라지는 변경의 방향에 맞춰 지속적으로 코드를 개선하려는 의지다.

 


패턴을 찾아라.

변경을 캡슐화하는 방법이 협력에 참여하는 객체들의 역할과 책임을 결정하고 이렇게 결정된 협력이 코드의 구조를 결정한다.

따라서 훌륭한 설계자가 되는 첫걸음은 변경의 방향을 파악할 수 있는 날카로운 감각을 기르는 것이다.

그리고 이 변경에 탄력적으로 대응할 수 있는 다양한 캡슐화 방법과 설계 방법을 익히는 것 역시 중요하다.

 

협력을 일관성 있게 만드는 과정은 유사한 기능을 구현하기 위해 반복적으로 적용할 수 있는 협력의 구조를 찾아가는 기나긴 여정이다.

따라서 협력을 일관성 있게 만드는 것은 유사한 변경을 수용할 수 있는 협력 패턴을 발견하는 것과 동일하다.