링크
생소한 용어
스크래치 리팩터링 - 리팩터링 후 잘못된 점을 찾기 위해 VCS에서 별도의 브랜치를 만든 이후, 맘대로 리팩터링함
- 리팩터링 이후, 영향성을 파악하고 해당 브랜치를 버림
- 코드의 동작을 이해할 수 있는 좋은 방법
생소한 인텔리제이 활용
- 메서드 추출 -> if / else로 감싸기 -> 메서드 인라인화 -> 제거될 수 있는 조건문 제거하기
- if / else / else if 병합
- push down members -> 커버리지 조사하면서, 미사용 메서드 제거
- switch 문으로 변경
[1단계] 복잡한 레거시 코드에 테스트 코드를 추가하자.
- 예제 코드는 조건문에 따라 코드 블록들이 존재하고, 조건문이 여러 곳에 산재해서 섞여 있음
- 중첩된 조건문이 매우 많고, 테스트하기 어려움. 너무 싫어
- 이런 코드를 이해하기 위해서 많은 시간을 투자하려는 경향이 있음
- 이럴 경우에는,
스크래치 리팩터링을 시도해볼만할지도?
복잡한 레거시 코드에 테스트를 추가하는 3가지 기법
- Characterization Test
- Approval Test
- Mutation Test
Characterization Test
- 기존 동작 유지에 필요한 테스트
- 레거시 코드에서 무엇을 하는지가 중요하지, 어떻게 동작하는지는 중요하지 않음
- 어떻게 동작하는지에 대한 테스트 작성은 버그를 찾는데에 불과함
- 무엇을 하는지에 대한 테스트를 Characterization Test(문서화 테스트)라고 함
Approval Test
- 단위 테스트에서 검증은 어려울 수 있음
- approval test는 결과의 스냅샷(텍스트)을 만들고, 변경되지 않았음을 검증해 단위 테스트에서 검증을 단순화함
Mutation Test
- 고의로 버그를 유발(프로덕션 코드를 약간 수정)하고 테스트가 해당 버그를 잡아내는지를 확인하여 테스트의 완전성을 검증하는 기법
- 이렇게 프로덕션을 약간 변경하는 테스트를 돌연변이 테스트(mutation test)라고 함
- 100% 커버리지를 갖는 경우도 테스트가 실패하지 않고 성공하는 경우가 있음..!
- 코드를 실행하는 것과 코드를 테스트하는 것은 동일하지 않기 때문임
- PIT
- PIT는 런타임에 프로덕션 코드에 코드를 삽입해 돌연변이 테스트를 발생시킴
- 살아남은 돌연변이 테스트가 있다는 것은 100% 커버리지를 갖는 테스트가 있다고 해도, 결함을 완전히 방지하지 못하다는 것을 의미
- changed conditional boundary :
a < 50 -> a <= 50 - negated conditional :
a < 50 -> a >= 50
[2단계] 리팩터링을 수행하자.
문제점
- 3개의 name에 대해 조건문이 산재해 있어서 가독성이 떨어짐
- 향후 새로운 name이 추가되거나 기존 name에 대한 행위가 변경될 때, 한 곳이 아니라 관련된 곳을 잘 찾아서 변경해야 하는 어려움이 있음
리팩터링
lift up conditionals란 길고 복잡한 조건문을 조작해, 특정 조건과 관련된 코드 블록을 그룹핑하는 기법 - 산재된 조건문을 한 블록으로 묶어서 다형성으로 풀어냄
- 다형성을 적용하려면, 다형적으로 생성하는 로직을 먼저 만드는 것이 좋을 수 있음
- 순서
lift up conditionals로 조건문 그룹핑 - switch 문으로 개선
- item 내부로 메서드 이동
- 정적 팩터리 메서드 생성
- 하위 클래스 생성
- push down members 수행
- 커버리지 분석하며, 미사용 코드 제거