16. SerialDate 리팩터링

프라이마리모·2025년 6월 30일

Clean Code

목록 보기
15/15
post-thumbnail

JCommon 라이브러리
위 링크에서 JCommon 라이브러리를 제공한다. 이 중 org.jfree.date라는 패키지가 있는데, 이 중 SerialDate라는 클래스를 리팩터링 해본다.

SerialDate는 날짜를 표현하는 자바 클래스이다. 하지만 자바는 이미 java.util.Date, java.util.Calendar와 같은 클래스를 제공하는데, 왜 하필 SerialDate를 써야할까?

첫째, 돌려보자

클린코드 교재의 473쪽 B-2의 코드를 참고하고 진행한다.
우선, 클로버(코드커버리지 분석도구)를 통해 SerialDateTests 클래스를 검사한다. 검사결과 이 클래스는 50%정도만 테스트를 진행하고 있다는 사실을 확인할 수 있다. 따라서 더 높은 코드 커버리지를 위해 단위 테스트 케이스를 구현하고, 해당 단위 테스트에서 실패한 경우(주석 처리한 부분)를 성공시킬 수 있도록 원본 클래스를 리팩터링한다.

  • 23~63행 주석부분 통과하도록 수정
    • SerialDate 설계 상 불통이 옳으나, 저자 기준 통과해야 함
    • 대소문자 구분 없이 모두 통과해야할 것으로 추정
      -> 259행, 263행 equalsIgnoreCase로 변경
  • 32행, 45행 주석 유지
    • 'tues', 'thurs' 약어 지원 여부 불분명
  • 153~154행 불통 -> 통과해야함
  • 163~213행 stringToMonthCode 메서드 수정
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;
        }
    }
}
  • 318행 : 672행의 getFollowingDayOfWeek 메서드 버그 표시됨
    • 메서드 버그 수정 if(baserDOW >= targetWeekday) {
  • 719행 실행 오류 : 718행 if문 항상 거짓으로 처리됨
    • 버그 수정
    		int delta = targetDOW = base.getDayOfWeek();
    		int positiveDelta = delta + 7;
    		int adjust = positiveDelta % 7;
    		if (adjust > 3)
      	adjust -= 7;
    		return SerialDate.addDays(adjust, base);
  • 417행, 429행 : weekInMonthToString, relativeToString 오류 문자열 대신 IllegalArgumentException으로 테스트 통과 처리

둘째, 고쳐보자

위와 같이 변경한 SerialDate는 모든 테스트 케이스를 통과한다. 이제 SerialDate를 올바로 고쳐보자. 코드 변경 시 마다 JCommon 단위테스트와 자체 단위테스트를 모두 실행하였다.

  • 초반 선언부 주석은 너무 오래되었다. 법적 정보()만 남겨두고 나머지는 제거한다.
  • enum을 모두 독자적인 소스 파일로 이동.
  • 정적 변수(dateFormatSymbols)와 정적 메서드(getMonthNames, isLeapYear, lastDayOfMonth)는 새 클래스로 이동
  • 일부 추상 메서드는 DayDate.java로 이동
  • Month.makeMonth.fromInt로 변경. 다른 enum도 똑같이 변경하고 모든 enum에 toInt() 접근자를 생성, index 필드를 private로 정의.
  • plusYears와 plusMonths의 중복을 correctLastDayOfMonth라는 새 메서드를 통해 제거
  • 사용하던 숫자 1 대신 모두 Month.JANUARY.toInt() 혹은 Day.SUNDAY.toInt()로 적절히 변경. SpreadsheetDate 코드를 살펴보고 알고리즘을 조금 손봤다.

결론

위 처럼 수정 결과, DayDate 코드 커버리지는 84.9%로 감소하였다. 테스트하는 코드가 줄어서가 아니라 클래스 크기가 작아지는 바람에 테스트하지 않는 코드의 비중이 커졌기 때문이다. 테스트하지 않는 코드는 너무 사소해 테스트할 필요도 없는 코드만 남았다.

profile
개발공부 요약노트

0개의 댓글