
JCommon 라이브러리
위 링크에서 JCommon 라이브러리를 제공한다. 이 중 org.jfree.date라는 패키지가 있는데, 이 중 SerialDate라는 클래스를 리팩터링 해본다.
SerialDate는 날짜를 표현하는 자바 클래스이다. 하지만 자바는 이미 java.util.Date, java.util.Calendar와 같은 클래스를 제공하는데, 왜 하필 SerialDate를 써야할까?
클린코드 교재의 473쪽 B-2의 코드를 참고하고 진행한다.
우선, 클로버(코드커버리지 분석도구)를 통해 SerialDateTests 클래스를 검사한다. 검사결과 이 클래스는 50%정도만 테스트를 진행하고 있다는 사실을 확인할 수 있다. 따라서 더 높은 코드 커버리지를 위해 단위 테스트 케이스를 구현하고, 해당 단위 테스트에서 실패한 경우(주석 처리한 부분)를 성공시킬 수 있도록 원본 클래스를 리팩터링한다.
equalsIgnoreCase로 변경if ((result < 1) || result > 12) {
result = -1;
for (int i = 0; i < maonthNames.length; i++) {
if (s.equalsIgnoreCase(shortMonthNames[i])) {
result = i + 1;
break;
}
if (s.equalsIgnoreCase(monthNames[i])) {
result = i + 1;
break;
}
}
}
getFollowingDayOfWeek 메서드 버그 표시됨if(baserDOW >= targetWeekday) { int delta = targetDOW = base.getDayOfWeek();
int positiveDelta = delta + 7;
int adjust = positiveDelta % 7;
if (adjust > 3)
adjust -= 7;
return SerialDate.addDays(adjust, base);weekInMonthToString, relativeToString 오류 문자열 대신 IllegalArgumentException으로 테스트 통과 처리위와 같이 변경한 SerialDate는 모든 테스트 케이스를 통과한다. 이제 SerialDate를 올바로 고쳐보자. 코드 변경 시 마다 JCommon 단위테스트와 자체 단위테스트를 모두 실행하였다.
dateFormatSymbols)와 정적 메서드(getMonthNames, isLeapYear, lastDayOfMonth)는 새 클래스로 이동DayDate.java로 이동Month.make를 Month.fromInt로 변경. 다른 enum도 똑같이 변경하고 모든 enum에 toInt() 접근자를 생성, index 필드를 private로 정의.correctLastDayOfMonth라는 새 메서드를 통해 제거Month.JANUARY.toInt() 혹은 Day.SUNDAY.toInt()로 적절히 변경. SpreadsheetDate 코드를 살펴보고 알고리즘을 조금 손봤다.위 처럼 수정 결과, DayDate 코드 커버리지는 84.9%로 감소하였다. 테스트하는 코드가 줄어서가 아니라 클래스 크기가 작아지는 바람에 테스트하지 않는 코드의 비중이 커졌기 때문이다. 테스트하지 않는 코드는 너무 사소해 테스트할 필요도 없는 코드만 남았다.