개요
2장에서는 올바른 객체지향 개발에 대해서 알아보았고, 3장에서는 객체지향 설계의 핵심에 대해서 얘기하였다. 4장 부터는 객체지향 설계를 왜 해야하는지에 대한 관점에서부터 출발하여 객체지향 설계를 안했을 때의 단점을 하나 하나 살펴본다. 이번 4장에서는 데이터 중심의 관점으로 객체의 상태에 초점을 맞추는 데이터 중심의 설계를 살펴보면서 객체 지향적인 설계의 구조와의 차이점을 알아보고자 한다.
결론부터 말하자면, 데이터 중심의 관점은 객체의 상태에 초점을 맞추기 때문에 객체 자체를 독립된 데이터로 보고, 구현 자체가 객체의 상태에 종속되기 때문에 변경에 취약해진다.
설계의 품질을 판단하기 위한 척도
설계의 품질은 판단하기 위한 척도로 캡슐화, 응집도, 결합도를 이용하여 판단이 가능하다.
캡슐화
변경 가능성이 높은 부분을 객체 내부로 숨기는 추상화 기법이다. 변경 가능성이 높은 부분을 내부로 숨기게 되고, 클라이언트 입장에서는 내부가 어떻게 변하든 상관없이 동일한 퍼블릭 인터페이스를 사용할 수 있다.
교재에서는 상대적으로 변경가능성이 높은 부분을 구현, 안정적인 부분을 인터페이스라고 칭한다.
응집도
모듈에 포함된 내부 요소들이 연관돼 있는 정도를 나타낸다. 모듈 내의 요소들이 하나의 목적을 위해 긴밀하게 협력한다면, 그 모듈은 높은 응집도를 가지고 있다는 것으로 볼 수 있다. 만약, 하나의 변경으로 인해 모듈 전체가 함께 변경된다면 응집도가 높은 것이고, 모듈의 일부만 변경된다면 응집도가 낮은 것이다. 응집도가 높으면 높을수록 결국 하나의 책임만 가지고 있다는 것이기 때문에 잘 된 객체지향 설계라고 볼 수 있다.
결합도
의존성의 정도를 나타내며 다른 모듈에 대해 얼마나 많은 지식을 가지고 있는지를 나타내는 척도이다. 만약 한 모듈이 다른 모듈에 대해 너무 자세한 부분을 알고 있다면 하나의 모듈이 수정이 될 때 다른 모듈도 수정이 될 가능성이 높다. 이런 경우 결합도가 높다고 볼 수 있고, 결합도가 높을수록 모듈 자체가 하나의 책임만을 수행하고 있는 것이 아니기 때문에, 결합도가 낮아야 잘 된 객체지향 설계라고 볼 수 있다.
이제부터 우리가 살펴볼 데이터 중심의 설계는 3개의 문제점을 가지고 있다. 캡슐화 위반, 높은 결합도, 낮은 응집도를 모두 가지게 된다.
데이터 중심의 설계
먼저 교재에 있는 예시에서 데이터 클래스들을 조합해서 영화 예매 절차를 구현하는 클래스의 예매 메서드를 살펴보자.
public class ReservationAgency {
public Reservation reserve(Screening screening, Customer customer, int audienceCount) {
...
Money fee;
if (discountable) {
...
fee = movie.getFee().minus(discountedAmount).times(audienceCount);
} else {
fee = movie.getFee();
}
...
}
}
이 코드에는 위에서 얘기한 3가지 문제가 존재한다. 해당 클래스는 사람 한 명의 예매 요금을 계산하기 위해서 Money 타입의 fee를 지역변수로 선언하고, 내부에서 Movie 클래스의 getFee() 메서드를 호출한 결과를 fee에 저장하고 있다.
이로 인해 가장 먼저 캡슐화가 위반됨을 알 수 있다. 클래스를 설계하면서 상태를 숨기기 위해 Getter를 사용하여 필드를 숨긴 것 같지만 사실 movie.getFee()는 Movie에 속한 데이터 Fee에 public 처럼 결국 접근이 가능하다. 이러한 설계 방식을 추측에 의한 설계 전략이라고 부른다. 그리고 이는 캡슐화를 위반 한 것이다.
두 번째로, 높은 결합도 문제가 보인다. 예를 들어서, 요금을 계산하는 타입을 Money가 아닌 다른 걸로 변경을 해야하는 상황이 왔다고 가정하자. 이럴 경우에 조건문 내에 속한 많은 부분들이 수정이 되고, 심지어 나아가서는 Movie에 속한 fee의 타입도 변경이 되어야하는 상황이 발생한다. 이런 상황은 결국 높은 결합도를 가진 상황을 의미한다.
마지막으로, 해당 메서드는 요금 계산 방법이 일련의 이유로 변경이 된다거나 추가된다거나 제거된다거나 하는 경우에 계속에서 수정을 해주어야 한다는 위험성에 노출이 되어있다. 이는 낮은 응집도를 가진 상황을 의미한다.
데이터 중심의 설계의 문제점
위의 예시를 통해 우리는 데이터 중심의 설계가 낮은 응집도와 높은 결합도를 가지고 있는 것을 볼 수 있었다. 그리고 이는 단적으로 캡슐화의 원칙을 위배했기 때문에 벌어진 일이다. 데이터 중심의 설계는 위처럼 캡슐화 위반은 기본, 높은 결합도와 낮은 응집도가 덩달아서 따라오게 된다. 결국 데이터에 의존하고 있기 때문에 변경가능성에 취약한 구현이 변경되어 적절하지 않은 책임을 가지고 있게 된 것이다. 결국 객체는 자신이 어떤 데이터를 가지고 있는지를 내부에 캡슐화를 해서 숨기고 외부에서는 퍼블릭 인터페이스를 통해서만 상태에 접근 할 수 있어야 하는데, 이는 객체 스스로 자신의 데이터를 지켜야 한다는 것이고 이는 설계의 제 1원리인 캡슐화를 잘 해주어야 한다.
스스로 자신의 데이터를 책임지는 객체
객체에게 의미 있는 메서드란 즉, 퍼블릭 인터페이스는 객체 스스로가 무언가를 수행하기 위해 책임져야 하는 메서드를 의미한다. 위에서 봤듯이 상태를 private로 설정하더라도, 접근자(Getter)와 수정자(Setter)를 통해서 속성이 외부로 노출된다면 이는 캡슐화가 위반 된 것이다. 따라서, 객체를 설계 할 때에는 이 객체가 데이터에 대해 수행해야 하는 오퍼레이션은 무엇인지, 이 객체가 어떤 데이터를 포함해야 하는지에 대해서 동시에 생각해야 한다.
결론
데이터 중심의 설계의 문제점을 다시 정리해보자.
1. 데이터 중심의 설계는 객체의 행동보다는 상태에 초점을 맞춘다.
- 데이터 중심의 관점에서의 객체는 단순한 데이터의 집합체이다.
- 데이터를 먼저 결정하고 필요한 오퍼레이션을 나중에 결정하는 방식은 데이터에 관한 지식이 객체의 인터페이스에 고스란히 드러나게 한다.
2. 데이터 중심 설계는 객체를 고립시킨 채 오퍼레이션을 정의하도록 만든다.
- 객체지향 설계의 무게 중심은 항상 객체의 내부가 아니라 협력에 맞춰져있어야 한다. 하지만 데이터 중심의 설계는 외부가 아닌 내부를 향하게 된다.
이번 장에서는 데이터 중심의 설계를 왜 하면 안 좋은지에 대해서 배웠다. 실제로 현재의 나도 그렇고 대부분의 개발을 입문하는 사람들은 데이터 중심의 개발을 하는데에 익숙해져 있을 것이라고 생각한다. 하지만 결국 개발은 지속적인 유지보수를 통해서 좀 더 나은 애플리케이션을 만드는 작업이니, 변경에 취약한 데이터 중심의 설계를 피하도록 노력해야 할 것이다.
'도서 > 오브젝트' 카테고리의 다른 글
3. 역할, 책임, 협력 (0) | 2023.05.26 |
---|---|
2. 객체지향 프로그래밍 (0) | 2023.05.24 |
1. 객체, 설계 (0) | 2023.05.18 |