개발하는 프로 국밥러
article thumbnail

오브젝트

조영호님의 책 오브젝트를 보며 정리한 내용입니다.

문제가 될 시 해당글 삭제하겠습니다.


객체지향에서 애플리케이션의 가장 중요한 재료는 클래스가 아닌, 객체들이 주고받는 메시지이다!
객체가 수신하는 메시지들이 객체의 퍼블릭 인터페이스를 구성한다.

 

[협력과 메시지]

클라이언트 서버 모델

  • 두 객체 사시의 협력 관계를 설명하기 위해 사용하는 전통적인 모델
  • 협력은 클라이언트가 서버의 서비스를 요청하는 단방향 상호작용이다.
  • 객체가 독립적으로 수행할 수 있는 것보다 더 큰 책임을 수행하기 위해서 다른 객체와 협력해야 한다!

[메시지와 메시지 전송]

  • 메시지 전송 or 메시지 패싱 : 한 객체가 다른 객체에게 도움을 요청하는 것.
  • 메시지 전송자(클라이언트) : 메시지를 전송하는 객체
  • 메시지 수신자(서버) : 메시지를 수신하는 객체
  • 메시지의 구성 : 오프레이션명 + 인자
  • 메시지 전송의 구성 : 오퍼레이션명 + 인자 + 메시지 수신자

 

  • 메서드 : 메시지를 수신했을 때 실제로 수행되는 함수 또는 프로시저
    • 동일한 메시지를 전달하더라도, 객체의 타입에 따라 실행되는 메서드는 달라질 수 있다!!
    • 전통적인 방식의 개발자는 어떤 코드가 실행될지 정확하게 알고 있는 상황에서 함수 호출 구문을 작성한다.
      (전통적인 방식의 개발자는 코드의 의미가 컴파일 시점, 런타임 시점에 동일하다)
    • 반면 객체는 메시지와 메서드라는 서로 다른 개념을 실행 시점의 연결해야 한다!
      (객체지향 방식의 개발자는 코드의 의미가 컴파일 시점, 런타임 시점에 달라질 수 있다)
      (이러한 구분은 클라이언트와 서버가 느슨하게 결합될 수 있도록 한다! == 확장에 유리)

[퍼블릭 인터페이스와 오퍼레이션, 시그니처]

  • 퍼블릭 인터페이스 : 객체가 의사소통을 위해서 외부에 공개하는 메시지의 집합.
  • 오퍼레이션 : 퍼블릭 인터페이스에 포함된 메시지.
  • 시그니처 : 오퍼레이션이나 메서드의 명세를 나타낸 것으로 이름과 인자의 목록을 포함한다.

[인터페이스와 설계 품질]

- 퍼블릭 인터페이스 품질에 영향을 미치는 원칙과 기법

1. 디미터 법칙
   - 객체 내부 구조에 강하게 결합되지 않도록 협력 경로를 제한하는 것(오직 인접한 이웃하고만 말하라!)
   - 위 설명이 어려울 수 있기에 다음 조건에 해당하는 인스턴스에만 메시지를 전송하도록 하자!
      1. this 객체
      2. 메서드의 매개변수
      3. this 속성
      4. this의 속성인 컬렉션의 요소
      5. 메서드 내에서 생성된 지역 객체
      -> 디미터 법칙을 따르지 않았을 시 기차 충돌 이라 불리는 않좋은 코드를 짜게 된다.
         ex) screening.calulcateFee(audienceCount);
      -> 디미터 법칙을 통해 부끄럼타는 코드를 작성할 수 있다.
         (불필요한 어떤 것도 공유하지 않고, 다른 객체의 구현에 의존하지 않는 코드)
         (캡슐화하기 위해 따라야 하는 구체적인 지침을 제공한다)

2. 묻지 말고 시켜라
- 훌륭한 객체의 상태에 관해 묻지 말고 원하는 것을 시켜야 한다!
- 메시지 전송자는 메시지 수신자의 상태를 기반으로 결정을 내린 후 메시지 수신자의 상태를 바꿔서는 안된다!!!!!!!
   -> 객체의 상태를 변경하는 것은 메시지 수신자의 책임이다!!!!!
- 묻지 말고 시키는 것에 추가적으로 객체가 어떻게 작업을 수행하는지 노출시켜서는 안된다!!!!
   -> 어떻게 하는지가 아닌 무엇을 하는지를 서술해야 한다!

3. 의도를 들어내는 인터페이스
메서드의 이름을 지을 때 어떻게가 아닌 무엇을 하는지를 드러내야 한다!
(클라이언트 입장에서 동일한 작업을 수행하는 메서드들을 묶을 수 있다)
(의도를 드러내는 선택자(Intention Revealing Selector) -> 의도를 드러내는 인터페이스(Intention Revealing Interface))
클라이언트의 의도를 드러낼 수 있는 인터페이스 이름을 선택하자

4. 명령 쿼리 분리 원칙
- 루틴 : 절차를 묶어 호출이 가능하도록 이름을 부여한 기능 모듈
    - 프로시저 == 명령 : 부수효과를 발생시킬 수 있지만, 값을 반환할 수 없다.(Update / Delete) 
      -> 프로지저와 명령은 해당 메서드를 호출할 때는 부수효과에 대해서 항상 고민해야한다!!!
   - 함수 == 쿼리: 값을 반환할 수 있지만 부수효과를 발생시킬 수 없다. (Select)
- 명령 쿼리 분리 원칙을 한 문장으로 표현하면 "질문이 답변을 수정해서는 안된다!" 는 것이다!
- 명령 쿼리 분리 원칙을 지켜야하는 이유!
   - 한 메서드 안에 명령 쿼리가 함께 있다면, 너무나 고치기 힘든 버그를 만들어낸다...
      -> 실행결과를 예측하기가 너무 어려워진다.
      -> 인터페이스가 복잡해질수도 있지만 예측할 수 없는 버그로 주말을 반납하는 것 보다는 낫다.

 


[원칙의 함정]

- 설계는 트레이드 오프의 산물이라는 것이고, 원칙을 맹목적으로 추구하려는 것은 일관성을 잃어버릴 수 있다.
1. 디미터 법칙은 하나의 도트(.) 를 강제하는 규칙이 아니다!
   - 다미터 법칙은 결합도와 관련된 것이며, 객체 내부의 구조를 외부로 노출하지 않는다면 문제가 되지 않는다.
      ex) Java8 Stream
2. 결합도와 응집도의 충돌
   - 클래스는 하나의 변경 원인만을 가져야한다. 서로 상관없는 책임이 뭉쳐있는 클래스는 응집도가 낮으며 작은 변경으          로도 쉽게 무너질 수 있다.
   - 디미터 법칙, 묻지 말고 시켜라 원칙을 무작정 따르면 애플리케이션은 응집도가 늦은 객체로 넘쳐날 수 있다!
      -> 객체가 본질적으로 책임져야 하는 책임들에 대해서 우선적으로 생각하고! 그 후에 법칙들을 적용하자!

 

 

profile

개발하는 프로 국밥러

@gugbab2

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!