본문 바로가기
독서 기록

[오브젝트] 5장 - 책임 할당하기

by 워냥 2024. 3. 25.

내용 정리: 20240323 TIL, 20240324 TIL

1. 개요

5장에서는 책임 할당에 관한 다양한 기법들을 알아본다.
이전 장까지는 책임을 적절히 할당하는 것이 유연한 설계의 핵심임을 강조했다.
이제 그 책임을 어떻게 효과적으로 할당할 수 있는지 구체적인 방법들에 대해 알아볼 것이다.
 
책임 할당을 위한 가이드로 GRASP 패턴을 소개한다.
이 패턴들은 설계 과정에서 책임을 적절히 할당하는 데 도움을 줄 수 있는 가이드라인을 준다.


2. 책임 주도 설계

책임 주도 설계를 위해서는 설계 과정에서 데이터보다 객체의 행동에 초점을 맞춰야 한다.
객체가 수행해야 할 행동을 먼저 결정하고, 그 행동을 수행하는 데 필요한 데이터를 뒤이어 결정해야 한다.
 
객체가 수행해야 할 행동, 즉 책임은 협력에 적합해야 한다.
객체의 개별적인 입장이 아닌 객체가 참여하고 있는 전체 협력의 관점에서 책임을 고려해야 한다.
 
객체에 할당된 책임이 협력에 잘 맞지 않는다면 그 책임은 나쁜 것이다.
반면 협력에 적합한 책임은 좋은 책임이다.
 
협력을 중심으로 책임을 고려하면 캡슐화 원칙을 자연스럽게 지키게 된다.
 

도메인부터 시작하기

책임을 할당하는 과정에서 도메인 개념을 파악하는 것이 중요하다.
도메인의 관계를 명확히 한 후 책임 할당을 시작하면 보다 효율적으로 설계를 진행할 수 있다.
 
하지만 도메인 개념 정리에 과도한 시간을 투자하는 것은 피해야 한다.
도메인 모델은 단순한 이론적 개념뿐만 아닌 실제 구현도 포함하고 있다.
실제 코드 구현 과정에서 얻게 되는 인사이트가 도메인 모델을 변화시킬 수 있다.
 
빠르게 도메인 모델을 설계하고 구현을 시작하자.
구현 과정에서 얻은 깨달음을 바탕으로 도메인 모델을 지속적으로 조정하는 유연한 접근이 필요하다.


3. GRASP 패턴

GRASP 패턴(General Responsibility Assignment Software Pattern)은 책임 할당에 대한 지침을 제시한다.
각 패턴들은 객체들에게 책임을 적절히 분배하는 방법에 대한 내용을 담고 있다.
 

정보 전문가 패턴

정보 전문가(Information expert) 패턴은 책임을 가장 잘 수행할 수 있는 객체를 고를 때 도움을 준다.
이 패턴은 객체가 가지고 있는 정보를 기반으로 책임을 할당하라고 한다.
 
중요한 점은 정보를 안다는 것이 단순히 데이터를 저장한다는 것이 아니라는 것이다.
필요한 정보를 얻을 수 있는 다른 객체를 알고 있는 것 또한 정보를 알고 있다고 한다.
따라서 정보 전문가는 필요한 정보를 반드시 저장하고 있을 필요는 없다.
 

낮은 결합도 패턴과 높은 응집도 패턴

설계 과정에서 나올 수 있는 다양한 설계를 평가할 때 낮은 결합도와 높은 응집도를 기준으로 하자.
 
낮은 결합도(Low Coupling) 패턴은 객체 간의 의존성이 최소화되도록 책임을 할당한다.
기존에 결합되어 있는 객체들을 활용하여 새로운 결합도가 생기지 않도록 해야 한다.
 
높은 응집도(High Cohesion) 패턴은 하나의 객체가 단단히 연관된 책임들로 이뤄지도록 한다.
 
새로운 책임을 할당할 때마다 두 가지 패턴의 관점에서 전체적인 설계 품질을 검토해야 한다.
 

창조자 패턴

창조자(Creator) 패턴은 객체 생성 책임을 할당하는 방법에 대해 알려준다.
생성될 객체와 가장 많은 정보를 공유하거나, 가장 연관성이 높은 객체에게 생성 책임을 맡긴다.

창조자 패턴은 생성과 사용의 관계를 고려하여 책임을 배정한다.
이를 통해 결합도를 관리하는 동시에 설계의 일관성을 가질 수 있다.


