인프런 커뮤니티 질문&답변

하하님의 프로필 이미지
하하

작성한 질문수

오브젝트 - 기초편

5-2. 메시지와 메서드의 분리

영화 예매 예제에서 결합도 문의드립니다.

해결된 질문

작성

·

82

·

수정됨

2

안녕하세요,

좋은 강의 감사합니다.

 

영화 예매 예제를 보면서 궁금한 점이 있어 질문 드립니다.

Screening 객체는 DiscountPolicy, DiscountCondition 내부에서도 참조되어 사용되는 것으로 보입니다.

 

  1. 다수의 객체가 Screening 객체를 참조하고 있기에, Screening 객체의 변경 시 변경의 파급 효과(Ripple effect)가 높아지는 상황으로 이해 됩니다. 즉, 결합도가 높은 상태로 보이는데 맞을까요?

 

  1. DiscountPolicy 객체가 비율 할인 정책과, 금액 할인 정책의 책임을 모두 수행할 경우(낮은 응집도)에는. 비록 Screening Movie 객체가 단일 DiscountPolicy 객체에 의존하고 있더라도 파급 효과가 높은 것으로 이해됩니다. 그렇다면 결합도를 정의하는 척도는 의존성의 개수가 아닌 Ripple effect의 가능성이라고 봐도 될까요? (= 결합도가 높으면 파급 효과의 가능성이 높아진다)

 

감사합니다.

답변 2

3

조영호님의 프로필 이미지
조영호
지식공유자

하하님 안녕하세요.

먼저 좋은 질문 남겨주셔서 감사합니다.

강의에서 설명드린 것처럼 결합도는 변경이될 때 함께 변경될 수 있는 가능성을 의미합니다.

그리고 의존성은 자주 변경되는 요소에서 상대적으로 덜 자주 변경되는 요소쪽으로 향하도록 구성해야 합니다.

예제에는 Screening에 비해 DiscountCondition들이 더 자주 변경된다고 전제하고 있다는 사실을 기반으로 설명을 진행하도록 하겠습니다. 🙂

  • 1번 질문 답변

결론부터 말씀드린 다면 잠재적으로 많은 코드들이 Screening을 참조하고 있고 Screening이 변경될 경우 영향을 받는 코드가 많아질 수 있기 때문에 맥락을 고려하지 않고 순순하게 코드만 본다면 결합도가 높다고 할 수 있습니다.

다만 코드에서의 의존성은 징후를 나타낼 뿐 실제로 중요한 것은 얼마나 자주, 그리고 어떤 부분에서 변경이 발생하는 지 살펴보는 것입니다.

실제로 Screening이 자주 변경되고 이에 따라 의존하는 코드들이 함께 변경된다면 결합도가 높다고 할 수 있고, Screening이 자주 변경되지 않는다면 결합도가 낮다고 할 수 있습니다.

코드를 자세히 보시면 대부분은 Screening의 클래스 이름에 의존하고 있다는 사실을 알 수 있을 거에요.

SequenceCondition과 PeriodCondition에서 참조하는 메서드들은 단순한 getter가 아니라 협력을 하면서 실제로 필요하다고 판단된 메시지에 기반하고 있습니다.

결론적으로 Screening이 안정적이고 클래스의 명칭이 변경될 확률이 높지 않다면 결합도는 예상보다 낮다고 말할 수 있습니다

그렇더라도 결합도를 낮추도록 현재의 코드를 개선하는 것은 항상 바람직한 일입니다.

다만 코드가 불필요하게 복잡하지 않도록 개선 전과 후를 트레이드오프 하시는게 좋겠습니다.

코드 사이즈가 크지 않고 앞으로 어떤 부분에서 변경이 발생할지 예상하기 어렵다면 현재의 코드를 유지하고 실제로 변경이 발생할 때까지 기다리는게 좋습니다(현재 코드는 이런 가정에 기반하고 복잡성을 추가하지 않았습니다).

  • 2번 질문 답변

예제에서는 Movie가 DiscountPolicy에 의존하고 있기 때문에 Movie가 DiscountPolicy에 의존하고 있다고 가정하겠습니다. 이 경우 다음 처럼 DiscountPolicy 안에서 if/switch 등의 분기문을 이용해서 타입 기반으로 어떤 할인 정책을 이용할 지 결정하도록 코드를 구현할 수 있습니다.

class DiscountPolicy {
  DiscountPolicyType type;

  public Money calculateDiscountAmount() {
    switch(type) {
      case AMOUNT_POLICY: ...
      case PERCENT_POLICY: ...
    }
  }	
}

이 경우 Movie는 DiscountPolicy의 calculateDiscountAmount 메시지에만 의존하고 있습니다.

따라서 이 메시지가 변하지 않는다면 DiscountPolicy의 변경에 Movie가 영향을 받지 않기 때문에 결합도 측면에서는 그렇게 큰 차이가 발생하지는 않습니다(다만 DiscountPolicy가 구체 클래스라면 DiscountPolicy를 수정할 일이 더 많아질 수 있고 그 결과 Movie가 영향을 받을 확률이 높아지기 때문에 이 문제가 발생한다면 결합도를 낮추는게 좋겠죠).

여기에서 결합도를 낮추게 만드는 동기는 결합도 자차게 아니라 DisocuntPolicy의 응집도를 높이려는 시도입니다.

