[Ch.4] 설계 품질과 트레이드 오프

신은지·2022년 11월 26일
0


오브젝트 : 코드로 이해하는 객체지향 설계 (조영호 저) 를 읽고 정리합니다.


품질 척도

유지보수성! 오늘의 기능을 수행하면서 내일의 변경을 수용할 수 있는지?

🌱 캡슐화

  • 목적은 변경의 영향 통제!
  • 객체 내부 구현을 외부로부터 감춰, 특정 변경의 파급 효과를 조절하게 하는 것.
    • 구현 : 변경될 가능성이 높은 부분
    • 인터페이스 : 상대적으로 안정적인 부분
  • 불안정한 구현이 아닌, 안정적인 인터페이스에 의존하게 관계를 조절할 때 객체지향이 구현될 수 있다.

🔨 응집도와 결합도

  • 응집도 (⬆️)
    • 내부 요소들이 연관되어 있는 정도
    • 객체 또는 클래스에 얼마나 관련 높은 책임을 할당했는가? 를 확인하는 척도
  • 결합도 (⬇️)
    • 다른 모듈에 대해 얼마나 많은 지식을 가지고 있는가. 즉 의존성의 정도
    • 객체 또는 클래스가 협력에 필요한 적절한 수준의 관계만을 유지하고 있는가? 를 확인하는 척도
  • 내 설계를 쉽게 변경할 수 없다면, 구성 요소들의 응집도가 너무 낮지 않은지, 결합도가 너무 높지 않은지를 점검해 볼 타이밍..! 😇

변경의 관점에서 응집도와 결합도를 살펴보자.

  • 응집도 : 변경이 발생할 때 모듈 내부에서 얼마나 많이 변경해야 하니?
  • 결합도 : 한 모듈이 변경되기 위해 다른 모듈을 얼마나 많이 변경해야 하니?

훌륭한 설계?

훌륭한 설계란 합리적인 비용 안에서 변경을 수용할 수 있는 구조를 만드는 것!

😊 책임 중심 설계

객체는 협력하는 공동체의 일원이라는 관점으로, 객체 행동에 초점을 맞춘다.

  • 설계는 변경에 유연하게 대응할 수 있는 시스템을 만든다는 목적을 가지고 진행된다.
    • 이 목적 아래서 모든 객체들은 서로에게 덜 영향받도록 최대한 자율적이어야 하며, 따라서 추상화되고 캡슐화된다.

😡 상태 중심 설계

상태 = 데이터. 객체를 독립된 데이터 덩어리로 바라보는 관점

캡슐화를 위반하고, 결합도가 높아지며, 응집도가 낮아져서 문제에요~

  • 객체에게 필요한 데이터가 무엇인가? 에 초점이 맞춰진다.
  • 구현에 관한 세부사항이 객체 인터페이스에 강하게 결합된다.
    • 따라서 변경에 유연하게 대응할 수 없다.
      • 상태를 변경하면 인터페이스가 변해야하고, 인터페이스에 의존하는 모든 객체들을 바꿔야하니까!

🤔 데이터 중심 설계가 갖는 문제점을 구체적으로 확인해보자!

  • 1️⃣ 캡슐화 위반
    • 문맥이 아닌, 내부 데이터에 초점을 맞췄기 때문에 언제 상태값이 사용될 지 알 수 없다.
      • 따라서 발생 가능한 상황들을 커버하기 위해 모든 상태에 대해 접근자 메서드와 수정자 메서드를 두어야 한다. (= 추측에 의한 설계 전략)
    • 객체 내부에 접근하기 위해 사용하는 접근자와 수정자가, 오히려 객체 내부에 어떤 값이 있다는 사실을 퍼블릭 인터페이스에 드러내게 된다!
      • 따라서 내부 구현을 퍼블릭 인터페이스에 노출하면서 자연스럽게 캡슐화를 위반하고, 변경에 약해진다.
  • 2️⃣ 높은 결합도
    • 전체 시스템을 하나의 거대한 의존성 덩어리로 만드는 지름길!
      • 캡슐화 위반 -> 내부 구현의 노출 -> 클라이언트가 구현에 강결합 -> 뭐 하나 바꾸려면 전부 바꿔야함
      • 여러 데이터 객체를 쓰는 제어 로직이 특정 객체에게 집중 -> 특정 객체에게 전체 로직이 강결합 -> 뭐 하나 바꾸려면 전부 바꿔야함22
  • 3️⃣ 낮은 응집도
    • 단일 책임 원칙(SRP)의 위반 : 클래스는 단 하나의 변경 이유만 가져야 한다.
      • 변경의 이유가 다른 코드들을 하나의 모듈에 뭉쳐둠 -> 변경과 아무 상관 없는 코드들이 변경에 영향을 받음
      • 다른 모듈에 위치해야 할 책임의 일부가 엉뚱한 곳에 위치 -> 하나의 요구사항 변경을 위해 여러 모듈 수정 필요

🥺 어떻게 고쳐쓸 순 없을까요?

  • 1️⃣ 캡슐화를 지키자!
    • 특정 객체의 변경 주체를 외부에서 내부로 이동시키자!
      • 객체가 스스로를 책임지게 만들기
        • 객체가 어떤 데이터를 포함해야 하는지 & 이 데이터에 대해 수행해야 하는 행동은 무엇인지 고려
        • = 객체 내부 상태를 저장하는 방식 & 저장된 상태에 대해 호출할 수 있는 오퍼레이션의 집합
    • 객체 구현도 내부로 이동시키자!
      • 내부 변경이 외부로 퍼져나가지 않게 만들기
        • 변할 수 있는 것은 어떤 것(속성이든, 뭐든 전부!)이라도 전부 감춰야 한다
  • 2️⃣ 결합도를 낮추자!
    • 변경의 여파가 퍼지지 않도록, 위의 캡슐화 원칙을 통해 결합도를 낮추기
  • 3️⃣ 응집도를 높이자!
    • 바꿀 때 하나만 바꿔도 되게, 위의 캡슐화 원칙을 통해 응집도를 높이기

😮 그거 완전.. 책임 중심 설계 아니에요?

맞아용!

  • 데이터 중심 설계가 유연하지 못한 이유는 캡슐화를 위반했기 때문!
    • 객체의 상태는 결국 구현의 일부
      • 잘 변하는 불안정한 요소에 초점을 맞추고 설계했으니 당연히 변경에 취약해진 것
    • 상태 처리 오퍼레이션을 나중에 추가하느라 내부 지식이 인터페이스에 노출된다
      • 협력 문맥을 놓쳤기에 객체가 고립될 수 밖에 없다
      • 협력이 구현에 종속되게 만들면 당연히 객체들은 변경에 휩쓸리게 된다.
  • 객체지향 설계는 항상 객체 외부를 위주로 이루어져야 한다.
    • 객체가 어떻게 다른 객체와 협력하는지가 중요하지, 내부 상태를 관리하는 방법은 전체 설계에서 그닥 중요한 일이 아니다!
profile
호그와트 장학생

0개의 댓글