SlideShare a Scribd company logo
1 of 71
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
s66 GOOS
20, 21, 22
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장에서 다룰 내용
‘왜’ 테스트 하기 어려운가?
• 테스트를 작성하기 어려운 경우
• 테스트 주도 개발
• ‘테스트 악취’
1. 불분명, 불안정한 테스트
2. 테스트하기 어려운 코드
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1
• 테스트 요구사항 T1
1. receiver 객체는 request를 여러번 받을 수 있다.
2. 다음 request 를 받을때 시간이 많이 지났음을 식별할 수 있어야 한다.
#Test : 1
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1
• 구현 분석
• 싱글톤 객체인 System에서 now 인스턴스를 받는다. (new Date())
• firstDateIsDifferentFrom 은 Date 연산을 도와주는 메소드 (예시구현)
#Test : 1
의존성을 가진 싱글톤 객체
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1
• Problem
• 테스트를 수행하려면 너무 많은 시간이 걸린다. (= 어렵다)
• Conclusion
• Date 를 생성하는 방법을 제어해야 한다.
• 새로운 객체를 도입해 receiver에게 전달해야 한다.
#Test : 2
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1 #Test : 2
• 테스트 구현사항
• receiver 객체는 Clock 없이 생성할 수 없다.
• Date를 생성하는 방법을 제어할 수 있다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1 #Test : 2
• Solution
• Date 의존성을 떼어냄
• Next Problem
• Receiver 안에 Date 처리 로직이 남음
• Conclusion
• clock 안으로 Date 처리 로직을 이동
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1 #Test : 3
• 테스트 구현사항
• receiver 객체 안에 날짜 비교 로직을 제외하고 싶다.
• 구현한 clock 이 날짜 비교 로직을 갖게 하자.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1 #Test : 3
• 구현 분석
• receiver 객체는 더 이상 날짜 구분 로직을 포함하지 않아도 된다.
• 날짜 관련 구현을 전부 위임하면?
날짜 저장 구현도 위임하자
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1 #Test : 4
• 테스트 요구사항 T1`
• Receiver에게 request를 보내고 만료되었는지 확인한다.
테스트 이름도 바뀜
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1 #Test : 4
• 구현 분석
• Receive 객체에는 시간을 저장하는 로직도 남아있지 않게 되었다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
객체는 객체 범위 내에서 관리되는 값이나, 명시적으로 전달되는 값과 인스턴스를 다뤄야 한다.
객체의 동작이 객체 밖의 컨텍스트에 영향을 받는다면
- 외부 컨텍스트 조건에 따라 테스트를 작성해야 하고
- 객체를 컴포넌트로 구분해서 쓰기 어려워진다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.2
• 보조 로깅
• 시스템을 감시하기 위한 목적
• 시스템 관리자, 운영자가 보고
관리하는 로그
• 제품에 포함되어 테스트 주도
적이어야 한다.
• 로그를 분석하는 스크립트나 관
리 도구를 보호하기 위해
• 진단 로깅
• 개발자가 내부 이해를 위한 목적
• 개발자가 개발 중에만 보는 로그
• 제품에 포함되어서는 안된다.
• Q : 테스트 주도적일 필요 있을까?
없다.
제품에 포함하지 않기로 합의한 메세지이기 때문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.2
• 구현 분석
• 일반적인 로깅 구현
• 역할 분석
• Location을 처리하는 일
• 정보를 출력하는 일
단일 책임 원칙 위반
Q: 정보를 출력하는 일이 중복될 것이라는 예상?
Q: logger.info(…) 내용은 “구현”인가 “의도”인가?
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.2
• support : 보조 객체
• 로거, 메세지 버스, 팝업 창 등..
• 변화점
• 목 객체를 활용하여 테스트 가능
• 코드가 의도하는 바를 표현함
• “구현”이 아닌 “의도”를 전달하자
• 일관성 유지, 재사용 촉진
테스트를 작성 중 실천 양식
잘 모르는 예외를 처리할 수 없어 로
그만 남기고 넘어가지 않는다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.2 로깅은 기능이다
로그를 캡슐화하여 관리하는 것은 로그가 넘쳐 실패하는 제품으로 나아가는걸 막아준다.
로거를 대상으로 테스트할 수 없다면 설계가 명확하지 않았기 때문이다.
실제 운영되는 서비스에서
중요한 의미로 쓰이지 않는 로그때문에 중요한 로그를 찾지 못한걸 경험이 누구에게나 있을 것이다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.3 p.272
• Problem
• CDPlayer와 MusicCentre간에 관계가
암시적으로 남는다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.3
• Problem
• MusicCentre가 CDPlayer에 너무 많이 접근할 수 있음
• Solution
• MusicCentre가 쓰는 메소드를 ScheduleDevice 인터페이스로 묶는다
• SOLID : Interface Segregation Principle (인터페이스 분리 원칙)
MusicCentre 가 쓰는 메소드
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.3 구상 클래스에 대한 목 객체 적용
한꺼번에 변경할 수 없는 레거시 코드를 다루는 경우
전혀 변경할 수 없는 서드 파티 코드를 다룰때
참고 : 19장 257p 스스로 규칙을 어기는 것인가?
단, 클래스의 내부 기능을 재정의 해서는 절대 안 된다.
재정의한 구현이 테스트에 묶여버린다.
우리는 테스트에 “구현” 전달을 지양하고, “의도” 전달을 지향하기 때문.
테스트로 부터의 피드백 – 테스트에서 닿지 않는 구조는 클래스를 더 작게 분할할 시점이다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.4
• Problem
• Video 인터페이스를 만들 필요가 보이지 않는다.
• To-be
• 값 객체로 바꾸자.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.4 값에 목 객체를 적용하지 말라
값을 표현하기 위해서는 인스턴스를 적절하게 생성하서 사용한다.
책에서 제안하는 휴리스틱
1. 해당 클래스의 값이 불변적이다.
2. 해당 타입의 인터페이스를 구현하는 클래스의 이름이 모호하다.
값의 인스턴스를 생성해서 사용하기 복잡한 경우를 뒤에서 다룬다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.5
• Problem
• 생성자가 너무 크다
• Solution
• 일부 인자를 묶어 새로운 클래스로 대체
(unpacker, counterPartyFinder)는 생성자에
정해지고 짝으로 움직인다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.5
• Problem
• 생성자가 너무 크다
• Solution
• 일부 인자를 묶어 새로운 클래스로 대체
(locationFinder, domesticNotifier,
importedNotifier) 는 같이 생성되고
세트로 움직인다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.5
• 구현 분석
• MessageProcessor의 책임이 줄어듦.
• input, process, output 세 객체만 남는다.
• 코드가 더 명료해짐
• 테스트 하기 쉽다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.5 비대한 생성자
MessageUnpacker, MessageDispatcher와 같은 암시적인 컴포넌트를 뽑아내는 두 가지 조건.
1. 늘 함께 사용되고 수명이 같은 인자일때.
2. 새롭게 묶어낸 개념을 설명할 더 나은 이름이 있을때.
이제 우리는 변화를 통합하기 훨씬 쉬워졌다.
- 객체가 유연해졌다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.6
• Problem
• 생성자가 너무 크다
• 관련없는 책임이 많이 포함되어 있다.
• 관련이 없는 기능들이 같이 묶여있다.
• 너무 방대한 클래스다.
• Solution
• 나눠야 한다.
• 서로 관련 없는 테스트가 많이 생긴다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.6 혼동되는 객체
테스트 간에 서로 아무런 관련이 없다면 객체를 쪼갤 수 있다.
‘레거시 코드 활용 전략’ – 내 프로젝트 군살 빼기
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.7
• 요구사항
• 경주 게임.
• 차량을 설정하여 누가 경주에 이기는지
확인한다.
• Problem
• 생성자가 너무 크다.
• Solution
• 의존성을 가지고 있는 모든 객체가 전부
꼭 필요한가?
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.7
• 구현 분석
• 객체들을 기본값으로 초기화 했다.
• 생성자가 줄어들었다.
• 나머지 객체들을 인터페이스로 변경할
수 있게 되었다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.7 너무 많은 의존성
20.5, 20.6, 20.7 은 하나의 목표를 위해 여러가지 방법을 제안하고 있음.
- 생성자의 크기를 줄인다.
Q : 왜 생성자를 줄여야 할까?
- 테스트에 의도를 파악하기 힘들게 만들고
- 변화에 유연하지 못하게 만들고
- 객체가 앞으로 계속 늘어날 수 있고
…
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20장
• 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다
• 20.2 로깅은 기능이다
• 20.3 구상 클래스에 대한 목 객체 적용
• 20.4 값에 목 객체를 적용하지 말라
• 20.5 비대한 생성자
• 20.6 혼동되는 객체
• 20.7 너무 많은 의존성
• 20.8 너무 많은 예상 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.8
• Problem
• 테스트가 무엇을 테스트 하고자 하는지 알기 어렵다.
• 중요도가 파악이 되지 않는다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.8
• 구현 분석
• thirdParty 만 영향을 미침
• 영단어 설명
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.8 너무 많은 예상 구문
너무 많은 예상 구문은 테스트를 읽기 어렵게 만든다.
예상 구문이 너무 많은 경우는 테스트의 단위가 너무 커서 예상할 내용이 너무 많거나
객체 상호 작용을 너무 많이 직접 예상하기 때문이다.
- 테스트의 규모가 너무 커지지 않도록 항상 주의 해야 한다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
20.9 테스트가 우리에게 말해주는 것 (테스트로 얻는 피드백)
객체에 담고 있는 내용을 객체 내부로 한정할 수 있으면 콘텍스트에 독립적인 객체가 완성된다.
이름은 도메인 정보를 담는다.
- 객체의 구현에 대해 서술하지 않고 객체망 의 상호 작용을 담는다.
- 고도의 추상화를 포함하고, 객체에 “의도”를 이름이 표현한다.
데이터 대신 행위를 전달하라
- 객체에 “의도”를 전달한다. (테스트는 동작에 추상적이고, 객체는 값에 추상적이다)
테스트는 테스트와 그 내부 품질에 대한 피드백을 꾸준히 우리에게 말한다.
- 테스트에서 악취가 발견되면 즉시 수정하라.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21장에서 다룰 내용
읽기 쉬운
테스트 작성 가이드
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21장
• 21.1 테스트 이름은 기능을 기술한다
• 21.2 정규 테스트 구조
• 21.3 테스트 코드의 능률화
• 21.4 단정과 예상 구문
• 21.5 리터럴과 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.1
• 테스트 요구사항 1
• List는 항목이 추가된 순서대로 항목을 보관한다.
• 서술어 : 보관한다 - holds
• 목적어 : 항목 - Items
• 주어 : List
• 수식어구 : 항목이 추가된 순서대로
• holdsItemsInTheOrderTheyWereAdded
• 테스트 요구사항을 그대로 이름으로 옮긴다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.1
• 테스트 요구사항 2
• List는 동일한 항목에 대해 여러 개의 참조를 보관할 수 있다.
• 서술어 : 보관할 수 있다 – can hold
• 목적어 : 항목 - Multiple References
• 주어 : List
• 수식어구 : 동일한 항목에 대해
• canHoldMultipleReferencesToTheSameItem
• 테스트 요구사항을 그대로 이름으로 옮긴다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.1
• 테스트 요구사항 3
• List는 보관 중이지 않은 항목을 제거할 때 예외를 던진다.
• 서술어 : 던진다 – throws
• 목적어 : 항목 – an Exception
• 접속사 : 때 – when
• 종속절 - 서술어 : 제거할 – remove
• throwsAnExceptionWhenRemovingAnItemDoesntHold
• 테스트 요구사항을 그대로 이름으로 옮긴다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.1 테스트 이름은 기능을 기술한다
테스트 이름은 예상하는 결과, 객체의 행동, 시나리오의 동기를 서술해야 한다.
실천 양식
- 개발 기간 동안 정기적으로 테스트 문서를 읽으려는 노력을 해야한다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21장
• 21.1 테스트 이름은 기능을 기술한다
• 21.2 정규 테스트 구조
• 21.3 테스트 코드의 능률화
• 21.4 단정과 예상 구문
• 21.5 리터럴과 구문
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.2
1. 준비 : 테스트의 콘텍스트
2. 실행 : 테스트 행위 촉발
3. 검증 : 예상되는 효과 검사
4. 정리 : 잔존 상태 정리
21.1
• 예상하는 결과
• 객체의 행동
• 시나리오의 동기
검증 - 결과 / 실행 – 행동 / 준비 – 동기
정리는 구현의 일부
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.2 정규 테스트 구조
준비, 실행, 검증 정리 단계로 나누어 진다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.3
instruments 컬렉션에 Instrument 항목중에서
strikePrice가 81보다 큰 항목이 하나라도 있는지 검사.
assertThat(instruments,hasItem(instrumentWithPrice(greatherThan(81))));
쉽게 의도를 파악할 수 있는 단정문으로 검사한다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.3 p293
• 테스트 요구사항
• 매크로 적용의 결과가 맞는지 확인
Exception이 test 밖으로 빠져나갈 수 있도록 둔다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.4
• 테스트 요구사항
• 스나이퍼 식별자(ID)를 확인한다
• 메세지를 확인한다.
• 세번째 인자로는 어느 객체가 와도 무방(-any)하다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.4
assertFalse(“end date”, first.endDate().equals(second.endDate()));
assertThat(”end date”, first.endDate(), not(equalTo(second.endDate())));
부정문 not을 이용하면 코드가 더 명시적으로 보인다.
assertFalse보다 위와 같이 쓰는걸 권장한다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
21.5
테스트 코드에는 필연적으로 리터럴 값이 많이 포함된다.
테스트는 값에 구체적이기 때문에
변수에 이름을 부여해서 사용하자.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22장에서 다룰 내용
테스트를 위해 필요한 객체를 생성하고 싶을때마다
우리는 생성자 인자를 모두 직접 작성해야 한다.
- 또 이 객체를 생성하는 코드가 많아지면 테스트를
읽기 매우 어려워진다.
- 생성자 인자나 구조를 변경하는 순간 여러 테스트
가 깨지게 된다.
이 문제를 해결해서 복잡한 내용을 담은 테스트 코드
를 읽기 쉽게 만들어야 한다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.0
• object mother Pattern (객체 모체 패턴)
• pros
• 구조를 만드는 코드에 이름을 부여함
• 재사용할 수 있다
• cons
• 데이터 변화에 대처하기 힘들다
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22장
• 22.1 테스트 데이터 빌더
• 22.2 비슷한 객체 생성
• 22.3 빌더 조합
• 22.4 팩터리 메소드를 이용한 도메인 모델 강조
• 22.5 사용 시점에서 중복 없애기
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.1
• 객체 생성
Order order = new OrderBuilder().
build();
• 의미 있는 값 지정
new OrderBuilder().
fromCustomer(…).build();
new CustomerBuilder().
withAddress(new AddressBuilder…)
.build()
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22장
• 22.1 테스트 데이터 빌더
• 22.2 비슷한 객체 생성
• 22.3 빌더 조합
• 22.4 팩터리 메소드를 이용한 도메인 모델 강조
• 22.5 사용 시점에서 중복 없애기
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.2 p.300
• 비슷한 객체를 생성하는 일이 있을때 코드를 줄이는 방법
중복된 데이터를 넣는 중간 빌더 상태를 만들어서 각각 사용한다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.2 301p
• builder를 이용해 또 다른 builder를 구현할 수 있게 한다.
상태를 중복하는 메서드를 추가하여 데이터를 만들 수 있다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22장
• 22.1 테스트 데이터 빌더
• 22.2 비슷한 객체 생성
• 22.3 빌더 조합
• 22.4 팩터리 메소드를 이용한 도메인 모델 강조
• 22.5 사용 시점에서 중복 없애기
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.3 302p
• builder를 이용해 또 다른 builder를 구현할 수 있게 한다.
상태를 중복하는 메서드를 추가하여 데이터를 만들 수 있다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22장
• 22.1 테스트 데이터 빌더
• 22.2 비슷한 객체 생성
• 22.3 빌더 조합
• 22.4 팩터리 메소드를 이용한 도메인 모델 강조
• 22.5 사용 시점에서 중복 없애기
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.4 302p
• method Overloading을 이용해서 with 구문을 만든다.
• 단, String 타입처럼 중복된 타입에 대해서는 올바르게 동작하지 않는다.
• 왜? 하나의 타입에 두 개 이상의 멤버인 경우 선택할 수 없기 때문.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22장
• 22.1 테스트 데이터 빌더
• 22.2 비슷한 객체 생성
• 22.3 빌더 조합
• 22.4 팩터리 메소드를 이용한 도메인 모델 강조
• 22.5 사용 시점에서 중복 없애기
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.5
• 요구사항
• 왼쪽 코드는 테스트에 필요한 값
을 생성하는 코드이다. 이 코드의
중복을 찾아 제거하자
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
22.5
• 테스트 코드의 중복을 제거하
는데 성공하였다.
s66 테스트 주도 개발로 배우는
객체 지향 설계와 실천
감사합니다.
삼가 고인의 명복을 빕니다.

More Related Content

Viewers also liked

Pres open-data-api-numerique-nantes-sept15
Pres open-data-api-numerique-nantes-sept15Pres open-data-api-numerique-nantes-sept15
Pres open-data-api-numerique-nantes-sept15NFR21
 
Identifica y clasifica reactivos quimicos
Identifica y clasifica reactivos quimicos Identifica y clasifica reactivos quimicos
Identifica y clasifica reactivos quimicos Jesus Martinez Peralta
 
Stratégie numérique rurale - Communauté de Communes du Sud-Artois
Stratégie numérique rurale - Communauté de Communes du Sud-ArtoisStratégie numérique rurale - Communauté de Communes du Sud-Artois
Stratégie numérique rurale - Communauté de Communes du Sud-ArtoisLes Interconnectés
 
L'Etabli - Université du temps libre Landes Côte Sud
L'Etabli - Université du temps libre Landes Côte SudL'Etabli - Université du temps libre Landes Côte Sud
L'Etabli - Université du temps libre Landes Côte SudLes Interconnectés
 
Irrigation water management
Irrigation water managementIrrigation water management
Irrigation water managementboopathin
 
France as a model for Chilean educational reform to reduce economic disparity
France as a model for Chilean educational reform to reduce economic disparityFrance as a model for Chilean educational reform to reduce economic disparity
France as a model for Chilean educational reform to reduce economic disparityMélanie Rieder
 

Viewers also liked (9)

Fuelを利用したOpenStack簡単セットアップ
Fuelを利用したOpenStack簡単セットアップFuelを利用したOpenStack簡単セットアップ
Fuelを利用したOpenStack簡単セットアップ
 
Pres open-data-api-numerique-nantes-sept15
Pres open-data-api-numerique-nantes-sept15Pres open-data-api-numerique-nantes-sept15
Pres open-data-api-numerique-nantes-sept15
 
ENGAGE eat insects
ENGAGE eat insectsENGAGE eat insects
ENGAGE eat insects
 
Identifica y clasifica reactivos quimicos
Identifica y clasifica reactivos quimicos Identifica y clasifica reactivos quimicos
Identifica y clasifica reactivos quimicos
 
Stratégie numérique rurale - Communauté de Communes du Sud-Artois
Stratégie numérique rurale - Communauté de Communes du Sud-ArtoisStratégie numérique rurale - Communauté de Communes du Sud-Artois
Stratégie numérique rurale - Communauté de Communes du Sud-Artois
 
L'Etabli - Université du temps libre Landes Côte Sud
L'Etabli - Université du temps libre Landes Côte SudL'Etabli - Université du temps libre Landes Côte Sud
L'Etabli - Université du temps libre Landes Côte Sud
 
Irrigation water management
Irrigation water managementIrrigation water management
Irrigation water management
 
France as a model for Chilean educational reform to reduce economic disparity
France as a model for Chilean educational reform to reduce economic disparityFrance as a model for Chilean educational reform to reduce economic disparity
France as a model for Chilean educational reform to reduce economic disparity
 
Насатова Л.С.
Насатова Л.С.Насатова Л.С.
Насатова Л.С.
 

Similar to S66 goos-w6

Devon 2011-b-5 효과적인 레거시 코드 다루기
Devon 2011-b-5 효과적인 레거시 코드 다루기Devon 2011-b-5 효과적인 레거시 코드 다루기
Devon 2011-b-5 효과적인 레거시 코드 다루기Daum DNA
 
아꿈사.C++ api 디자인.20140315 a
아꿈사.C++ api 디자인.20140315 a아꿈사.C++ api 디자인.20140315 a
아꿈사.C++ api 디자인.20140315 aChoonghyun Yang
 
애자일 프랙티스
애자일 프랙티스애자일 프랙티스
애자일 프랙티스한 경만
 
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"용근 권
 
Effective java
Effective javaEffective java
Effective javaHaeil Yi
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기Wonchang Song
 
테스트 기발 개발, TBD(Test based developement)
테스트 기발 개발, TBD(Test based developement)테스트 기발 개발, TBD(Test based developement)
테스트 기발 개발, TBD(Test based developement)도형 임
 
클린 코드 part2
클린 코드 part2클린 코드 part2
클린 코드 part2Minseok Jang
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Javajigi Jaesung
 
테크데이 발표자료.pptx.pdf
테크데이 발표자료.pptx.pdf테크데이 발표자료.pptx.pdf
테크데이 발표자료.pptx.pdfJihoon Kim
 
도메인 객체의 생명주기
도메인 객체의 생명주기도메인 객체의 생명주기
도메인 객체의 생명주기ukjinkwoun
 
Machine Learning Foundations (a case study approach) 강의 정리
Machine Learning Foundations (a case study approach) 강의 정리Machine Learning Foundations (a case study approach) 강의 정리
Machine Learning Foundations (a case study approach) 강의 정리SANG WON PARK
 
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드SangIn Choung
 
Java script 기본과 jquery의 활용
Java script 기본과 jquery의 활용Java script 기본과 jquery의 활용
Java script 기본과 jquery의 활용정기 김
 
목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해Yong Hoon Kim
 
클린코드와 테스트코드
클린코드와 테스트코드클린코드와 테스트코드
클린코드와 테스트코드Herren
 
복잡한 오브젝트를 우아하게 처리하기
복잡한 오브젝트를 우아하게 처리하기복잡한 오브젝트를 우아하게 처리하기
복잡한 오브젝트를 우아하게 처리하기jgyuity1289
 

Similar to S66 goos-w6 (20)

Devon 2011-b-5 효과적인 레거시 코드 다루기
Devon 2011-b-5 효과적인 레거시 코드 다루기Devon 2011-b-5 효과적인 레거시 코드 다루기
Devon 2011-b-5 효과적인 레거시 코드 다루기
 
아꿈사.C++ api 디자인.20140315 a
아꿈사.C++ api 디자인.20140315 a아꿈사.C++ api 디자인.20140315 a
아꿈사.C++ api 디자인.20140315 a
 
애자일 프랙티스
애자일 프랙티스애자일 프랙티스
애자일 프랙티스
 
Cygnus unit test
Cygnus unit testCygnus unit test
Cygnus unit test
 
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
KSUG 스프링캠프 2019 발표자료 - "무엇을 테스트할 것인가, 어떻게 테스트할 것인가"
 
Effective java
Effective javaEffective java
Effective java
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기
 
테스트 기발 개발, TBD(Test based developement)
테스트 기발 개발, TBD(Test based developement)테스트 기발 개발, TBD(Test based developement)
테스트 기발 개발, TBD(Test based developement)
 
클린 코드 part2
클린 코드 part2클린 코드 part2
클린 코드 part2
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
테크데이 발표자료.pptx.pdf
테크데이 발표자료.pptx.pdf테크데이 발표자료.pptx.pdf
테크데이 발표자료.pptx.pdf
 
도메인 객체의 생명주기
도메인 객체의 생명주기도메인 객체의 생명주기
도메인 객체의 생명주기
 
Machine Learning Foundations (a case study approach) 강의 정리
Machine Learning Foundations (a case study approach) 강의 정리Machine Learning Foundations (a case study approach) 강의 정리
Machine Learning Foundations (a case study approach) 강의 정리
 
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
katalon studio 툴을 이용한 GUI 테스트 자동화 가이드
 
Java script 기본과 jquery의 활용
Java script 기본과 jquery의 활용Java script 기본과 jquery의 활용
Java script 기본과 jquery의 활용
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Tdd
TddTdd
Tdd
 
목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해목 오브젝트(Mock Object)의 이해
목 오브젝트(Mock Object)의 이해
 
클린코드와 테스트코드
클린코드와 테스트코드클린코드와 테스트코드
클린코드와 테스트코드
 
복잡한 오브젝트를 우아하게 처리하기
복잡한 오브젝트를 우아하게 처리하기복잡한 오브젝트를 우아하게 처리하기
복잡한 오브젝트를 우아하게 처리하기
 

S66 goos-w6

  • 1. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 s66 GOOS 20, 21, 22
  • 2. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장에서 다룰 내용 ‘왜’ 테스트 하기 어려운가? • 테스트를 작성하기 어려운 경우 • 테스트 주도 개발 • ‘테스트 악취’ 1. 불분명, 불안정한 테스트 2. 테스트하기 어려운 코드
  • 3. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 4. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 • 테스트 요구사항 T1 1. receiver 객체는 request를 여러번 받을 수 있다. 2. 다음 request 를 받을때 시간이 많이 지났음을 식별할 수 있어야 한다. #Test : 1
  • 5. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 • 구현 분석 • 싱글톤 객체인 System에서 now 인스턴스를 받는다. (new Date()) • firstDateIsDifferentFrom 은 Date 연산을 도와주는 메소드 (예시구현) #Test : 1 의존성을 가진 싱글톤 객체
  • 6. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 • Problem • 테스트를 수행하려면 너무 많은 시간이 걸린다. (= 어렵다) • Conclusion • Date 를 생성하는 방법을 제어해야 한다. • 새로운 객체를 도입해 receiver에게 전달해야 한다. #Test : 2
  • 7. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 #Test : 2 • 테스트 구현사항 • receiver 객체는 Clock 없이 생성할 수 없다. • Date를 생성하는 방법을 제어할 수 있다
  • 8. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 #Test : 2 • Solution • Date 의존성을 떼어냄 • Next Problem • Receiver 안에 Date 처리 로직이 남음 • Conclusion • clock 안으로 Date 처리 로직을 이동
  • 9. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 #Test : 3 • 테스트 구현사항 • receiver 객체 안에 날짜 비교 로직을 제외하고 싶다. • 구현한 clock 이 날짜 비교 로직을 갖게 하자.
  • 10. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 #Test : 3 • 구현 분석 • receiver 객체는 더 이상 날짜 구분 로직을 포함하지 않아도 된다. • 날짜 관련 구현을 전부 위임하면? 날짜 저장 구현도 위임하자
  • 11. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 #Test : 4 • 테스트 요구사항 T1` • Receiver에게 request를 보내고 만료되었는지 확인한다. 테스트 이름도 바뀜
  • 12. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 #Test : 4 • 구현 분석 • Receive 객체에는 시간을 저장하는 로직도 남아있지 않게 되었다.
  • 13. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 객체는 객체 범위 내에서 관리되는 값이나, 명시적으로 전달되는 값과 인스턴스를 다뤄야 한다. 객체의 동작이 객체 밖의 컨텍스트에 영향을 받는다면 - 외부 컨텍스트 조건에 따라 테스트를 작성해야 하고 - 객체를 컴포넌트로 구분해서 쓰기 어려워진다
  • 14. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 15. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.2 • 보조 로깅 • 시스템을 감시하기 위한 목적 • 시스템 관리자, 운영자가 보고 관리하는 로그 • 제품에 포함되어 테스트 주도 적이어야 한다. • 로그를 분석하는 스크립트나 관 리 도구를 보호하기 위해 • 진단 로깅 • 개발자가 내부 이해를 위한 목적 • 개발자가 개발 중에만 보는 로그 • 제품에 포함되어서는 안된다. • Q : 테스트 주도적일 필요 있을까? 없다. 제품에 포함하지 않기로 합의한 메세지이기 때문
  • 16. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.2 • 구현 분석 • 일반적인 로깅 구현 • 역할 분석 • Location을 처리하는 일 • 정보를 출력하는 일 단일 책임 원칙 위반 Q: 정보를 출력하는 일이 중복될 것이라는 예상? Q: logger.info(…) 내용은 “구현”인가 “의도”인가?
  • 17. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.2 • support : 보조 객체 • 로거, 메세지 버스, 팝업 창 등.. • 변화점 • 목 객체를 활용하여 테스트 가능 • 코드가 의도하는 바를 표현함 • “구현”이 아닌 “의도”를 전달하자 • 일관성 유지, 재사용 촉진 테스트를 작성 중 실천 양식 잘 모르는 예외를 처리할 수 없어 로 그만 남기고 넘어가지 않는다
  • 18. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.2 로깅은 기능이다 로그를 캡슐화하여 관리하는 것은 로그가 넘쳐 실패하는 제품으로 나아가는걸 막아준다. 로거를 대상으로 테스트할 수 없다면 설계가 명확하지 않았기 때문이다. 실제 운영되는 서비스에서 중요한 의미로 쓰이지 않는 로그때문에 중요한 로그를 찾지 못한걸 경험이 누구에게나 있을 것이다.
  • 19. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 20. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.3 p.272 • Problem • CDPlayer와 MusicCentre간에 관계가 암시적으로 남는다.
  • 21. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.3 • Problem • MusicCentre가 CDPlayer에 너무 많이 접근할 수 있음 • Solution • MusicCentre가 쓰는 메소드를 ScheduleDevice 인터페이스로 묶는다 • SOLID : Interface Segregation Principle (인터페이스 분리 원칙) MusicCentre 가 쓰는 메소드
  • 22. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.3 구상 클래스에 대한 목 객체 적용 한꺼번에 변경할 수 없는 레거시 코드를 다루는 경우 전혀 변경할 수 없는 서드 파티 코드를 다룰때 참고 : 19장 257p 스스로 규칙을 어기는 것인가? 단, 클래스의 내부 기능을 재정의 해서는 절대 안 된다. 재정의한 구현이 테스트에 묶여버린다. 우리는 테스트에 “구현” 전달을 지양하고, “의도” 전달을 지향하기 때문. 테스트로 부터의 피드백 – 테스트에서 닿지 않는 구조는 클래스를 더 작게 분할할 시점이다.
  • 23. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 24. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.4 • Problem • Video 인터페이스를 만들 필요가 보이지 않는다. • To-be • 값 객체로 바꾸자.
  • 25. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.4 값에 목 객체를 적용하지 말라 값을 표현하기 위해서는 인스턴스를 적절하게 생성하서 사용한다. 책에서 제안하는 휴리스틱 1. 해당 클래스의 값이 불변적이다. 2. 해당 타입의 인터페이스를 구현하는 클래스의 이름이 모호하다. 값의 인스턴스를 생성해서 사용하기 복잡한 경우를 뒤에서 다룬다.
  • 26. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 27. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.5 • Problem • 생성자가 너무 크다 • Solution • 일부 인자를 묶어 새로운 클래스로 대체 (unpacker, counterPartyFinder)는 생성자에 정해지고 짝으로 움직인다.
  • 28. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.5 • Problem • 생성자가 너무 크다 • Solution • 일부 인자를 묶어 새로운 클래스로 대체 (locationFinder, domesticNotifier, importedNotifier) 는 같이 생성되고 세트로 움직인다.
  • 29. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.5 • 구현 분석 • MessageProcessor의 책임이 줄어듦. • input, process, output 세 객체만 남는다. • 코드가 더 명료해짐 • 테스트 하기 쉽다.
  • 30. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.5 비대한 생성자 MessageUnpacker, MessageDispatcher와 같은 암시적인 컴포넌트를 뽑아내는 두 가지 조건. 1. 늘 함께 사용되고 수명이 같은 인자일때. 2. 새롭게 묶어낸 개념을 설명할 더 나은 이름이 있을때. 이제 우리는 변화를 통합하기 훨씬 쉬워졌다. - 객체가 유연해졌다.
  • 31. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 32. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.6 • Problem • 생성자가 너무 크다 • 관련없는 책임이 많이 포함되어 있다. • 관련이 없는 기능들이 같이 묶여있다. • 너무 방대한 클래스다. • Solution • 나눠야 한다. • 서로 관련 없는 테스트가 많이 생긴다
  • 33. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.6 혼동되는 객체 테스트 간에 서로 아무런 관련이 없다면 객체를 쪼갤 수 있다. ‘레거시 코드 활용 전략’ – 내 프로젝트 군살 빼기
  • 34. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 35. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.7 • 요구사항 • 경주 게임. • 차량을 설정하여 누가 경주에 이기는지 확인한다. • Problem • 생성자가 너무 크다. • Solution • 의존성을 가지고 있는 모든 객체가 전부 꼭 필요한가?
  • 36. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.7 • 구현 분석 • 객체들을 기본값으로 초기화 했다. • 생성자가 줄어들었다. • 나머지 객체들을 인터페이스로 변경할 수 있게 되었다.
  • 37. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.7 너무 많은 의존성 20.5, 20.6, 20.7 은 하나의 목표를 위해 여러가지 방법을 제안하고 있음. - 생성자의 크기를 줄인다. Q : 왜 생성자를 줄여야 할까? - 테스트에 의도를 파악하기 힘들게 만들고 - 변화에 유연하지 못하게 만들고 - 객체가 앞으로 계속 늘어날 수 있고 …
  • 38. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20장 • 20.1 대체할 수 없는 객체에 대해 목 객체를 적용해야 한다 • 20.2 로깅은 기능이다 • 20.3 구상 클래스에 대한 목 객체 적용 • 20.4 값에 목 객체를 적용하지 말라 • 20.5 비대한 생성자 • 20.6 혼동되는 객체 • 20.7 너무 많은 의존성 • 20.8 너무 많은 예상 구문
  • 39. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.8 • Problem • 테스트가 무엇을 테스트 하고자 하는지 알기 어렵다. • 중요도가 파악이 되지 않는다.
  • 40. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.8 • 구현 분석 • thirdParty 만 영향을 미침 • 영단어 설명
  • 41. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.8 너무 많은 예상 구문 너무 많은 예상 구문은 테스트를 읽기 어렵게 만든다. 예상 구문이 너무 많은 경우는 테스트의 단위가 너무 커서 예상할 내용이 너무 많거나 객체 상호 작용을 너무 많이 직접 예상하기 때문이다. - 테스트의 규모가 너무 커지지 않도록 항상 주의 해야 한다.
  • 42. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 20.9 테스트가 우리에게 말해주는 것 (테스트로 얻는 피드백) 객체에 담고 있는 내용을 객체 내부로 한정할 수 있으면 콘텍스트에 독립적인 객체가 완성된다. 이름은 도메인 정보를 담는다. - 객체의 구현에 대해 서술하지 않고 객체망 의 상호 작용을 담는다. - 고도의 추상화를 포함하고, 객체에 “의도”를 이름이 표현한다. 데이터 대신 행위를 전달하라 - 객체에 “의도”를 전달한다. (테스트는 동작에 추상적이고, 객체는 값에 추상적이다) 테스트는 테스트와 그 내부 품질에 대한 피드백을 꾸준히 우리에게 말한다. - 테스트에서 악취가 발견되면 즉시 수정하라.
  • 43. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21장에서 다룰 내용 읽기 쉬운 테스트 작성 가이드
  • 44. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21장 • 21.1 테스트 이름은 기능을 기술한다 • 21.2 정규 테스트 구조 • 21.3 테스트 코드의 능률화 • 21.4 단정과 예상 구문 • 21.5 리터럴과 구문
  • 45. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.1 • 테스트 요구사항 1 • List는 항목이 추가된 순서대로 항목을 보관한다. • 서술어 : 보관한다 - holds • 목적어 : 항목 - Items • 주어 : List • 수식어구 : 항목이 추가된 순서대로 • holdsItemsInTheOrderTheyWereAdded • 테스트 요구사항을 그대로 이름으로 옮긴다
  • 46. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.1 • 테스트 요구사항 2 • List는 동일한 항목에 대해 여러 개의 참조를 보관할 수 있다. • 서술어 : 보관할 수 있다 – can hold • 목적어 : 항목 - Multiple References • 주어 : List • 수식어구 : 동일한 항목에 대해 • canHoldMultipleReferencesToTheSameItem • 테스트 요구사항을 그대로 이름으로 옮긴다
  • 47. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.1 • 테스트 요구사항 3 • List는 보관 중이지 않은 항목을 제거할 때 예외를 던진다. • 서술어 : 던진다 – throws • 목적어 : 항목 – an Exception • 접속사 : 때 – when • 종속절 - 서술어 : 제거할 – remove • throwsAnExceptionWhenRemovingAnItemDoesntHold • 테스트 요구사항을 그대로 이름으로 옮긴다
  • 48. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.1 테스트 이름은 기능을 기술한다 테스트 이름은 예상하는 결과, 객체의 행동, 시나리오의 동기를 서술해야 한다. 실천 양식 - 개발 기간 동안 정기적으로 테스트 문서를 읽으려는 노력을 해야한다.
  • 49. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21장 • 21.1 테스트 이름은 기능을 기술한다 • 21.2 정규 테스트 구조 • 21.3 테스트 코드의 능률화 • 21.4 단정과 예상 구문 • 21.5 리터럴과 구문
  • 50. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.2 1. 준비 : 테스트의 콘텍스트 2. 실행 : 테스트 행위 촉발 3. 검증 : 예상되는 효과 검사 4. 정리 : 잔존 상태 정리 21.1 • 예상하는 결과 • 객체의 행동 • 시나리오의 동기 검증 - 결과 / 실행 – 행동 / 준비 – 동기 정리는 구현의 일부
  • 51. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.2 정규 테스트 구조 준비, 실행, 검증 정리 단계로 나누어 진다.
  • 52. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.3 instruments 컬렉션에 Instrument 항목중에서 strikePrice가 81보다 큰 항목이 하나라도 있는지 검사. assertThat(instruments,hasItem(instrumentWithPrice(greatherThan(81)))); 쉽게 의도를 파악할 수 있는 단정문으로 검사한다.
  • 53. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.3 p293 • 테스트 요구사항 • 매크로 적용의 결과가 맞는지 확인 Exception이 test 밖으로 빠져나갈 수 있도록 둔다.
  • 54. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.4 • 테스트 요구사항 • 스나이퍼 식별자(ID)를 확인한다 • 메세지를 확인한다. • 세번째 인자로는 어느 객체가 와도 무방(-any)하다.
  • 55. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.4 assertFalse(“end date”, first.endDate().equals(second.endDate())); assertThat(”end date”, first.endDate(), not(equalTo(second.endDate()))); 부정문 not을 이용하면 코드가 더 명시적으로 보인다. assertFalse보다 위와 같이 쓰는걸 권장한다.
  • 56. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 21.5 테스트 코드에는 필연적으로 리터럴 값이 많이 포함된다. 테스트는 값에 구체적이기 때문에 변수에 이름을 부여해서 사용하자.
  • 57. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22장에서 다룰 내용 테스트를 위해 필요한 객체를 생성하고 싶을때마다 우리는 생성자 인자를 모두 직접 작성해야 한다. - 또 이 객체를 생성하는 코드가 많아지면 테스트를 읽기 매우 어려워진다. - 생성자 인자나 구조를 변경하는 순간 여러 테스트 가 깨지게 된다. 이 문제를 해결해서 복잡한 내용을 담은 테스트 코드 를 읽기 쉽게 만들어야 한다.
  • 58. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.0 • object mother Pattern (객체 모체 패턴) • pros • 구조를 만드는 코드에 이름을 부여함 • 재사용할 수 있다 • cons • 데이터 변화에 대처하기 힘들다
  • 59. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22장 • 22.1 테스트 데이터 빌더 • 22.2 비슷한 객체 생성 • 22.3 빌더 조합 • 22.4 팩터리 메소드를 이용한 도메인 모델 강조 • 22.5 사용 시점에서 중복 없애기
  • 60. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.1 • 객체 생성 Order order = new OrderBuilder(). build(); • 의미 있는 값 지정 new OrderBuilder(). fromCustomer(…).build(); new CustomerBuilder(). withAddress(new AddressBuilder…) .build()
  • 61. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22장 • 22.1 테스트 데이터 빌더 • 22.2 비슷한 객체 생성 • 22.3 빌더 조합 • 22.4 팩터리 메소드를 이용한 도메인 모델 강조 • 22.5 사용 시점에서 중복 없애기
  • 62. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.2 p.300 • 비슷한 객체를 생성하는 일이 있을때 코드를 줄이는 방법 중복된 데이터를 넣는 중간 빌더 상태를 만들어서 각각 사용한다.
  • 63. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.2 301p • builder를 이용해 또 다른 builder를 구현할 수 있게 한다. 상태를 중복하는 메서드를 추가하여 데이터를 만들 수 있다.
  • 64. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22장 • 22.1 테스트 데이터 빌더 • 22.2 비슷한 객체 생성 • 22.3 빌더 조합 • 22.4 팩터리 메소드를 이용한 도메인 모델 강조 • 22.5 사용 시점에서 중복 없애기
  • 65. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.3 302p • builder를 이용해 또 다른 builder를 구현할 수 있게 한다. 상태를 중복하는 메서드를 추가하여 데이터를 만들 수 있다.
  • 66. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22장 • 22.1 테스트 데이터 빌더 • 22.2 비슷한 객체 생성 • 22.3 빌더 조합 • 22.4 팩터리 메소드를 이용한 도메인 모델 강조 • 22.5 사용 시점에서 중복 없애기
  • 67. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.4 302p • method Overloading을 이용해서 with 구문을 만든다. • 단, String 타입처럼 중복된 타입에 대해서는 올바르게 동작하지 않는다. • 왜? 하나의 타입에 두 개 이상의 멤버인 경우 선택할 수 없기 때문.
  • 68. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22장 • 22.1 테스트 데이터 빌더 • 22.2 비슷한 객체 생성 • 22.3 빌더 조합 • 22.4 팩터리 메소드를 이용한 도메인 모델 강조 • 22.5 사용 시점에서 중복 없애기
  • 69. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.5 • 요구사항 • 왼쪽 코드는 테스트에 필요한 값 을 생성하는 코드이다. 이 코드의 중복을 찾아 제거하자
  • 70. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 22.5 • 테스트 코드의 중복을 제거하 는데 성공하였다.
  • 71. s66 테스트 주도 개발로 배우는 객체 지향 설계와 실천 감사합니다. 삼가 고인의 명복을 빕니다.