도전 TDD! - 테스트 주도 개발의 패턴(3)
테스트 주도 개발 패턴 30장~32장
6/14/2024, 8:48:00 PM
30장. 디자인 패턴
우리는 언제나 완전히 다른 문제들을 해결하는 것 같지만 대다수는 사용하는 도구에 의해 생기는 것이지 직면한 외부의 문제 때문에 생기는 것이 아니다(Alexander, Christopher. 1970)
커맨드
- 간단한 메서드 호출보다 복잡한 형태의 계산 작업에 대한 호출이 필요하다면, 계산 작업에 대한 객체를 생성하여 이를 호출해라
- 생성할때 계산에 필요한 모든 매개 변수들을 초기화하고 호출할 준비가 되면 해당 객체의 메서드 호출. like Runnable interface
값 객체
- 여기저기 공유되어야 하는 객체가 있다면, 상태가 절대 변하지 않고 연산이 발생하면 항상 새로운 객체를 반환하는 객체를 만들어라.
- 교차하고 합해지는 기하학적 모양들, 숫자와 함께 그 단위가 따라다니는 단위값, 기호대수학 등 대수학 같이 보이는 상황이라면 항상 시도해보는 편.
- 가독성, 디버깅 모두 쉽게 만들어준다
널 객체
- 객체의 특별한 상황을 표현하고자 한다면, 그 특별한 상황을 표현하는 새로운 객체를 만들어라. 그리고 그 객체가 정상적인 상황을 나타내는 객체와 동일한 인터페이스를 구현하도록 해라.
if(instanceA != null)
과 같은 코드가 계속 중복될때와 같은 상황에 유용.
fun getHandler() : HandlerInterface {
return if(handler == null ) EmptyHandler() else handler
}
class EmptyHandler() : HandlerInterface {
fun handle() {
// do nothing
}
}
템플릿 메서드
- 작업 순서는 변하지 않지만 각 작업 단위에 대한 미래의 개선 가능성을 열어두고 싶다면, 다른 메서드들을 호출하는 내용으로만 이루어진 메서드를 만든다.
- 프로그래밍에는 고전적인 순서들로 가득하다. (ex 입력/처리/출력)
- 초기 설계부터 도입하는 것 보다는 경험에 의해 발견되는 것이 좋다. 이 부분은 순서일 뿐이고, 이 부분이 상세한 구현에 대한 내용이구나!
플러거블 객체
- if-else 로 변이를 표현하지 말자. 명시적인 의사 결정 코드는 모든 소스 전역으로 확대된다.
- 인터페이스를 만들고 구현체로 변이를 다루라는 뜻
팩토리 메서드
- 새 객체를 만들 때 유연성을 원하는 경우, 생성자 대신 일반 메서드에서 객체를 생성해라.
- 메서드가 객체를 생성한다는 사실을 기억해야 한다는 단점 존재(크게 와닿지는 않았음)
컴포지트
- 하나의 객체가 다른 객체 목록의 행위를 조합한 것처럼 행동하게 하려면, 객체 집합을 나타내는 객체를 단일 객체에 대한 임포스터로 구현하라.
- 집합을 나타내는 객체가 단일 객체와 동일한 인터페이스를 구현
수집 매개 변수
- 여러 객체에 걸쳐 존재하는 오퍼레이션의 결과를 수집하고 싶다면, 결과가 수집될 객체를 만들고 각 오퍼레이션의 매개 변수로 추가하라.
31장. 리팩토링
시스템의 설계를 작은 단계를 통해 변화 시키는 방법. TDD 에서 리팩토링은 프로그램의 의미론은 바꾼다는 점에서 전통적인 리팩토링의 의미와는 다르다. 관측상의 동치성, 즉 테스트 코드가 모두 통과한다는(=기대 동작이 변하지 않았다는) 확신이 있기 때문에 가능
차이점 일치시키기
- 비슷해 보이는 두 코드 조작을 합치고 싶다면, 두 코드가 단계적으로 닮아가게끔 수정하라. 완전히 동일해지면 둘을 합친다.
- 한번에 하지말고 조금씩 하라는 뜻. 반복문->조건문->메서드->클래스 이런 단계 처럼..
변화 격리하기
- 객체나 메서드의 일부만 바꾸고 싶다면, 일단 바꿔야할 부분을 격리하라.
데이터 이주시키기
- 표현 양식을 변경하고 싶다면, 일시적으로 데이터를 중복시켜라.
- 두가지 포멧을 모두 다루도록 해놓고 하나를 지우라는 것.
메서드 추출하기
- 길고 복잡한 메서드를 읽기 쉽게 만들고 싶다면, 긴 메서드의 일부를 별도의 메서드로 분리하고 이를 호출하게 하라.
메서드 인라인
- 너무 꼬여있거나 산재한 제어 흐름을 단수화 하고 싶다면, 메서드를 호출하는 부분을 호출될 메서드의 본문으로 교체하라
인터페이스 추출하기
- 인터페이스를 만들고 기존 클래스가 구현하게 하고, 타입 선언부에서 클래스 이름 대신 인터페이스 이름을 사용해라.
메서드 옮기기
- 메서드를 원래 있어야할 장소로 옮기고 싶다면, 어울리는 클래스에 메서드를 추가하고 그것을 호출하라
- 한 메서드에서 다른 객체에 하나 이상의 메시지를 보내는 것을 보면 언제나 의심하라! 메서드를 옮겨야할 타이밍
메서드 객체
- 여러 개의 매개 변수와 지역 변수를 갖는 복잡한 메서드는, 메서드를 꺼내서 객체로 만들어라.
- 메서드 추출하기를 적용할 수 없는 코드를 간결하게 만들때 유용
32장. TDD 마스터하기
TDD를 적용하는 과정에서 숙고해볼 수 있는 질문들. 다음은 그 중 인상깊었던 내용들이다
- 설계 문제가 있음을 보여주는 테스트들의 특징
- 긴 셋업 코드
- 셋업 중복
- 실행이 오래걸리는 테스트
- 깨지기 쉬운 테스트 : 예상치 못하게 실패하는 테스트
- TDD를 하면 발생하지 않은 변주 종류는 잘 표현하지 못할지라도, 발생하는 변주 종류들, 그것들을 잘 표현하는 프레임워크를 만들게 해준다.
- 테스트를 얼마나 작성해야 하나? 테스트는 깊이 신뢰할 수 있는 코드를 만들고자 하는 목적에 대한 수단일 뿐이다. 구현에 대한 지식이 신뢰할 만 하다면 테스트를 작성하지 않을 것.
- TDD는 더 나은 코드를 작성한다면 좀더 성공할 것이라는, 매력적일 정도로 나이브한 해커적인 가정에 근거한다.
- 적당한 수준의 엔지니어링만으로도 충분히 프로젝트가 성공하게 할 수 있다.
- 그러나 TDD는 업계에서 통용하는 수준보다 훨씬 적은 수의 결함과 깨끗한 설계를 가능하게 한다. TDD==선을 실행하면서 잘 사는 방법
- 프로잭트가 커지면 커질수록 개발자들은 여러 곳에서 나는 냄새 때문에 불안해지고 실증을 느끼게 된다. TDD를 하면 시간이 지나도 처음 프로젝트를 할때처럼 (혹은 조금 더) 좋은 느낌을 가지고 프로그래밍 할 수 있다.
- 완벽하게 사리에 맞는 설계 아이디어가 결국은 틀린 것으로 판명난다. 그냥 시스템이 무슨 일을 할지 생각하고 나중에 설계가 알아서 정해지도록 하는 것이 더 낫다.
소감
3부 테스트 주도 개발의 패턴을 모두 다 읽었다. 저자의 말대로 3부를 먼저 읽음으로써 TDD를 시도하며 직접 이곳저곳 해매이기 전에 TDD의 구체적인 가이드를 확인하였다. 이제 실천할 차례다. 1,2부로 돌아가 차근차근 체험해보자.
댓글
* 작성 이후에 수정/삭제 할 수 없어요!
아직 작성된 댓글이 없습니다.