OBJECT 21 객체 작성 원칙 및 테스트 작성 요령 정리(마지막)
object 책을 강의한 코드스핏츠 유튜브 요약
📜 제목으로 보기
- 참고 유튜브 : 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가지 기준 관계
- 의존성으로서 전송하는 것인지
- 알림을 주기 위해 전송하는 것인지
- 조정을 하기 위해 전송하는 것인지
-
대부분의 has-a관계(소유모델)은
delegate
(위임)관계 때문이다.- templatemethod -> strategy를 써서 delegate(위임)한다
테스트와 객체설계 및 발견
-
무조건 메인함수 or 테스트 코드부터 짠다.
- 그래야 지구평화를 안지키고, 필요한 것만 짤 수 있다.
- class를 사용하는 코드(인스턴스)부터 짠다.
- input -> output되는 객체부터 짠다.
-
테스트를 작게 짠다.
- 테스트 규모가 크다 == 값으로 짰다 or 단일책임원칙 실현안했다. or 의존성이 너무 심하다
-
처음부터 의존성 주입을 고려한다.
- 생성자주입 or setter주입 2종류가 있다.
- 주입할 수 있는 코드를 분리하여서 짜서 넣어본다.
- 이것을 해보면, 밖에서 주입시의 제약조건을 확인할 수 있다.
- 인자로 인터페이스를 받아들이면, 해당 구상클래스들이 다 들어올 수 있게된다. 구상을 받으면, 1개 밖에 못넣는다.
-
자바의 메서드의 인자는
반공변
이다.선언된 형의 자식들 밖
에 못들어온다- 가장 위쪽으로 파라미터를 선언해야한다.
- typescript는 공변이라서… 더 위를.. 집어넣을 수도 있다.
-
메서드 시그니쳐 짤 때 가장 중요한 것
은,이 함수가 외부세계에서, 얼마나 포괄적인 데이터를 받을 것인가
를 결정하는 것이다.- Object를 넣으면.. 다 받을 수 있다.
- integer, boolean을 가장 밑에 기본형을 쓰면, 거기 밑에는 아무것도 없어서 값밖에 못받는다.
-
객체지향에서 객체를 인자로 쓴다? ->
값x -> 좁은형을 안쓰겠다. 객체는 확장도 되니, 역할과 책임을 나타내기 위핸 객체로 나타낸다.
- 객체의 특징은 메서드에 있으며, 그 인자와 응답형에 의해 원하는 형을 넣어줘서 역할과 책임을 나타낸다.
- 인자는 들어올 수 있는 상한을 정해주고, return은 하한을 정해준다. 그 위로만 받겠다. 최소한 하한형까지는 보장해준다.
처음부터 의존성주입을 할 수 있는 메서드 인자
로 만들어놓아서,이것 저것 넣어보면서 확인하며 상한/하한을 정해나간다
-
목 객체 테스트를 해야한다.
- 그래야
객체의 통신테스트
를 할 수 있다. - context독립성 == 객체의 격리를 확인한다.
-
아예 처음부터, 목객체를 왕창 만들어놓고, 얘는 a한테 뭘 받아서 b를 주는게 역할이야. 이런식으로 짠다.
- office한테 영화를 받아와서 customer에게 줄거야
- office와 customer의 목객체들을 만들어놓고 테스트하면서 만들어나간다.
- 그래야
목객체 테스트 요령
- 처음에 객체들을 만들어서 중복을 제거한다.
- 중복되는 부분들은 템플릿메소드패턴 -> 전략패턴으로 빼서 다른 부분만 구현하고
본체만 남기도록
하게 한다 -
Renderer의 경우, 단위 (구상)클래스 1개만 나오고, Visitor가 여러개 나오게 했다.
- 만약,전략패턴 같은 VIsitor로 빼지 않았더라면, ConsoleRenderer, JsonRenderer와 같은 제어문 속에 중복이 발생하게 된다.
- 중복되는 부분들은 템플릿메소드패턴 -> 전략패턴으로 빼서 다른 부분만 구현하고
- 단일 책임 원칙을 구현하다보면, 부수적인 로직들은 도우미 메서드로 빠지게 된다.
- 도우미 메서드들은 Util클래스를 만들어서 static 메서드들로 때려박는다.
- 도우미 메서드의 조직화 과정에서 종단점 도우미를 발견한다 (책 읽어야 할 수 있음)
-
최종목표는 구현계층 vs 선언계층 나눠져있는 것을 모두 선언계층으로 옮기는 것이다.
- 보다 선언적으로 바뀌었다는 말
- Visitor객체는 보다 선언계층으로 옮겨간 것이다.
- 제어의 역전으로 제어구문을 뺏겨 인터페이스대로 메서드를 만들 수 밖에 없다
- 자유롭게 구현 vs 인터페이스 아래 선언된 메서드로 오버라이딩만
- 달라진 값밖에 줄 수 밖에 없다.
- 선언적으로 바뀌게 되면, 팩토리가 되거나, 조립층에 DI가 들어가게 된다
-
디자인패턴들은 선언적으로 바뀌는 핵심적은 블록들이다.
- 다 의존성역전, 제어의역전을 만들어 선언으로 빼야한다.
- 커맨드패턴 -> 커맨드객체를 받아들이는 커맨드홀더객체(invoker객체)가 됨으로서 모든 메서드들은 필요없게 된다.
- Visitor패턴 -> 제어문을 완전히 한 쪽에다가 위임(Renderer)하고 나는 제어구조에 참여하는 메서드로 만든 다음, visitor가 된다.
어댑터 계층 구현하기
- 절대로 라이브러리 코드를 바로 쓰지말고 무조건 감싸서 써라
- ex> useEffect -> useXXXEffect(어댑터)를 통해서 써라
외부충격을 흡수하는 어댑터
를만들 때부터 끼워서 써라
- 아무것도 안하는 path함수라도 만들어서 써라
- jquery -> jQ라고 함수로 감싸서 써라
- jquery기능들을 바로 쓰지말고, 함수로 따로 만들어서 써라
- $함수 감싸기, attribute함수 감싸기, css함수 감싸기
- jquery가
시그니쳐를 바꿔도 충격흡수를 함수/클래스
에서 해준다. - jdbc보다는 springjdbc가 더 낫다. 한번이라도 더 감싸진 것이 낫다
- jquery -> jQ라고 함수로 감싸서 써라
- 어댑터의 종류 3가지
-
1:1매핑
해서 쓰는단순한 어댑터
- 한번 감싸써 서드파티의 시그니쳐가 바뀌더라도 충격을 흡수하지만, 변경시마다 수정해줘서야해서 서드파티변경에 취약하다는 단점
-
델리게이터 어댑터
: 위임(델리게이터)를 추가한 것- 이벤트를 받는다던지, 직접적인 관계들을 다 뺀 것
- jquery를 아무리 감싸도 event를 걸면 직접적으로 연결된다.
- jquery가 요구하는대로의 리스너를 만들 수 밖에 없다
- 하지만 델리게이터가 있다면, jquery이벤트 -> 델리게이터의 이벤트 -> 우리는 델리게이터가 요구하는 리스너를 주면된다.
- 델리게이터는 jquery가 원하는 리스너를 전달해주겠지만
- 그 안에는 우리가 준 리스너를 호출하는 코드가 들어가있고 안변한다.
- jquery를 리스너를 넘기면, jquery event를 인자로 받는 리스너인데,
- 델리게이터 리스너 인자에 도우미객체 + native객체 2개를 받도록 만들어, 델리게이터는 jquery에게 jquery리스너를 주겠지만, 그 내부에는 내 리스너를 jquery리스너 형태에 맞게끔 변형해서 건네준다.
- 도우미객체 + 원래 객체를 같이 jquery에게 건네주는 델리게이터?
- 이벤트를 받는다던지, 직접적인 관계들을 다 뺀 것
-
어댑터 레이어
: 어려운 것.. 레이어 수준.. 시스템을 감싸서..
-