설계 품질과 트레이드오프에 대한 내용이다.
자세한 내용이 궁금하면 오브젝트를 펼쳐보는 걸 추천드립니다.📖
객체지향 설계에서는 상태(데이터) 분할의 중심축과 책임 분할의 중심축 두 가지 방법으로 시스템을 객체로 분할할 수 있다.
상태 분할의 중심축은 절차지향 설계라 생각하면 되고, 책임 분할의 중심축은 객체지향 설계라 생각하면 된다.
좋은 설계의 기준으로 사용되는 캡슐화, 응집도, 결합도를 알아보자
캡슐화
객체의 내부 구현을 외부로부터 감추는 걸 캡슐화라 한다. 여기서 나중에 변경이 될 가능성이 높은 걸 구현이라 하며, 반대로 변경이 될 가능성이 낮아 상대적으로 안정한 부분을 인터페이스라고 부른다.
캡슐화는 객체지향에서 가장 중요한 원리이며, 추상화의 한 종류다.
복잡성을 다루기 위한 가장 효과적인 도구는 추상화다. 다양한 추상화 유형을 사용할 수 있지만 객체지향 프로그래밍에서 복잡성을 취급하는 주요한 추상화 방법은 캡슐화다.
설계가 필요한 이유는 요구사항 변경 때문이고, 캡슐화가 중요한 이유는 불안정한 부분과 안정한 부분을 분리하여 변경의 영향을 통제하기 때문이다.
한마디로 캡슐화란 변경 가능성이 높은 부분을 객체 내부로 숨기는 추상화 기법이다.
응집도와 결합도
응집도는 모듈에 포함된 내부 요소들이 연관돼 있는 정도를 뜻한다. 내부 요소들이 하나의 목적을 위해 협력한다면 높은 응집도를 갖는다고 말하며, 반대로 내부 요소들이 서로 다른 목적으로 사용되면 낮은 응집도를 갖는다.
변경의 관점에서 응집도란 변경이 생기면 모듈 내부의 변경의 정도로 바라보면 된다. 높은 응집도는 모듈 전체가 변경될 확률이 높고, 낮은 응집도는 모듈 일부분만 변경될 수 있다.
결합도는 다른 모듈에 얼마나 알고 있는지 의존성에 대한 척도를 나타낸다. 의존하는 객체에 많은 걸 알면 높은 결합도를 갖는다 하고, 기능 구현에 필요한 최소한의 지식을 가질수록 낮은 결합도를 갖는다.
변경의 관점에서 결합도란 한 모듈이 변경되기 위해 다른 모듈의 변경을 요구하는 정도로 측정할 수 있다. 한마디로 얼마나 많이 모듈을 함께 수정하는지 나타낸다.
결론으로 응집도 결합도는 변경에 관련된다. 변경에 쉬운 설계라면 높은 응집도에 낮은 결합도를 가진 것이고, 변경이 어려운 설계라면 낮은 응집도에 높은 결합도를 가진다고 생각하면 된다.
덧붙이자면 캡슐화와 관련이 깊다. 캡슐화를 지키면 모듈안의 응집도는 높아지고 결합도는 낮아진다.
* 단, 표준 라이브러리 모듈이나 프레임워크 경우 결합도에 대해 고민을 안 해도 된다. String, ArrayList 같은 건 변경될 일이 매우 낮기 때문이다.
데이터 중심의 문제점
데이터 중심은 데이터와 프로세스를 분리한다고 했다. 이는 캡슐화를 위반하여 낮은 응집도와 높은 결합도를 가질 확률이 높다.
캡슐화를 위반한 이유가 무엇일까?
객체의 책임이 아닌 객체의 데이터(상태)에 초점을 맞추기 때문이며, 과도한 getter, setter를 가질 수 있다.
결합도가 높은 이유는 무엇일까?
제어 객체와 여러 데이터 객체가 서로 결합되어 있기 때문이다. 이 중 데이터 객체 하나만 변경되면 제어 객체에 영향이 갈 수밖에 없다.
응집도 낮은 이유는 무엇일까?
결합도와 비슷하다. 변경이 생기면 수정할 곳이 하나 이상이 생기기 때문이다.
* 특정 객체의 내부 구현이 변경 되었을 시, 이를 사용하는 클라이언트도 수정해야 한다면 파급효과(ripple effect)라 한다. 이는 캡슐화가 부족하다는 증거다.
자율적인 객체를 향해
데이터 중심에서 생기는 문제들은 모두 캡슐화를 위반하여 생기는 문제이며, 캡슐화를 지켜야한다. 캡슐화는 설계의 1 원리다.
캡슐화란 변하는 어떤 것이든 감추는 것이다. 그것이 무엇이든 구현과 관련된 것이라면 말이다.
행동과 상태를 객체의 단위로 묶는 것은 객체 스스로 상태를 처리하기 위해서다. 객체는 데이터 중심처럼 단순히 데이터를 제공하는 게 아니고, 협력을 위해 책임을 수행하는 오퍼레이션이 더 중요하다.
데이터 중심 설계의 문제점
데이터 중심의 설계가 변경에 취약한 이유는 두 가지다.
1. 데이터 중심 설계는 객체의 행동보다는 상태에 초점
데이터 중심의 관점에서는 객체는 단순 데이터 덩어리일 뿐이다. 별도의 절차 객체에서 데이터 객체를 사용하기 위해 과도한 getter, setter를 남발하기 때문에 인스턴스 변수에 private를 선언해도 무의미하다. 캡슐화가 완전히 무너진다는 의미다.
2. 데이터 중심 설계는 객체를 고립시킨 채 오퍼레이션을 정의
올바른 객체지향 설계의 무게 중심은 다른 객체와 협력하는 책임에 대한 것이다. 하지만 데이터 중심의 관점에서는 다른 객체가 아닌, 즉 외부가 아닌 객체의 내부로 향한다. 협력이라는 문맥을 무시하고 객체 상태를 먼저 결정한다. 결론적으로 객체를 먼저 구현해놓고 협력에 억지로 끼워맞춘다.
'서적 > 오브젝트: 코드로 이해하는 객체지향 설계' 카테고리의 다른 글
오브젝트 06_ 메시지와 인터페이스 (0) | 2021.06.09 |
---|---|
오브젝트 05_ 책임 할당하기 (0) | 2021.06.09 |
오브젝트 03_ 역할, 책임, 협력 (0) | 2021.06.08 |
오브젝트 02_ 객체지향 프로그래밍 (0) | 2021.06.08 |
오브젝트 01_ 객체, 설계 (0) | 2021.06.07 |