Post

일관성 있는 협력

14. 일관성 있는 협력

객체는 협력을 위해 존재한다.

협력은 객체가 존재하는 이유와 문맥을 제공

객체지향 설계의 목표는 적절한 책임을 수행하는 객체들의 협력을 기반으로 결합도가 낮고 재사용 가능한 코드 구조를 창조하는 것

객체지향 패러다임의 장점은 설계를 재사용할 수 있다는 것

재사용을 위해서는 객체들의 협력 방식을 일관성 있게 만들어야 함

일관성은 설계에 드는 비용을 감소

일관성 있는 설계가 가져다 주는 더 큰 이익은 코드가 이해하기 쉬워진다는 것

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

일관성 있는 협력 패턴을 적용하면 코드가 이해하기 쉽고 직관적이며 유연해진다

14.1 핸드폰 과금 시스템 변경하기

핸드폰 과금을 예시로 듦

일관성을 고려하지 않고 방식마다 다르게 구현

14.2 설계에 일관성 부여하기

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

일관성 있는 설계를 위한 두 번째 조언은 널리 알려진 디자인 패턴을 학습하고 변경이라는 문맥 안에서 디자인 패턴을 적용해 보라는 것

협력을 일관성 있게 만들기 위한 기본 지침

  • 변하는 개념을 변하지 않는 개념으로부터 분리하라
  • 변하는 개념을 캡슐화하라

조건 로직 대 객체 탐색

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

클래스를 분리하기 위한 기준?? -> 변경의 이유와 주기

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

단일 책임 원칙을 따르도록 클래스를 분리해야 함

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

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

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

변경에 초점을 맞추고 캡슐화의 관점에서 설계를 바라보면 일관성 있는 협력 패턴을 얻을 수 있다.

캡슐화 다시 살펴보기

데이터 은닉이란 오직 외부에 공개된 메서드를 통해서만 객체의 내부에 접근할 수 있게 재현함으로써 객체 내부의 상태 구현을 숨기는 기법

그러나 캡슐화는 데이터 은닉 이상

캡슐화는 소프트웨어 안에서 변할 수 있는 모든 ‘개념’을 감추는 것

캡슐화란 변하는 어떤 것이든 감추는 것

다양한 종류의 캡슐화 존재

  • 데이터 캡슐화
  • 메서드 캡슐화
  • 객체 캡슐화
  • 서브타입 캡슐화

캡슐화란 단지 데이터 은닉을 의미하는 것이 아님

코드 수정으로 인한 파급효과를 제어할 수 있는 모든 기법이 캡슐화의 일종

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

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

변하는 부분을 분리해서 타입 계층을 만든다

변하지 않는 부분의 일부로 타입 계층을 합성

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

변경 분리하기

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

변경 캡슐화하기

협력을 일관성 있게 만들기 위해서는 변경을 캡슐화해서 파급효과를 줄여야 한다.

협력 패턴 설계하기

추상화만으로 구성한 협력은 추상화를 구체적인 사례로 대체함으로써 다양한 상황으로 확장할 수 있게 된다.

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

변하는 것과 변하지 않는 것을 분리하고 변하는 것을 캡슐화한 코드는 오로지 변하지 않는 것과 추상화에 대한 의존성만으로도 전체적인 협력을 구현할 수 있다. 변하는 것은 추상화 뒤에 캡슐화되어 숨겨져 있기 때문에 전체적인 협력의 구조에 영향을 미치지 않는다.

구체적인 협력 구현하기

변경을 캡슐화해서 협력을 일관성 있게 만들었을 때의 장점

변하는 부분을 변하지 않는 부분으로부터 분리했기 때문에 변하지 않는 부분 재사용 가능

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

-> 코드의 재사용성 향상 + 테스트해야하는 코드양 감소

기본 정책을 추가하기 위해 규칙을 지키는 것보다 어기는 것이 더 어렵다

일관성 있는 협력은 개발자에게 확장 포인트를 강제하기 때문에 정해진 구조를 우회하기 어렵게 만든다.

개발자는 코드의 형태로 주어진 제약 안에 머물러야 하지만 작은 문제에 집중할 수 있는 자유를 얻음

변하지 않는 모든 부분은 모든 기본 정책에서 공통적

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

유사한 기능에 대해 유사한 협력 패턴을 적용하는 것 -> 개념적 무결성(Conceptual Integrity)을 유지할 수 있는 가장 효과적인 방법

협력 패턴에 맞추기

가급적 기존의 협력 패턴에 맞추는 것이 가장 좋은 방법

설계를 약간 비트는 것이 조금은 이상한 구조를 낳더라도 전체적으로 일관성을 유지할 수 있는 설계를 선택하는 것이 현명하다.

지속적으로 개선하라

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

협력을 설계하는 초기 단계에서 모든 요구사항을 미리 예상할 수 없기 때문에 자연스러운 형상

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

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

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

패턴을 찾아라

일관성 있는 협력의 핵심은 변경을 분리하고 캡슐화하는 것

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

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

애플리케이션에서 유사한 기능에 대한 변경이 지속적으로 발생하고 있다면 변경을 캡슐화할 수 있는 적절한 추상화를 찾은 후, 이 추상화에 변하지 않는 공통적인 책임을 할당

현재의 구조가 변경을 캡슐화하기에 적합하지 않다면 코드를 수정하지 않고도 원하는 변경을 수용할 수 있도록 협력과 코드를 리팩터링

객체지향 설계는 객체의 행동과 그것을 지원하기 위한 구조를 계속 수정해 나가는 작업을 반복해 나가면서 다듬어짐

참조

  1. 오브젝트
This post is licensed under CC BY 4.0 by the author.