해결된 질문
작성
·
51
1
5-1. 객체 구현하기 (2:16)
질문: reserve 함수 구현 시 Movie가 아래 처럼 전달될 수 도 있다고 생각했습니다.
생각 1 (함수 인자로 Movie 전달):
public Reservation reserve (Movie movie...) { ... }
생각 2 (Movie Id를 전달 받고, 함수 내부에서 Movie 검색)
설계 관점에서 이러한 구현과 기존 구현은 어떻게 다르다고 이해할 수 있을까요?
감사합니다.
참조 (기존 구현된 코드):
public class Screening {
private Movie movie;
public Reservation reserve (Customer customer, int audienceCount) {
Money fee = movie.calculateFee(this).times(audienceCount);
return new Reservation(customer, this, audienceCount, fee);
}
}
답변 2
1
김태호님 안녕하세요.
좋은 질문 남겨 주셔서 감사합니다. 🙂
아래에 답변 드릴게요.
메서드 인자로 Movie 전달
메서드 인자로 Movie를 전달받는 경우에는 메서드를 호출하는 클라이언트쪽에서 Movie를 조회해서 전달해줘야 합니다.
만약 Screening 클래스 안에서 Movie를 인자로 전달받는 메서드가 많아진다면 Screening을 사용하는 클라이언트에서 맡아야 하는 책임이 늘어나겠죠.
Screening의 메서드를 호출하는 모든 클라이언트에 조회 로직을 추가해야하기 때문에 Screening 클래스의 사용성이 저하되게 됩니다.
Screening이 Movie와 빈번하게 협력해야 한다면 Screening이 Movie의 참조를 포함하도록 결합도를 높여서 Screening과 Movie 객체 그룹의 사용성을 높일 수 있을 겁니다.
반면에 Screening의 메서드에서 Movie에 메시지를 전송하는 경우가 빈번하지 않고 결합도를 낮추는게 사용성 관점에서 더 중요하다면 말씀하신 것처럼 Movie를 인자로 전달하는 방법을 선택할 수 있습니다.
이 경우에는 어떤 참조는 끊고 어떤 참조는 연결할 지에 대한 고민이 필요합니다.
메서드 인자로 id 전달
메서드 인자로 id를 전달하면 Screening에서 Movie를 조회해야 합니다.
이를 위해 Screening에 Movie를 조회하는 책임을 담당하는 객체를 의존성 주입하거나 서비스 로케이터 형태로 객체를 조회해야 합니다.
이 경우 Screening이 조회를 위한 객체에 불필요하게 의존하게 되어 결합도가 높아지고, 결과적으로 단위 테스트 작성이 어려워지게 됩니다.
따라서 가급적이면 도메인 로직을 처리하는 클래스에서 조회 로직을 분리하시는게 좋습니다.
예제의 경우처럼 Screening이 Movie를 꼭 참조로 연결할 필요는 없지만 응집도와 결합도 측면에서 트레이드오프를 하시는게 좋습니다.
답변이 되었는지 모르겠네요. 🙂
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다.
김태호님께서 제기하신 Movie와 Customer의 위치에 따른 설계 선택에 관한 고민은 객체지향 설계에서 자주 나오는 중요한 문제입니다. 객체 간의 관계를 어떻게 설정하느냐에 따라 시스템의 유연성과 응집도가 크게 달라질 수 있습니다. 이 문제를 이해하려면 두 가지 접근 방식의 차이에 대해 알아야 합니다.
장점:
reserve
함수 호출 시 필요한 Movie
객체를 외부에서 명시적으로 제공받기 때문에, Screening
클래스는 Movie
의 생성 또는 초기화 책임을 갖지 않게 됩니다.Movie
객체와의 결합도가 낮아져, 향후 Movie
의 변경이 Screening
에 미치는 영향을 줄일 수 있습니다.단점:
reserve
를 호출하는 측에서 항상 Movie
객체를 가져와야 하므로, 호출 측의 책임이 증가합니다.장점:
Screening
이 Movie
id를 관리하고 있다면, Movie
객체를 내부적으로 관리할 수 있어 호출자의 책임이 줄어듭니다.Movie
객체를 가져오므로 초기화 과정에서 불필요한 객체 로딩을 피할 수 있습니다.단점:
Screening
이 로직 내부에서 Movie
객체를 찾기 위한 추가적인 책임을 지게 됩니다. 이는 Screening
클래스의 응집도를 저하시킬 수 있습니다.Movie
를 찾는 과정에서 데이터베이스나 다른 서비스 호출이 필요할 수 있어 성능에 영향을 줄 수 있습니다.현재 구현에서는 Screening
클래스 내부에서 이미 Movie
객체를 필드로 가지고 있어, reserve
메서드 호출 시 Movie
객체를 별도로 전달할 필요가 없습니다. 이는 Screening
객체가 해당 상영이 어떤 영화에 대한 것인지 알기에 충분토록 설계되어 있다는 의미입니다. 이처럼 각 객체가 자신이 필요한 정보를 최대한 자율적으로 관리하면 응집도가 높아집니다.
최종적인 선택은 설계 목표 및 데이터 흐름에 따라 달라질 수 있습니다. 데이터의 소스가 다양화되거나 객체의 재사용성이 중요한 경우 첫 번째 방법이 더 적절할 수 있습니다.
관련된 주제를 다룬 유사한 질문을 참고하시면 이러한 객체 간의 관계와 책임 할당에 대한 더 깊은 이해를 얻을 수 있을 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드립니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
답변 감사합니다.
특히, 조회 로직이 도메인 로직을 처리하는 클래스 내부에 포함되어 있으면 단위 테스트 작성이 어려워진다는 부분은 항상 느끼면서도 설계 과정에서 놓치게 되네요.
감사합니다.