📜 제목으로 보기

  • 참고 유튜브 : https://www.youtube.com/watch?v=navJTjZlUGk
  • 정리본: https://github.com/LenKIM/object-book
  • 코드: https://github.com/eternity-oop/object
  • 책(목차) : https://wikibook.co.kr/object/

객체 작성 원칙

메세지 전송 이유: 3가지 관계

  • 객체망으로 해결한다: 객체로 메세지를 보내어서 해결한다

  • 객체 -> 객체로 메세지를 보내는 3가지 기준 관계

    image-20220808132850818

    1. 의존성으로서 전송하는 것인지
    2. 알림을 주기 위해 전송하는 것인지
    3. 조정을 하기 위해 전송하는 것인지
  • 대부분의 has-a관계(소유모델)은 delegate(위임)관계 때문이다.

    • templatemethod -> strategy를 써서 delegate(위임)한다

테스트와 객체설계 및 발견

image-20220808133349257

  1. 무조건 메인함수 or 테스트 코드부터 짠다.

    • 그래야 지구평화를 안지키고, 필요한 것만 짤 수 있다.
    • class를 사용하는 코드(인스턴스)부터 짠다.
    • input -> output되는 객체부터 짠다.
  2. 테스트를 작게 짠다.

    • 테스트 규모가 크다 == 값으로 짰다 or 단일책임원칙 실현안했다. or 의존성이 너무 심하다
  3. 처음부터 의존성 주입을 고려한다.

    • 생성자주입 or setter주입 2종류가 있다.
    • 주입할 수 있는 코드를 분리하여서 짜서 넣어본다.
    • 이것을 해보면, 밖에서 주입시의 제약조건을 확인할 수 있다.
      • 인자로 인터페이스를 받아들이면, 해당 구상클래스들이 다 들어올 수 있게된다. 구상을 받으면, 1개 밖에 못넣는다.
    • 자바의 메서드의 인자는 반공변이다. 선언된 형의 자식들 밖에 못들어온다
      • 가장 위쪽으로 파라미터를 선언해야한다.
      • typescript는 공변이라서… 더 위를.. 집어넣을 수도 있다.
    • 메서드 시그니쳐 짤 때 가장 중요한 것은, 이 함수가 외부세계에서, 얼마나 포괄적인 데이터를 받을 것인가를 결정하는 것이다.
      • Object를 넣으면.. 다 받을 수 있다.
      • integer, boolean을 가장 밑에 기본형을 쓰면, 거기 밑에는 아무것도 없어서 값밖에 못받는다.
    • 객체지향에서 객체를 인자로 쓴다? -> 값x -> 좁은형을 안쓰겠다. 객체는 확장도 되니, 역할과 책임을 나타내기 위핸 객체로 나타낸다.
      • 객체의 특징은 메서드에 있으며, 그 인자와 응답형에 의해 원하는 형을 넣어줘서 역할과 책임을 나타낸다.
      • 인자는 들어올 수 있는 상한을 정해주고, return은 하한을 정해준다. 그 위로만 받겠다. 최소한 하한형까지는 보장해준다.
    • 처음부터 의존성주입을 할 수 있는 메서드 인자로 만들어놓아서, 이것 저것 넣어보면서 확인하며 상한/하한을 정해나간다
  4. 목 객체 테스트를 해야한다.

    • 그래야 객체의 통신테스트를 할 수 있다.
    • context독립성 == 객체의 격리를 확인한다.
    • 아예 처음부터, 목객체를 왕창 만들어놓고, 얘는 a한테 뭘 받아서 b를 주는게 역할이야. 이런식으로 짠다.
      • office한테 영화를 받아와서 customer에게 줄거야
      • office와 customer의 목객체들을 만들어놓고 테스트하면서 만들어나간다.

목객체 테스트 요령

