글 검색

공개된 글의 제목과 본문을 검색합니다.

    닫기 Esc

    1. 책임 주도 설계를 향해#

    1.1. 데이터보다 행동을 먼저 결정하라#

    • 객체에게 중요한 것은 데이터가 아닌 외부에 제공하는 행동이다.
    • 객체는 협력에 참여하기 위해 존재하며 협력 안에서 수행하는 책임이 객체의 존재가치를 증명한다.
    • 데이터는 객체가 수행하는 데 필요한 재료를 제공할 뿐이므로 너무 이른 시기에 데이터에 초점을 맞추면 객체의 캡슐화가 약화된다.
    • “데이터를 처리하는 데 필요한 오퍼레이션은 무엇인가”, “이 책임을 수행하는 데 필요한 데이터는 무엇인가”를 먼저 결정해야 한다.
    • 객체지향 설계에서 가장 중요한 것은 적절한 객체에게 적절한 책임을 할당하는 능력이다.

    1.2. 협력이라는 문맥 안에서 책임을 결정하라#

    • 객체에게 할당된 책임의 품질은 협력에 적합한 정도로 결정된다.
      • 협력에 어울리지 않는다면 나쁜책임
      • 어색해도 협력에 어울린다면 그 책임은 좋은 책임이다.
    • 협력을 시작하는 주체는 메시지 전송자이기 때문에 협력에 적합한 책임이란 메시지 수신자가 아닌 메시지 전송자에게 적합한 책임을 의미한다.
      • 다시말해 메시지 전송 클라이언트의 의도에 적합한 책임을 할당해야 한다.
      • 객체가 메시지를 선택하는 게 아닌 메시지가 객체를 선택해야 한다.
    • 메시지가 클라이언트의 의도를 표현한다는 사실에 주목하자
      • 객체 결정 전 객체가 수신할 메시지를 먼저 결정한다는 점 역시 주목하자
      • 클라이언트는 단지 임의의 객체가 메시지를 수신할 것이라는 사실일믿고 의도를 표현할 메시지를 전송할 뿐이고 수신이 결정된 객체는 이를 처리할 책임을 할당 받는다.

    1.3. 책임 주도 설계#

    책임 주도 설계의 흐름을 다시 살펴보자.

    • 시스템이 사용자에게 제공해야 하는 기능인 시스템 책임을 파악한다.
    • 시스템 책임을 더 작은 책임으로 분할한다.
    • 분할된 책임을 수행할 수 있는 적절한 객체 또는 열학을 찾아 책임을 할당한다.
    • 객체가 책임을 수행하는 도중 가른 객체의 도움이 필요한 경우 이를 책임질 적절한 객체 또는 역할을 찾는다.
    • 해당 객체 또는 역할에게 책임을 할당함으로써 두 객체가 협력하게 한다.

    2. 책임 할당을 위한 GRASP 패턴#

    • GRASP = General Responsibility Assignment Software Pattern

    2.1. 도메인 개념에서 출발하기#

    • 도메인 안에는 무수히 많은 개념들이 존재하며 이 도메인 개념들을 책임 할당의 대상으로 사용하면 코드에 도메인의 모습을 투영하기 쉬워진다.
    • 설계를 시작하는 단계에서는 개님들의 의미와 관계가 정확하거나 완벽할 필요가 없다 단지 우리에게는 출발점이 필요할 뿐이다.
    • 이 단계에서는 책임을 할당받을 객체들의 종류와 관계에 대한 유용한 정보를 제공할 수 있다면 충분하다.

    2.2. 정보 전문가에게 책임을 할당하라#

    • 책임 주도 설계 방식의 첫 단계는 애플리케이션이 제공해야 하는 기능을 애플리케이션의 책임으로 생각하는 것이다.
      • 이 책임을 애플리케이션에 대해 전송된 메시지로 간주하고 이 메시지를 책임질 첫 번째 객체를 선택하는 것으로 설계를 시작한다.
    • 영화관 프로그램에서 사용자에게 제공해야 하는 기능은 영화를 예매하는 것이다.
      • 이를 책임으로 간주한다면 어플리케이션은 영화를 예매할 책임이 있다고 말할 수 있다.
    • 책임을 수행하는데 메시지를 결정해야 하고 메시지를 전송할 객체와 수신할 객체 모두 의도를 반영해 결정해야 한다.
    • 누가 메시지를 수신받을 것인가를 결정하기 위해선 객체가 상태와 행동을 통합한 캡슐화의 단위라는 사실에 집중해야한다.
      • 객체는 자율적인 존재여야 하고 책임과 수행을 위한 상태는 동일한 객체 안에 존재해야 한다.
      • 따라서 객체에게 책임을 할당하는 첫 번째 원칙은 책임을 수행할 정보를 알고 있는 객체에게 책임을 할당하는 것이다.
    • GRASP에서는 이를 INFORMATION EXPERT(정보 전문가) 패턴이라고 부른다.

    3. 책임 주도 설계의 대안#

    • 책임 주도 설계에 익숙해지기 위해선 부단한 노력과 시간이 필요하다.
      • 설계를 진행하는 동안 데이터가 아닌 책임 관점에서 사고하기 위한 충분한 경험과 학습이 필요하기 때문이다.
    • 책임과 객체 사이에서 방황할 때 돌파구를 찾기 위해 선택하는 방법은 최대한 빠르게 목적한 기능을 수행하는 코드를 작성하는 것이다.,
      • 무에서 책임과 협력을 고민하기 보다 일단 실행되는 코드를 작성 후 명확히 들어나는 책임을 올바른 위치로 이동시키는 것이다.
      • 주로 객체지향 설계에 대한 경험이 부족한 개발자들과 페어 프로그래밍을 할 때나 설계의 실마리가 풀리지 않을 때 이런 방법을 시용하는데 생각보다 훌륭한 설계를 얻게 되는 경우가 종종 있다.
    • 주의할 점은 코드를 수정한 후에 겉으로 드러나는 동작이 바뀌어서는 안 된다는 것
      • 캡슐화를 향상시키고, 응집도를 높이고, 결합도를 낮춰야 하지만 동작은 그대로 유지해야 한다.
      • 이해하기 쉽고 수정하기 쉬운 소프트웨어로 개선하기 위해 겉으로 보이는 동작은 바꾸지 않은 채 내부 구조를 변경하는 것을 리팩터링이라 함

    3.1. 메서드 응집도#

    • 데이터 중심으로 설계된 영화 예매 시스템에서 도메인 객체들은 단지 데이터의 집합일 뿐이며 모든 절차는 외부 클래스에 집중돼 있다.
    • 긴 메서드는 다양한 측면에서 유지보수에 부정적 영향을 미친다.
      • 어떤 일을 수행하는지 한눈에 파악하기 어렵기 때문에 코드를 전체적으로 이해하는 데 너무 많은 시간이 걸린다.
      • 하나의 메서드 안에서 너무 많은 작업을 처리하기 때문에 변경이 필요할 때 수정해야 할 부분을 찾기 어렵다.
      • 메서드 내부의 일부 로직만 수정하더라도 메서드의 나머지 부분에서 버그가 발생할 확률이 높다.
      • 로직의 일부만 재사용하는 것이 불가능하다.
      • 코드를 재사용하는 유일한 방법은 원하는 코드를 복사해서 붙여넣는 것뿐이므로 코드 중복을 초래하기 쉽다.
    • 한마디로 긴 메서드는 응집도가 낮아 이해하기 어렵고 재사용이 어려우며 변경하기도 어렵다.
    • 그리고 이런 메서드를 몬스터 메서드라고 부른다.
    • 응집도가 낮다면? 로직 이해를 위한 주석이 필요하게 된다.
      • 주석 대신 메서드를 작게 분해해서 각 메서드의 응집도를 높여라
    • 응집도 높은 메서드는 변경되는 이유가 단 하나여야 한다.
    • 작은 메서드들로 조합된 메서드는 마치 주석들을 나열한 것처럼 보이기 때문에 코드를 이해하기 쉬워진다.
    • 객체로 책임을 분리 시 가장 먼저 할 일은 메서드를 응집도 있는 수준으로 분해하는 것이다.
      • 작고, 명확하며 한 가지 일에 집중하는 응집도 높은 메서드는 변경 가능한 설계를 이끌어내는 기반이 된다.
    전체 글 둘러보기