선생님, 개발을 잘하고 싶어요.

[오브젝트] 챕터 5 - 책임 할당하기 본문

일상/책 리뷰

[오브젝트] 챕터 5 - 책임 할당하기

알고싶은 승민 2022. 3. 2. 11:40

책임 주도 설계... 설계에 대해서 별 생각을 안하고 있었는데 설계 관련된 책을 읽는게 나름의 인사이트를 주는 것 같습니다.

코드의 좋고 나쁨을 평가할 수 있는 스스로의 기준이 마련되어야 내가 좋은 코드를 짜고 좋은 개발자가 될 수 있겠지요.

이런 설계 책을 읽으면 나만의 기준을 잡아가는데 도움이 되는 듯 합니다.

 

(물론 아직 실제로 더 사용을 해봐야하겠지만요)

 

이 챕터에서 의문인 부분은, "변경의 이유가 하나 이상인 클래스를 조심하라"는 건데요. 흠... 변경의 이유가 여러개라도 그 변경의 파장이 하나의 클래스 범위 내에서만 일어난다면 높은 응집도는 아니더라도 낮은 결합도를 가지고 변경 범위가 클래스 하나 레벨로 좁은, 변경하기 쉬운 코드가 생기지 않을까요.

결국 변경의 이유가 하나 이상인 모듈을 조심하는 게 더 옳은 조언이 아닐까 생각하고 있습니다만... 잘 모르겠네요.


<aside> 💡 객체에 책임을 할당하는 기본 원리를 다룬다.

