JAVA

설계 품질과 트레이드오프 | 책임 할당하기 | 메시지와 인터페이스

잔망루피 2024. 8. 25. 16:37

 

조영호의 '오브젝트'를 읽고 알게 된 내용을 정리한다 😊

4장. 설계 품질과 트레이드오프

🌈 TIL

  • 객체지향설계는 올바른 객체에게 올바른 책임을 할당하는 것이다. 이를 통해 낮은 결합도와 높은 응집도를 가진 구조를 만들 수 있다.
  • 응집도는 모듈에 포함된 내부 요소들이 연관되어있는 정도다.
  • 결합도는 의존성의 정도다.
  • 캡슐화를 지키면 응집도는 높아지며 결합도는 낮아진다.
  • 데이터 중심의 설계 캡슐화 위반, 높은 결합도, 낮은 응집도의 문제가 있을 가능성이 높다.
  • 접근자 수정자 메서드를 사용하는 게 캡슐화를 한다고 생각했는데 아니라는 것을 알았다. 속성의 가시성을 private로 설정했다고 해도 접근자 수정자를 통해 속성을 외부로 제공하면 캡슐화를 위반한 것이다.
  • 추측에 의한 설계전략(design-by-guessing strategy) 접근자 수정자에 과도하게 의존하는 설계다.

 

5장. 책임 할당하기

🌈 TIL

  • 메시지를 전송하는 쪽의 의도에 맞게 책임을 할당해야 한다.
  • GRASP General Responsibility Assignment Software Pattern이다. 객체에게 책임을 할당할 때 지침으로 삼을 수 있는 원칙들의 집합을 패턴으로 정리한 것이다.
  • INFORMATION EXPERT 정보 정문가 패턴이다. 책임을 수행할 정보를 알고 있는 객체에게 책임을 할당해야한다.
  • LOW COUPLING은 낮은 결합도 패턴이다.
  • HIGH COHESION은 높은 응집도 패턴이다.
  • LOW COUPLING HIGH COHESION는설계를 진행하면서 책임과 협력의 품질을 검토하는데 사용할 수 있는 중요한 평가 기준이 된다.
  • CREATOR는 창조자 패턴이다. 객체를 생성할 책임을 어떤 객체에게 할당할지에 대한 지침을 제공한다. 아래 조건을 많이 충족하는 객체가 무엇일지 생각해보면 좋다.
    • B가 A 객체를 포함하거나 참초
    • B가 A 객체를 기록
    • B가 A 객체를 긴밀하게 사용
    • B가 A 객체를 초기화하는 데 필요한 데이터를 가지고 있다.
  • 클래스의 응집도 판단 기준
    • 클래스가 하나 이상의 이유로 변경돼야 한다면 응집도가 낮다.
    • 클래스의 인스턴스를 초기화하는 시점에 경우에 따라 서로 다른 속성들을 초기화하고 있다면 응집도가 낮다.
    • 메서드 그룹이 속성 그룹을 사용하는지 여부로 나뉜다면 응집도가 낮다.
  • POLYMORPHISM은 다형성 패턴이다. 객체의 타입에 따라 변하는 행동이 있다면 타입을 분리하고 변화하는 행동을 각 타입의 책임으로 할당
  • PROTECTED VARIATIONS는 변경 보호 패턴이다. 예를 들어, A 클래스를 수정하지 않아도 오직 B 인터페이스를 실체화하는 클래스를 추가하는 경우
  • Refactoring은 이해하기 쉽고 수정하기 쉬운 소프트웨어로 개선하기 위해 겉으로 보이는 동작은 바꾸지 않은 채 내부 구조만 변경하는 것이다.
  • monster method는 응집도가 낮기 때문에 재사용, 변경하기가 어려운 긴 메서드다. 메서드를 작게 분해해서 메서드의 응집도를 높일 수 있다.
  • 메서드를 다른 클래스로 이동시킬 때 일반적으로 인자에 정의된 클래스 중 하나로 이동한다.

 

