일관성 없는 코드의 문제점
1. 개념적으로 연관되어있는 코드에 대해 서로 다른 구현 방식을 채택할수록 설계의 일관성이 무너지게 됨
2. 코드를 이해하기 어려움: 한가지를 이해했다고 다른 한가지를 이해하는 것이 아님
결론은 유사한 기능을 서로 다른 방식으로 구현 해서는 안 된다는 것이다. 일관성 없는 설계와 마주한 개발자는 여러 가지 해결 방법 중에서 현재의 요구사항을 해결하기에 가장 적절한 방법을 찾아야 하는 부담을 안게 된다.
유사한 기능은 유사한 방식으로 구현해야 한다. 객체 지향에서 기능을 구현하는 유일한 방법은 객체 사이의 협력을 만드는 것 뿐이므로 유지보수 가능한 시스템을 구축하는 첫걸음은 협력을 일관성 있게 만드는 것이다.
설계에 일관성 부여하기
일관성 있는 설계를 만드는 데 가장 훌륭한 조언
1. 다양한 설계 경험을 익히라는 것 (직관력 습득)
2. 널리 알려진 디자인 패턴을 학습하고 변경이라는 문맥 안에서 디자인 패턴을 적용해 보라는 것
(경험 법칙을 모아놓은 일종의 템플릿)
디자인 패턴이 반복적으로 적용할 수 있는 설계 구조를 제공한다고 하더라도 모든 경우에 적합한 패턴을 찾을 수 있는 것은 아니다. 따라서 협력을 일관성 있게 만들기 위해 다음과 같은 기본 지침을 따르는 것이 도움이 될 것
- 변하는 개념을 변하지 않는 개념으로부터 분리하라
- 변하는 개념을 캡슐화하라
캡슐화 다시 살펴보기
많은 사람들이 캡슐화에 대해서 반사적으로 데이터 은닉(*외부에 공개된 메서드를 통해서만 객체의 내부에 접근할 수 있게 제한함으로써 객체 내부의 상태 구현을 숨기는 기법)을 떠올리지만, 캡슐화는 데이터 은닉 그 이상이다.
캡슐화란 변하는 어떤 것이든 감추는 것이다.
대표적인 예제: 객체의 퍼블릭 인터페이스와 구현을 분리하는 것
캡슐화란 단순히 데이터를 감추는 것이 아니라, 소프트웨어 안에서 변할 수 있는 어떤 '개념'이라도 감추는 것이다.
- 데이터 캡슐화 : Movie 클래스의 인스턴스 변수 title의 가시성은 private이기 때문에 외부에서 직접 접근할 수 없다. 이 속성에 접근할 수 있는 유일한 방법은 메서드를 이용하는 것뿐이다. 다시 말해 클래스는 내부에 관리하는 데이터를 캡슐화한다.
- 메서드 캡슐화 : DiscountPolicy 클래스에서 정의돼 있는 getDiscountAmount 메서드의 가시성은 protected다. 클래스의 외부에서는 이 메서드에 직접 접근할 수 없고 클래스 내부와 서브 클래스에서만 접근이 가능하다. 따라서 클래스 외부에 영향을 미치지 않고 메서드를 수정할 수 있다. 다시 말해 클래스의 내부 행동을 캡슐화하고 있는 것이다.
- 객체 캡슐화 : Movie 클래스는 DiscountPolicy 타입의 인스턴스 변수 discountPolicy를 포함한다. 이 인스턴스 변수는 private 가시성을 가지기 때문에 Movie와 DisvountPolicy 사이의 관계를 변경 하더라도 외부에는 영향을 미치지 않는다. 다시 말해서 객체와 객체 사이의 관계를 캡슐화한다. 눈치가 빠른 사람이라면 객체 캡슐화가 합성을 의미한다는 것을 눈치챘을 것이다.
- 서브타입 캡슐화 : Movie는 DiscountPolicy에 대해서는 알고 있지만 AmountDiscountPolicy와 PercentDiscountPolicy에 대해서는 알지 못한다. 그러나 실제로 실행 시점에는 이 클래스들의 인스턴스와 협력할 수 있다. 이것은 파생 클래스인 DiscountPolicy와의 추상적인 관계가 AmountDiscountPolicy와 PercentDiscountPolicy의 존재를 감추고 있기 때문이다. 다시 말해 서브타입의 종류를 캡슐화하고 있는 것이다. 눈치가 빠른 사람이라면 서브타입 캡슐화가 다형성의 기반이 된다는 것을 알 수 있을 것이다.
서브타입 캡슐화와 객체 캡슐화를 적용하는 방법
1. 변하는 부분을 분리해서 타입 계층을 만든다.2. 변하지 않는 부분의 일부로 타입 계층을 합성한다.
일관성 있는 기본 정책 구현하기
1. 변경 분리하기
변하는 개념과 변하지 않는 개념을 분리하기
2. 변경 캡슐화하기(파급효과 줄이기)
변하지 않는 부분(규칙)으로부터 변하는 부분(적용조건)을 분리하는 것.
즉, '적용조건'이라는 변경에대해 캡슐화
3. 협력 패턴 설계하기
변하는 부분을 생략한 채 변하지 ㅇ낳는 부분만을 이용해 객체 사이의 협력을 이야기 할 수 있음 (즉, 재사용 가능한 협력 패턴만 남음)
p500 그림 14.17
구체적인 협력 구현하기
유사한 기능에 대해 유사한 협력 패턴을 적용하는 것은 객체지향 시스템에서 개념적 무결성(Conceptual Integrity)-일관성을 유지할 수 있는 가장 효과적인 방법이다. 시스템이 일관성 있는 몇 개의 협력 패턴으로 구성된다면 시스템을 이해하고, 수정하고, 확장하는 데 필요한 노력과 시간을 아낄 수 있다. (시스템 설계에서 가장 중요함,,이라고 감히 얘기하심)
지속적으로 개선하라
협력은 고정된 것이 아니다. 만약 현재의 협력 패턴이 변경의 무게를 지탱하기 어렵다면 변경을 수용할 수 있는 협력 패턴을 향해 과감하게 리팩터링하라. 요구 사항의 변경에 따라 협력 역시 지속적으로 개선해야 한다. 중요한 것은 현재의 설계에 맹목적으로 일관성을 맞추는 것이 아니라 달라 지는 변경의 방향에 맞춰 지속적으로 코드를 개선하려는 의지다.
패턴을 찾아라
변경을 분리하고 캡슐화하는 것이 일관성 있는 협력의 핵심
협력을 일관성 있게 만든다는 것은 유사한 변경을 수용할 수 있는 협력 패턴을 발견하는 것과 동일=> 이와 관련된 두가지 개념: 패턴, 프레임워크
'개발 > Clean Code' 카테고리의 다른 글
[오브젝트] 10장. 상속과 코드 재사용 (0) | 2021.06.04 |
---|---|
[오브젝트] 9장 유연한 설계 (0) | 2021.06.03 |
[Clean Code] 15장. JUnit 들여다보기 (0) | 2021.03.08 |
[Clean Code] 10장. 클래스 (2) | 2021.01.03 |
[Clean Code] 5장. 형식맞추기 (0) | 2020.12.01 |
댓글