</aside>

  • 책임 할당 과정은 일종의 트레이드오프
    • 상황에 따라 다르다.
  • 다양한 관점에서 설계를 평가할 수 있어야함.
  • 책임 주도 설계를 향해
    • 데이터보다 행동을 먼저 결정하라
      • 객체에게 중요한 것 → 외부에 제공하는 행동
      • 클라이언트 관점에서 객체가 수행하는 행동 → 객체의 책임
      • 객체의 데이터에서 행동으로 무게 중심을 옮길 기법은?
      • 이 객체가 수행해야 하는 책임은? → 책임을 수행하는 데 필요한 데이터는?
    • 협력안에서 책임을 결정하라
      • 이 책임이 객체가 참여하는 협력에 적합한가? → 아직 감 못잡겠음
      • 협력에 적합한 책임 → 클라이언트 의도에 적합한 책임
      • 메시지를 결정한 후에 객체를 선택해야 한다.
      • “이런 메시지를 전송해야 하는데 누구한테 하지?” (이런 기능이 필요한데, 누구한테 시키지?)
        • 다분히 클라이언트 입장이다.
      • 클라이언트는 서버 코드에 대한 아무런 가정도 할 수 없다. (서버 코드가 완벽히 캡슐화 되는 것)
  • 책임 할당을 위한 GRAPS 패턴
    • 도메인 개념에서 출발하기
      • 도메인 개념을 책임 할당의 대상으로 사용하면 코드에 도메인의 모습을 투영하기 수월하다.
      • 완벽할 필요 없다. 중요한 것은 설계를 시작하는 것, 빠르게 설계와 구현을 진행하라
      • 올바른 도메인 모델은 없다. 구현하며 변경되는 게 자연스럽다.
      • 구현에 도움이 되는 모델이 필요하다.
    • 정보 전문가에게 책임을 할당하라
      • 클라이언트는 무엇을 원하나? (what)
      • 무슨 서버가 적합할까?
      • 정보 전문가 패턴 (Information Expert)
        • 객체의 책임과 필요한 상태는 동일한 객체가 들고 있어야한다.
        • 책임을 수행할 정보를 알고있는 객체에 책임 할당
          • 꼭 저장할 필요는 없다. “안다”는 것?
      • 책임을 수행하는 데 필요한 작업 구상 & 스스로 처리할 수 없는 작업 가리기
    • 높은 응집도와 낮은 결합도
      • 책임을 할당할 수 있는 다양한 대안이 있다면?
      • 응집도와 결합도 측면을 고려하여 더 나은 대안을 선택하자.
      • 낮은 결합도 (Low Coupling)
        • 협력이 추가될 때, 새로운 결합도가 추가되나?
      • 높은 응집도 (High Cohesion)
        • 협력이 추가될 때
        • 서로 다른 이유로 변경되는 책임을 짊어지게 되는가? (응집도가 낮아짐)
      <aside> 💡 책임을 할당하고 코드를 작성하는 매 순간 낮은 결합도, 높은 응집도의 관점에서 설계하라
    • </aside>
    • 창조자에게 객체 생성 책임을 할당하라
      • 어떤 객체에게 객체 생성 책임을 할당해야하나?
      <aside> 💡 실제 설계는 코드를 작성하며 이루어진다.</aside>
    • 협력과 책임이 동작하는지 확인하는 유일한 방법은 실행 뿐이다.
  • General Responsibility Assignment Software Pattern
  • 구현을 통한 검증
    • 변경의 이유가 하나 이상인 클래스 부터 설계를 개선하자.
      • 낮은 응집도를 유발한다
      • 변경에 취약하다. 다양한 이유로 하나의 클래스가 수정되어야함.
      • ? 정말 그러한가?
        • 하나의 클래스면 별 상관 없지않나?
        • 모듈 레벨에서 낮은 응집도를 가진다면 “하나의 기능을 변경하기 위해서 다양한 객체를 손 봐야하는 게 되는거 아닌가?” p.111-
    • 응집도가 높은 클래스는 인스턴스를 생성할 때 모든 속성을 함께 초기화한다.
    • 함께 초기화되는 속성을 기준으로 코드를 분리하자
    • 긴 메서드를 응집도 높은 작은 메서드로 잘게 분해해 나가면 숨겨져 있던 문제점이 명확하게 드러나는 경우가 많다.
    • 타입 분해하기, 타입 → 관련된 속성 그룹, 메서드 그룹
    • 특정 객체 입장에서 응집도가 높아지는 것이 항상 전체적 설계 품질 향상을 의미하는 건 아니다.
      • 변경과 캡슐화, 높은 응집도, 낮은 결합도 차원에서 항상 전체적 평가를 내릴 수 있어야한다.
    • 다형성 패턴 (Polymorphism)
      • 타입에 따라 변하는 행동 → 타입 분리 및 변하는 행동을 타입의 책임으로 할당
    • 변경 보호 (Protected Varaitions)
      • 변경을 캡슐화하도록 책임을 할당
      • 예측 가능한 변경은 인터페이스로 변경을 캡슐화하자
      <aside> 💡 도메인을 잘 알고, 설계에서 변경이 일어날 지점을 알아낼 수 있어야함.
    • </aside>
    • 변경과 유연성
      • 코드를 이해하고 수정학 쉽도록 최대한 단순하게 만들기 → 더 좋은 방법
      • 코드 수정하지 않고도 변경을 수용할 수 있도록 코드를 유연하게 만들기
      • 유연성은 의존성 관리의 문제다. 요소들 사이 의존성 정도가 유연성 정도를 결정한다.
    • 절차형 코드로 프로그램을 빠르게 작성하고 객체지향적인 코드로 변경하며 연습해 볼 수도 있다
  • 책임 주도 설계의 대안
    • 리팩터링
    • 동작은 그대로 유지하며 → 캡슐화 향상, 응집도 높이기, 결합도 낮추기
    • 이해하기 쉽고 수정하기 쉬운 소프트웨어로 개선하는 거
    • 몬스터 메서드를 응집도가 높은 메서드들로 뽑아내자.
    • 메서드의 목적을 알기 쉽게 만들자
    • 적절한 위치? → 각 메서드가 사용하는 데이터를 정의하고 있는 클래스

책임 주도 설계

  • responsibility-driven design tries to avoid dealing with details
    • by only specifying the intent of a certain request
  • 좋은 캡슐화를 얻을 수 있다.
  • 행동 추상화에 집중한다
  • 행위를 집중시키지 않는다는 점에서 분산 시스템과 같은 걸 구성할 때 도움되는 컨샙
Comments