6장. 메시지와 인터페이스

  • Client-Server 모델
    • 협력 안에서 메시지를 전송하는 객체는 Client
    • 메시지를 수신하는 객체가 Server
  • 메시지는 객체들이 협력하기 위해 사용할 수 있는 유일한 의사소통 수단 ex) 메시지수신자. 오퍼레이션명(인자)
  • 메시지 전송 / 메시지 패싱은 한 객체가 다른 객체에게 도움을 요청하는 것
  • 메시지 전송자 메시지를 전송하는 객체
  • 메시지 수신자 메시지를 수신하는 객체
  • 클래스 의존성은 Association, Dependency, Inheritance, Realization이 있다.
  • 양방향 의존성은 피하자.
  • Many to One처럼 다중성이 적은 방향을 선택하자.
  • 패키지 사이의 의존성 사이클을 제거하자.
  • 메서드 메시지를 수신했을 때 실제로 실행되는 함수 또는 프로시저이며 오퍼레이션의 구현
  • 오퍼레이션은 프로그래밍 언어의 관점에서 퍼플릭 인터페이스에 포함된 메시지. 추상적이다. 동일한 오퍼레이션이라도 메서드는 다를 수 있다.
  • 퍼블릭 인터페이스는 객체가 의사소통을 위해 외부에 공개하는 메시지의 집합
  • 시그니처(signature)는 오퍼레이션 또는 메서드의 이름과 파라미터의 목록을 합친 것
  • 좋은 인터페이스는 최소한의 인터페이스와 추상적인 인터페이스라는 조건을 만족해야 한다.
  • 퍼블릭 인터페이스의 품질에 영향을 미치는 원칙
    • 디미터 법칙
      • 클래스가 특정한 조건을 만족하는 대상에게만 메시지를 전송
      • ex) this 객체, 메서드의 매개변수, this의 속성, this의 속성인 컬렉션의 요소, 메서드 내에서 생성된 지역 객체
      • screening.getMovie().getDiscountConditions();와 같은 코드는 디미터 법칙을 위반
      • IntStream.of(1, 15, 20, 3, 9).filter(x -> x > 10).distinct().count();와 같은 코드는 디미터 법칙을 지킴. 객체 내부의 구현에 대한 어떤 정보도 외부로 노출하지 않았다.
    • 묻지 말고 시켜라
    • 의도를 드러내는 인터페이스
      • 클라이언트 관점에서 isSatisfiedByPeriod, isSatisfiedBySequence와 같은 메서드명은 할인조건을 판단하는 동일한 작업을 실행한다. 내부 구현을 이해하지 못 하면 동일한 작업을 수행한다는 것을 알지 못 한다. 이처럼 책임을 수행하는 방법을 드러내는 메서드를 사용한 설계는 변경에 취약함
    • 명령과 쿼리 분리 원칙(Command-Query Separation 원칙)
      • routine는 어떤 절차를 묶어 호출이 가능하도록 이름을 부여한 기능 모듈
      • Procedure는 정해진 절차에 따라 내부의 상태를 변경하는 루틴의 한 종류
        • 부수효과를 발생시킬 수 있지만 값을 반환할 수 없다.
      • Function은 어떤 절차에 따라 필요한 값을 계산해서 반환하는 루틴의 한 종류
        • 값을 반환할 수 있지만 부수효과를 발생시킬 수 없다.
      • 명령은 객체의 상태를 수정하는 오퍼레이션이고, 프로시저다.
        • 객체의 상태를 변경하는 명령은 반환값을 가질 수 없다.
      • 쿼리는 객체와 관련된 정보를 반환하는 오퍼레이션이고, 함수다.
        • 객체의 정보를 반환하는 쿼리는 상태를 변경할 수 없다.
      • Command-Query Interface는 명령-쿼리 분리 원칙에 따라 작성된 객체의 인터페이스다.

 

반응형

'JAVA' 카테고리의 다른 글

Factory Pattern을 적용한 리팩토링  (0) 2024.09.03
이상한 나라의 객체 | 역할, 책임, 협력  (0) 2024.07.15
Facade Pattern  (0) 2024.07.03
HttpURLConnection | RestTemplate | WebClient  (0) 2023.12.28
enums(열거형)  (0) 2023.05.22