4. 변경에 취약한 클래스 개선하기

개선이 필요한 패턴 두 가지

변경에 취약한 클래스에는 몇 가지 패턴이 존재한다.
 

1. 인스턴스 변수의 초기화 시점

클래스의 응집도를 판단하는 기준으로 인스턴스 변수가 언제 초기화되는지를 볼 수 있다.
응집도가 높은 클래스는 생성 시점에 모든 속성이 함께 초기화된다.
반면 늦은 응집도를 가진 클래스는 일부 속성만 초기화되고 나머지는 초기화되지 않은 채 남는다.

함께 초기화되는 속성들끼리 코드를 재구성하여 응집도를 높이자.
 

2. 메서드들이 인스턴스 변수를 사용하는 방식 살펴보기

클래스의 응집도는 메서드가 클래스의 인스턴스 변수를 어떻게 사용하는지에 따라 달라진다.
모든 메서드가 객체의 모든 인스턴스 변수를 활용한다면 그 클래스의 응집도는 높다.
메서드 별로 사용하는 인스턴스 변수가 나뉜다면 그 클래스의 응집도는 낮다.

속성과 메서드를 그룹으로 나누어 서로 관련 있는 것끼리 분리하자. 
 

다형성 패턴

다형성(Polymorphism) 패턴은 객체의 타입에 따라 변하는 로직이 있을 때 책임을 할당하는 방법을 제시한다.
조건문 대신 타입을 기반으로 한 로직 구현이 가능하기에 if-else 등의 조건 분ㄴ기보다 확장성을 높일 수 있다.
 
하나의 클래스가 여러 타입의 행동을 구현하고 있는 것처럼 보인다면, 클래스를 분리하고 다형성 패턴에 따라 책임을 분산시키자.
 

변경 보호 패턴

변경 보호(Protected Variations) 패턴은 불안정한 요소를 안정된 인터페이스 뒤로 캡슐화하여 보호하는 방법이다.
변경 가능성이 있는 부분이 확인되면 이를 인터페이스로 둘러싸 변경으로부터 시스템을 보호할 수 있다.
변경 보호 패턴을 사용하면 시스템은 변화에 유연하게 대응할 수 있게 된다.


5. 리팩터링

책임 주도 설계를 통해 설계의 완성도를 높이기 위해서는 적절한 책임과 객체를 선택해야 한다.
하지만 이는 숙련된 개발자들에게도 어려운 과제가 될 수 있다.

처음부터 완벽한 설계를 하기보다는 작동하는 코드를 먼저 만든 뒤 개선해 나가는 접근 방법이 더 현실적이고 효과적일 수 있다.
이러한 방식을 리팩터링(Refactoring)이라고 한다.

실행 가능한 코드부터 작성하자

우선 작동하는 코드를 목표로 구현을 시작해 보자.
이후 코드를 살펴보며 드러나는 책임들을 적절한 위치로 이동시키며 구조를 개선해 나가는 작업을 진행하면 된다.

책임 주도 설계에 익숙하지 않더라도 이러한 리팩토링 과정을 통해 유사한 결과를 달성할 수 있다.
캡슐화, 결합도, 응집도 등의 객체지향 원칙을 적용하려고 노력한다면 유연하고 깔끔한 코드를 얻을 수 있다.


6. 느낀 점

GRASP 패턴

이번 장에서는 GRASP 패턴을 포함한 여러 책임 할당 패턴을 살펴보았다.
이 패턴들은 구체적인 방법론이기보다는 좋은 코드 설계를 위한 지침 느낌이었다.
변경에 취약한 코드를 식별하고 개선할 수 있는 유용한 도구가 될 것 같다.

책임 주도 설계를 적용해 보며

그동안 책을 읽으며 책임 주도 설계의 중요성에 대해 배웠다.
하지만 실제로 지금 진행하고 있는 프로젝트에 이 원칙들을 적용하려고 하니 예상보다 어려움이 많았다.
아직 책임 주도 설계가 익숙하지 않아 내가 선택하는 설계 결정들이 올바른지 자주 의문을 가지게 되었다.

설계는 항상 완벽할 수 없기에 지속적인 리팩토링을 통해 개선해나가야 한다.
처음부터 완벽한 설계를 추구하기보다는 코드의 질을 판단할 수 있는 기준을 활용하며 개선해 나가는 연습을 해야겠다.

 

댓글