Skip to content

클린코드 16장 리팩토링 예제: SerialDate  #47

@56aiden90

Description

@56aiden90

Chapter 16 Refactoring SerialDate

Make it work

유닛 테스트 보완

image

유닛테스트 보완 결과 노출된 버그 예시

image

문제코드 수정 전

image

문제코드 수정 후

image

Make it right

  • 코드 히스토리 지우기

image

  • 클래스명 수정
    • SerialDate라는 클래스가 실제로 나타내는 개념은 serial number(일련 번호)가 아닌 ordinal number(서수). 즉 클래스 이름과 개념이 일치하지 않음
    • SerialDate라는 이름은 구현 클래스라는 것을 암시함. 그러나 실제로 SerialDate는 추상 클래스이고, 가장 최선은 구현/추상 여부가 이름에 드러나지 않는 것.
      저자는 DayDate라는 이름을 추천함
    • MonthConstants는 인터페이스가 아니라 enum이 되야함

image

image

- 불필요한 코멘트 제거

image

- 추상 클래스와 구현 클래스
SerialDate는 아래와 같이 MINIMUM_YEAR_SUPPORTED와 MAXIMUM_YEAR_SUPPORTED 멤버 프로퍼티를 갖고 있으며 이는 구현에 해당함. 그러나 추상 클래스는 구현에 대한 어떠한 암시도 하지 않아야 함.

image

    저자는 이 문제를 해결하기 위해 프로퍼티들을 구현 클래스인 SpreadSheetDate로 보내고 싶어함. 

image

    그러나 이 변수들을 구현부로 보내버리면 SerialDate를 사용하는 클래스들이 SerialDate의 구현에 대한 정보까지 필요로 하게 된다는 점이다. 일반적으로는 SerialDate의 구현 클래스의 인스턴스를 변수로 넘기는 방식이 사용된다. 그러나 SerialDate.MINIMUM_YEAR_SUPPORTED 실제 사용하고 있는 함수(getDate)라는 함수를 보면 인스턴스를 전달 받는 게 아니라, 반대로 인스턴스를 리턴하고 있다. 결국 이 함수 내부 어딘가에서 SerialDate의 구현 클래스의 인스턴스가 생성된다는 뜻이다. 

image

image

    인스턴스가 생성되는 위치를 추적해보면 SerialDate는 아래와 같이 createInstance라는 메소드를 통해 SpreadsheetDate라는 구현클래스의 인스턴스를 생성할 수 있다. 

image

    **베이스 클래스가 구현 클래스에 대해 알게 하는 것은 일반적으로 좋지 않다.**
    
    어떻게 이 문제를 해결할 수 있을까?
    AbstractFactory 패턴을 사용하면 된다
    
- 중복 코드 제거

image

- 불필요한 함수 쪼개기 제거

image

- 잘못된 static 키워드 제거
addDays의 인자로 SerialDate base를 받고있음. 구현 클래스의 인스턴스를 인자로 받고 있으므로 이 함수는 static이 될 수 없음

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions