본문 바로가기
Engineering WIKI/Book

리팩토링 2판 - Chapter 7 (캡슐화)

by wonos 2022. 10. 20.
  • 모듈을 분리하는 가장 중요한 기준은 아마도 시스템에서 각 모듈이 자신을 제외한 다른 부분에 드러내지 않아야 할 비밀을 얼마나 잘 숨기느냐에 있을 것이다. p.235
  • 클래스는 본래 정보를 숨기는 용도로 설계되었다. p.235

7.1 레코드 캡슐화하기

  • 저장하는 용도로는 레코드보다 객체를 선호하는 편이다. p.236
  • 객체를 사용하면 어떻게 저장했는지를 숨긴 채 세 가지 값을 각각의 메서드로 제공할 수 있다. 사용자는 무엇이 저장된 값이고 무엇이 계산된 값인지 알 필요가 없다.  p.237
  • 덩치 큰 데이터 구조를 다룰수록 쓰기 부분에 집중한다. p.243
  • setter 부분에서 데이터의 변화가 일어나기 때문에 가변 데이터라면 쓰기 부분에 집중해야 한다.
  • 데이터 구조의 읽기 전용 프락시를 반환하는 방법도 있다. 클라이언트 내부 객체를 수정하려 하면 프락시가 예외를 던지도록 하는 것이다. p.243
  • 읽기 전용 프록시를 만들면 프록시 객체에서 setter가 실행되면 예외가 발생하게 될 것이다.
  • 이 상황에서 프록시를 부모 객체로 치환했을 때 setter가 기대했던 대로 작동하지 않게 된다.
  • 그러면 리스코프 치환 원칙(LSP)을 위반하게 된다.
  • 이러한 위반을 알면서도 읽기 전용 프록시를 사용해야 하는 경우는 언제인지 아직은 모르겠다.
  • 때로는 새로 만든 클래스와 게터를 잘 혼합해서, 게터는 데이터 구조를 깊이 탐색하게 만들되 원본 데이터를 그대로 반환하지 말고 객체로 감싸서 반환하는 게 효과적일 수 있다. p.245
  • 때로는 setter 적극적 사용 + getter는 deep copy 한 데이터 반환 조합으로 사용할 수 도 있다.
  • 무조건 setter/getter로 인터페이스를 감싸는 게 좋은 것은 아니다.

7.2 컬렉션 캡슐화하기

  • 여기서 중요한 점은 코드 베이스에서 일관성을 주는 것이다. 앞에 나온 방식 중에서 한 가지만 적용해서 컬렉션 접근 함수의 동작 방식을 통일해야 한다.
  • 리팩토링 하는 방식도 객체 안에서 일관성 있게 적용해야 한다.

7.3 기본형을 객체로 바꾸기 (Replace Primitive with Object)

  • 나는 단순한 출력 이상의 기능이 필요해지는 순간 그 데이터를 표현하는 전용 클래스를 정의하는 편이다. p.251
  • 부지런히 전용 클래스를 만들어봐야겠다.
  • 반복적으로 사용되는 개념을 기본형 타입으로 계속 두지 말고 객체로 만들어보자.
  • 객체로 만들어두면 해당 개념에 추가적인 기능이 필요해지면 객체에 메서드를 추가할 수 있다.
class Priority {
    private let value: String

    init(_ value: String) {
        self.value = value
    }

    func toString() {
        return value
    }
}
  • 이 상황에서는 개인적으로 게터(value())보다는 변환 함수(toString())를 선호한다. 클라이언트 입장에서 보면 속성 자체를 받은 게 아니라 해당 속성을 문자열로 표현한 값을 요청한 게 되기 때문이다. p.253
  • 클라이언트 관점에서 보면 Priority 객체를 string으로 표현했을 때 어떤 결과물이 나오는가를 체크하게 된다.
  • 좀 더 맥락을 파악하기 좋다.

7.4 임시 변수를 질의 함수로 바꾸기

  • 이번 리팩터링은 클래스 안에서 적용할 때 효과가 가장 크다. p.257
  • 스냅숏 용도로 쓰이는 변수에는 이 리팩터링을 적용하면 안 된다. p.257

7.5 클래스 추출하기

  • 일부 데이터와 메서드를 따로 묶을 수 있다면 어서 분리하라는 신호다. p.260
  • 함께 묶이는 부분이 있다면 클래스로 한번 추출해보자.
  • 다시 돌아갈 수 있도록 커밋을 자주 남기거나 임시 함수를 만들어서 작업하는 방안이 있을 것 같다.
  • 하나씩 옮길 때마다 테스트한다. p.261
  • 앞의 절차에도 계속 나왔을 문구인데 갑자기 눈에 들어와서 남긴다.
  • 리팩터링을 작게 나눠서 진행하고 한 발자국 뗄 때마다 테스트를 한다.

7.7 위임 숨기기

  • 캡슐화는 모듈들이 시스템의 다른 부분에 대해 알아야 할 내용을 줄여준다. p.268

7.8 중개자 제거하기

  • 언제든 균형점을 옮길 수 있으니 말이다. 시스템이 바뀌면 '적절하다'의 기준도 바뀌기 마련이다. 6개월 전에는 바람직했던 캡슐화가 이제는 어색할 수 있다. 리팩터링은 결과 미안하다고 말하지 않는다. 즉시 고칠 뿐이다. p.272
  • 개발자들은 그 순간에 적합한 코드를 작성한다.
  • 시간이 지나면 코드도 변하고 적절함의 기준도 바뀐다.
  • 이전에는 꼭 필요했던 것이 이제는 필요 없어지기도 한다..
  • 리팩토링 기법들도 좋지만 그 순간에 맞는 트레이드 오프를 제대로 할 줄 아는 개발자가 되면 좋겠습니다.