image-20220808140621347

  1. 처음에 객체들을 만들어서 중복을 제거한다.
    • 중복되는 부분들은 템플릿메소드패턴 -> 전략패턴으로 빼서 다른 부분만 구현하고 본체만 남기도록 하게 한다
    • Renderer의 경우, 단위 (구상)클래스 1개만 나오고, Visitor가 여러개 나오게 했다.
      • 만약,전략패턴 같은 VIsitor로 빼지 않았더라면, ConsoleRenderer, JsonRenderer와 같은 제어문 속에 중복이 발생하게 된다.
  2. 단일 책임 원칙을 구현하다보면, 부수적인 로직들은 도우미 메서드로 빠지게 된다.
    • 도우미 메서드들은 Util클래스를 만들어서 static 메서드들로 때려박는다.
  3. 도우미 메서드의 조직화 과정에서 종단점 도우미를 발견한다 (책 읽어야 할 수 있음)
  4. 최종목표는 구현계층 vs 선언계층 나눠져있는 것을 모두 선언계층으로 옮기는 것이다.
    • 보다 선언적으로 바뀌었다는 말
    • Visitor객체는 보다 선언계층으로 옮겨간 것이다.
      • 제어의 역전으로 제어구문을 뺏겨 인터페이스대로 메서드를 만들 수 밖에 없다
      • 자유롭게 구현 vs 인터페이스 아래 선언된 메서드로 오버라이딩
      • 달라진 값밖에 줄 수 밖에 없다.
    • 선언적으로 바뀌게 되면, 팩토리가 되거나, 조립층에 DI가 들어가게 된다
    • 디자인패턴들은 선언적으로 바뀌는 핵심적은 블록들이다.
      • 다 의존성역전, 제어의역전을 만들어 선언으로 빼야한다.
      • 커맨드패턴 -> 커맨드객체를 받아들이는 커맨드홀더객체(invoker객체)가 됨으로서 모든 메서드들은 필요없게 된다.
      • Visitor패턴 -> 제어문을 완전히 한 쪽에다가 위임(Renderer)하고 나는 제어구조에 참여하는 메서드로 만든 다음, visitor가 된다.

어댑터 계층 구현하기

image-20220808140945129

  1. 절대로 라이브러리 코드를 바로 쓰지말고 무조건 감싸서 써라
    • ex> useEffect -> useXXXEffect(어댑터)를 통해서 써라
    • 외부충격을 흡수하는 어댑터만들 때부터 끼워서 써라
    • 아무것도 안하는 path함수라도 만들어서 써라
      • jquery -> jQ라고 함수로 감싸서 써라
        • jquery기능들을 바로 쓰지말고, 함수로 따로 만들어서 써라
        • $함수 감싸기, attribute함수 감싸기, css함수 감싸기
      • jquery가 시그니쳐를 바꿔도 충격흡수를 함수/클래스에서 해준다.
      • jdbc보다는 springjdbc가 더 낫다. 한번이라도 더 감싸진 것이 낫다
  2. 어댑터의 종류 3가지
    1. 1:1매핑해서 쓰는 단순한 어댑터
      • 한번 감싸써 서드파티의 시그니쳐가 바뀌더라도 충격을 흡수하지만, 변경시마다 수정해줘서야해서 서드파티변경에 취약하다는 단점
    2. 델리게이터 어댑터 : 위임(델리게이터)를 추가한 것
      • 이벤트를 받는다던지, 직접적인 관계들을 다 뺀 것
        • jquery를 아무리 감싸도 event를 걸면 직접적으로 연결된다.
        • jquery가 요구하는대로의 리스너를 만들 수 밖에 없다
        • 하지만 델리게이터가 있다면, jquery이벤트 -> 델리게이터의 이벤트 -> 우리는 델리게이터가 요구하는 리스너를 주면된다.
          • 델리게이터는 jquery가 원하는 리스너를 전달해주겠지만
          • 그 안에는 우리가 준 리스너를 호출하는 코드가 들어가있고 안변한다.
            • jquery를 리스너를 넘기면, jquery event를 인자로 받는 리스너인데,
            • 델리게이터 리스너 인자에 도우미객체 + native객체 2개를 받도록 만들어, 델리게이터는 jquery에게 jquery리스너를 주겠지만, 그 내부에는 내 리스너를 jquery리스너 형태에 맞게끔 변형해서 건네준다.
        • 도우미객체 + 원래 객체를 같이 jquery에게 건네주는 델리게이터?
    3. 어댑터 레이어: 어려운 것.. 레이어 수준.. 시스템을 감싸서..