[Clean Code] 16장 SerialDate 리펙터링
16장 SerialDate 리펙터링
JCommon 라이브러리와 SerialDate 클래스를 알아보며 전문가의 입장에서 깨끗한 코드 작성 방법을 알아볼 수 있는 챕터.
이 챕터( 책 )에서 수행하는 분석은 악의나 자만과는 거리가 멀다는 것을 명심하자.
비판이 있어야 발전이 가능하다.
다른 직업들도 하고있는 것들이다.
프로그래머들도 알아야한다.
코드 리뷰는 우리 모두가 편안하게 여겨야할 행동이고 다른 사람이 내게 해준다면 감사히 반겨야 할 행동이다.
목차
- 첫째, 돌려보자
- 둘째, 돌려보자
16-1. 첫째, 돌려보자
SerialDateTests는 단위 테스트 케이스 몇개를 포함하지만 모든 경우를 점검하지 않고 있다.
테스트 코드에서 전혀 실행하지 않는 코드도 존재한다.
테스트 커버리지는 대략 50% 정도이다.
클래스를 철저히 이해하고 리펙터링하려면 높은 테스트 커버리지가 필요하다
.
경계 조건 오류가 존재하며 논리적 오류로 인하여 결코 실행되지 않는 코드도 존재한다.
16-2. 둘째, 돌려보자
앞서 짜여진 코드를 보며 리팩터링을 진행한다.
주석
- 필요한 주석: 법적인 정보는 필요하다.
- 불필요한 주석: 지금은 필요하지 않는 변경 이력은 형상관리 프로그램에서 제공하므로 삭제
import문 간결화
- import문은 java.text와 java.util로 줄여도 된다.
javadoc 주석
여러 언어를 하므로 통일된 모임새를 맞추기 어렵다.
주석 전부를<pre>로 감싸게 되면 모양이 유지된다.
서술적인 이름 사용
- 일련번호라는 용어는 날짜보다 제품 식별 번호에 더 적합하다.
- SerialDate라는 이름은 구현을 암시하지만 실상은 추상 클래스이다.
- 따라서 이름의 추상화 수준이 올바르지 않다.
- 그냥 Date가 좋지만 이미 많이 존재 하므로 DayDate로 결정했다.
상수 열거형 보다 Enum 사용
MonthConstants를 상속하고 있는데 static final 상수 모듬에 불과하다.
MonthConstatns를 Enum으로 변경하여 사용하는 것이 마땅하다.
serialVersionUID
- serialVersionUID변수는 직렬화를 제어한다.
- 이 변수 값을 변경하면 이전 소프트웨어 버전에서 직렬화한 DayDate를 더 이상 인식하지 못한다.
- 역직렬화 시에 InvaildClassException이 발생한다.
- serialVersionUID 변수를 선언하지 않으면 컴파일러가 자동으로 생성하지만 모듈 변경시 자동으로 달라진다.
- 문서에서는 직접 선언을 권장하지만 저자는 컴파일러의 자동 제어가 훨씬 더 안전하다 여긴다.
- serialVersionUID를 변경하지 않아 생기는 괴상한 오류를 디버깅하는 것보다 차라리 InvaildClassException을 디버깅하는 편이 훨씬 나으니까
- (이 책을 검토한 여러명이 반론을 제기 했으며 직렬화 ID를 직접 제어하는 것이 낫다고 주장함)
- 저자는 이 의견도 타당하다고 생각한다.
- 따라서 특정 버전에서 직렬화한 클래스를 다른 버전에서 복원하지 않는 편이 안전하다.
변수 위치 올바르게 변경
- 책임이 있는 클래스와 관계없는 변수는 제거하거나 관련 책임이 있는 클래스로 옮겨야 한다.
기반 클래스와 파생 클래스
- 일반적으로 기반 클래스( 부모 클래스 )는 파생 클래스( 자식 클래스 )를 몰라야 바람직하다.
- 추상클래스는 구체적인 구현 정보를 포함할 필요가 없다.
- abstract factory 패턴을 적용해 객체를 생성하도록 한다.
접근 제한자 변경
- 내부에서만 사용하고 외부로 공개할 필요가 없는 경우 public → private으로 변경
불필요한 final 키워드 제거
- 인수와 변수 선언에서 final 키워드 제거
- 실질적인 가치는 없으면서 코드만 복잡하게 만든다고 판단했기 때문이다.
- 로버트 시몬스는 코드 전체에 final을 사용하라고 권장한다.
- ( 저자와 상반되는 의견이다. )
중첩 if문 통합
- if문이 중첩되어 나올 경우 논리 연산자를 이용해 하나로 만든다.
테스트 케이스에서만 호출한다면 제거
- 일력읜 리펙터링 작업은 나름대로 우아했지만 실제로 해당 메서드를 사용하는 코드는 방금 수정한 테스트 케이스가 유일했다.
- 그래서 저자는 테스트 케이스를 삭제했다.
물리적 의존성과 논리적 의존성
- 물리적 의존성은 없지만 논리적 의존성이 존재하는 경우가 있다.
- 무언가 구현에 논리적으로 의존한다면 물리적으로도 의존해야 마땅하다.
결론
이번 챕터에서 serialDate 객체를 탐험하며 보이스카우트 규칙을 따랐다.
체크아웃한 코드보다 좀 더 깨끗한 코드를 체크인하게 되었다.
시간은 걸렸지만 가치있는 작업이며 결과적으로 테스트 커버리지 증가, 버그 수정, 코드 길이를 줄이고 코드가 명확해졌다.
다음 차례의 보이스카우트는 우리보다 코드를 좀 더 쉽게 이해하리라.
결과적으로 우리보다 다음 차례의 보이스카우트가 더 쉽게 개선할 것이다.