설계 품질과 트레이드오프
객체지향 설계의 핵심은 역할, 책임, 협력이다.
올바른 객체에게 올바른 책임을 할당하면서 낮은 결합도와 높은 응집도를 가진 구조를 창조해야 한다.
객체의 상태가 아니라 객체의 행동에 초점을 맞춘다.
객체의 책임에 초점을 맞추는 것이다.
데이터 중심의 설계
객체가 내부에 저장해야 하는 '데이터가 무엇인가'를 시작으로 한 설계
데이터에 집중한다.
무엇을 구현할 때 필요한 데이터는 무엇인가?
🤔
필요한 데이터를 먼저 생각하는 순간 결합도가 높아진다.
캡슐화
객체의 내부 구현을 외부로부터 감추는 것.
구현이란, 변경될 가능성이 높은 어떤 것.
인터페이스, 상대적으로 안정적인 부분.
단순화하는 추상화의 한 종류다.
유지보수성이 목표다.
불안정한 부분과 안정적인 부분을 분리해서 변경의 영향을 통제할 수 있다.
🤔
응집도와 결합도
응집도 : 모듈에 포함된 내부 요소들이 연관돼 있는 정도.
결합도 : 의존성의 정도.
좋은 설계란, 오늘의 기능을 수행하면서 내일의 변경을 수용할 수 있는 것.
높은 응집도와 낮은 결합도는 변경하기 쉽게 만든다.
하나의 요구사항을 변경하기 위해 오직 하나의 모듈만 수정해야 한다.
인터페이스에 대해 프로그래밍하라.
응집도와 결합도는 변경과 관련이 깊다.
🤔
캡슐화 위반
내부 구현이 퍼블릭 인터페이스에 그대로 노출되면 안 된다.
🤔
높은 결합도
하나의 변경이 모든 모듈의 변경으로 이어진다.
🤔
낮은 응집도
서로 다른 이유로 변경되는 코드가 하나의 모듈 안에 공존할 때 모듈의 응집도가 낮다고 한다.
어떤 코드를 수정한 후에 아무런 상관도 없던 코드에 문제가 발생한다.
하나의 요구사항 변경을 위해 여러 모듈을 수정해야 한다.
'단일 책임 원칙'의 '책임'은 변경과 관련된 더 큰 개념이다.
🤔
캡슐화를 지켜라
설계의 제 1원리.
객체는 스스로의 상태를 책임져야 한다.
의미 있는 메서드는 객체가 책임져야 하는 무언가를 수행하는 메서드다.
코드 중복은 악의 근원이다.
🤔
getter, setter가 수행하는 일은 의미 없는 일이다.
내부에 '무언가를 수행하는' 책임(로직)을 두면 캡슐화다.
스스로 자신의 데이터를 책임지는 객체
상태와 행동을 하나로 묶는 이유는 객체 스스로 자신의 상태를 처리할 수 있게 하기 위해서다.
이 객체가 어떤 데이터를 포함해야 하는가?
이 객체가 데이터에 대해 수행해야 하는 오퍼레이션은 무엇인가?
🤔
캡슐화를 위반
인스턴스 변수 정보를 인터페이스를 통해 외부에 노출하지 마라.
내부 구현의 변경이 외부로 퍼져나가는 파급 효과는 캡슐화를 위반하는 것.
캡슐화란 변할 수 있는 어떤 것이라도 감추는 것.
🤔
높은 결합도
유연한 설계를 창조하기 위해서는 캡슐화를 설계의 첫 번째 목표를 삼아야 한다.
🤔
낮은 응집도
하나의 변경을 수용하기 위해 코드의 여러 곳을 동시에 변경해햐 한다.
응집도가 낮은 이유는 캡슐화를 위반했기 때문이다.
🤔
데이터 중심 설계의 문제점
너무 이른 시기에 데이터에 관해 결정하도록 강요한다.
협력이라는 문맥을 고려하지 않고 객체를 고립시킨 채 오퍼레이션을 결정한다.
데이터에 관한 지식이 객체의 인터페이스에 고스란히 드러나게 된다.
코드는 변경에 취약해진다.
중요한 것은 객체가 다른 객체와 협력하는 방법이다.
🤔