4장 설계 품질과 트레이드오프
정리
상태 중심의 설계를 보면서 책임 주도 설계와의 차이를 캡슐화, 응집도, 결합도를 사용해 확인하며 통찰얻기.
데이터 중심의 설계는 객체가 포함해야 하는 데이터에 집중한다.
따라서 책임 중심 설계가 ‘책임이 무엇인가’를 묻는 것으로 시작한다면
데이터 중심 설계는 객체가 내부에 저장해야 하는 ‘데이터가 무엇인가’를 묻는 것으로 시작한다.
훌륭한 객체 지향 설계는 데이터가 아니라 책임에 초점을 맞춰야 한다.
상태를 객체 분할의 중심축으로 삼으면 구현에 대한 세부사항이 객체의 인터페이스에 스며들어 캡슐화의 원칙이 무너진다.
객체를 설계하기 위한 가장 기본적인 아이디어는 변경의 정도에 따라 구현과 인터페이스를 분리하고 외부에서는 인터페이스에만 의존하도록 관계를 조절하는 것.
- 구현: 변경될 가능성이 높은 부분
- 인터페이스: 상대적으로 안정적인 부분
캡슐화
캡슐화란 변경 가능성이 높은 부분을 객체 내부로 숨기는 추상화 기법.
변경될 수 있는 어떤 것이라도 캡슐화해야 함(데이터 뿐만이 아닌 모든 것)
- 설계가 필요한 이유? - 요구사항이 변경되기 때문.
- 캡슐화가 중요한 이유? - 불안정한 부분과 안정적인 부분을 분리해 변경의 영향을 통제할 수 있기 때문.
캡슐화의 정도가 응집도와 결합도에 영향을 미친다.
캡슐화를 지키면 모듈 안의 응집도는 높아지고 모듈 사이의 결합도는 낮아진다.
응집도
모듈에 포함된 내부 요소들이 연관돼 있는 정도.
객체지향 관점에서 응집도는 객체 또는 클래스에 얼마나 관련 높은 책임들을 할당했는지를 나타냄.
변경의 관점에서 모듈 내부에서 발생하는 변경의 정도.
결합도
의존성의 정도.
다른 모듈에 대해 얼마나 많은 지식을 갖고 있는지를 나타내는 척도.
객체지향의 관점에서 결합도는 객체 또는 클래스가 협력에 필요한 적절한 수준의 관계만을 유지하고 있는지를 나타냄.
ex)어떤 모듈이 다른 모듈에 대해 꼭 필요한 지식만 알고 있다면 두 모듈은 낮은 결합도를 가진다.
변경의 관점에서 한 모듈이 변경되기 위해 다른 모듈의 변경을 요구하는 정도.
데이터 중심의 설계는 캡슐화 위반으로 인한 높은 결합도와 낮은 응집도를 갖는 문제가 있다.
객체에게 중요한 것은 책임이고, 구현을 캡슐화할 수 있는 적절한 책임은 협력이라는 문맥을 고려할 때만 얻을 수 있다.
추측에 의한 설계 전략: 접근자와 수정자에 과도하게 의존하는 설계 방식[Holub04]
객체가 사용될 협력을 고려하지 않고 객체가 다양한 상황에서 사용될 수 있을 것이라는 막연한 추측을 기반으로 설계를 진행하는 것.
단일 책임의 원칙(SRP)
클래스는 단 한 가지의 변경 이유만 가져야 한다.[Martin02]
클래스의 응집도를 높일 수 있는 설계 원칙.
자율적인 객체를 향해 캡슐화를 강화
객체가 자기 스스로를 책임지도록 책임을 이동해야 한다.
- 이 객체가 어떤 데이터를 포함해야 하는가?
- 이 객체가 데이터에 대해 수행해야 하는 오퍼레이션은 무엇인가?
위 두 질문을 통해 새로운 데이터 타입을 만들 수 있다.
올바른 객체지향 설계의 무게 중심은 항상 객체의 내부가 아닌 외부에 맞춰져 있어야 한다.
중요한 것은 객체가 다른 객체와 협력하는 방법이지 객체가 내부에 어떤 상태를 가지고 그 상태를 어떻게 관리하는가는 부가적인 문제이다.
데이터 중심 설계는 객체의 구현이 이미 결정된 상태에서 다른 객체와의 협력 방법을 고민하기 때문에 이미 구현된 객체의 인터페이스를 억지로 끼워맞출 수밖에 없다.
읽고 난 후..
이번 장을 읽으면서 기존에 진행했떤 프로젝트가 떠올랐다.
이번 장에서 본 것처럼 이론 상에선 캡슐화를 위해 접근자, getter를 쓰는 것이 바람직하진 않지만 실제 프로젝트에선 데이터 접근 빈도수가 많기 때문에 효율성을 따졌을 때, getter를 쓰는 것이 더 낫다는 판단이었다. 이처럼 너무 이론에 치우치지말고 트레이드오프를 잘 따지면서 최대한 객체지향적으로 코드를 짜는 것이 좋겠다라고 생각을 하게 되었다.