DiscountPolicy의 내부 응집도는 낮기 때문에 응집도를 높이는 쪽으로 설계를 개선해야 하고 결과적으로 DiscountPolicy를 추상 클래스나 인터페이스로 구현하게 되기 때문에 자연스럽게 Movie와 DiscountPolicy 사이의 결합도는 낮아지게 됩니다.

질문에서 "의존성의 개수가 아닌 Ripple effect의 가능성"이라고 말씀해 주셨는데 이 경우 아래와 같은 코드를 생각하신 걸까요?

 

class DiscountPolicy {
    DiscountPolicyType type;

    public Money calculateDiscountAmountWithAmountPlicy() {
      // 금액 할인 정책에 따라 계산
    }
	
    public Money calculateDiscountAmountWithPercentPlicy() {
       // 비율 할인 정책에 따라 계산
    }	
}

위 코드는 앞의 코드와 달리 결합도가 높은데 DiscountPolicy의 종류가 변경될 때마다(현재 예제에서는 실제 이런 변경이 자주 발생한다고 가정하고 있습니다) Movie도 영향을 받기 때문에 결합도가 높습니다.

결과적으로 의존성의 개수가 많으면 변경으로 인해 영향을 받을 확률도 높아지게 되기 때문에 두 가지는 밀접한 관련이 있습니다.

GRASP의 LOW COUPLING 패턴을 다시 보시면 결합도를 낮추기 위해 객체 사이의 의존성 개수를 줄이는데 초점을 맞추고 있다는 사실을 알 수 잇습니다.

대답이 되었는지 모르겠네요. 🙂

하하님의 프로필 이미지
하하
질문자

빠르고 자세한 답변 매우 감사드립니다!

이해에 많은 도움이 되었습니다.

 

1번 질문은, '변경의 안정성'의 요인을 간과하고 개수에만 초점을 맞췄던 것 같습니다.

답변 주신 내용을 통해 '안정적인 부분에만 의존하도록 의존성이 제어되었는가' 여부를 같이 따져봐야 하는 점 잘 리마인드 하였습니다.

 

2번 질문은, 코드 없이 너무 추상적으로 질문을 드렸던 것 같아 죄송합니다. 후자를 가정하고 질문 드린 것이 맞습니다.

질문 당시에는 의존성의 개수를 '객체'로 한정하여 생각하였습니다. 하지만 실제로는 'Movie 클래스 이름 + 2개의 구현 메서드 = 총 3개의 의존성'을 가진 상태라는 점으로 다시 이해하였습니다.

심지어 자주 변경될 수 있는 구현 메서드에 의존하고 있기에 결합도가 높은 상태라는 점도 이해하였습니다.

추가적으로, Movie -> DiscountPolicy 의존 관계를 말씀 드린 것이 맞습니다. 내용을 잘못 말했음에도 잘 이해해 주셔서 감사합니다ㅠ

문의글의 내용도 수정해 두도록 하겠습니다.

조영호님의 프로필 이미지
조영호
지식공유자

아이고 죄송하실 필요 없습니다.

설계가 워낙 다양한 해답이 있는 분야다보니 궁금한 부분을 명확하게 전달하기가 쉽지 않은 것 같아요.

저도 설계 관점에서 질문하거나 답변할 때 어려움을 느끼고는 합니다.

하하님께서 질문하신 의도가 정확하게 전달되었고 답변 역시 하하님의 의도에 적합하다면 원활히 소통됐다고 생각합니다.

다시 한번 좋은 질문 주셔서 감사드리고 궁금한 내용 있으면 편하게 남겨주세요.

감사합니다 하하님 🙂

0

안녕하세요, 인프런 AI 인턴입니다.

하하님께서 제기하신 영화 예매 예제의 결합도에 관한 질문은 객체지향 설계에서 매우 중요한 주제입니다. 결합도는 하나의 객체가 다른 객체에 얼마나 강하게 의존하고 있는지를 나타내며 이는 시스템의 유연성과 유지보수성에 직접적인 영향을 미칩니다.

  1. Screening 객체의 의존성: 여러 객체에서 Screening을 참조하고 있다면 실제로 Screening의 변경이 시스템 전반에 파급 효과를 미치게 될 가능성이 커질 수 있습니다. 이는 결합도가 높아진다는 것을 의미하며, 한 객체에서 다른 객체로의 영향력이 크다는 뜻이 됩니다. 결합도를 낮추기 위해선 인터페이스를 통해 간접적으로 의존성을 관리하거나, 의존성 주입(DI) 방식을 이용하여 참조를 최소화하는 방법이 있습니다.

  2. 결합도와 파급 효과: 결합도를 단순히 의존성의 개수로 측정하기보다는, 변경 시의 파급 효과로 이해하는 것이 더 적절할 수 있습니다. 즉, 결합도가 높은 상태라면 객체 간의 변경이 쉬운 일이 아니며, 하나의 객체 변화가 관련된 다른 객체들에게도 변경을 요구할 가능성이 크기 때문입니다. 높은 결합도는 일반적으로 시스템의 취약점을 늘리고, 유지보수하는 데 더 많은 노력을 필요로 합니다.

이에 관련된 내용을 다룬 기존의 질문과 답변에서, 응집도의 변경 측면에서 결합도에 대한 풍부한 설명을 찾을 수 있습니다. 응집도와 결합도는 서로 밀접하게 관련되어 있으며, 낮은 응집도는 고결합도를 초래할 수 있기 때문에 신중한 설계가 요구됩니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해 드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

하하님의 프로필 이미지
하하

작성한 질문수

질문하기