alt
Home 리팩터링 7장. 캡슐화
Post
Cancel

리팩터링 7장. 캡슐화

: 캡슐화가 잘 되어있을수록 모듈 각각은 내부가 다른 모듈에게 노출되지 않는다. 이 때 캡슐화의 단위는 클래스, 모듈, 심지어 함수도 될 수가 있다. 이 장의 리팩터링을 적용하면 많은 경우 캡슐화를 개선할 수 있다.


1. 레코드 캡슐화하기

  • 무엇이 저장된 값이고, 무엇이 계산된 값인지 바깥에서 알 필요가 없고, 데이터를 더 의미있는 단위로 값을 제공해 줄 수 있게 된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    // before
    person = { firstName: "foo", lastName = "bar" };
      
    // after
    class Person {
      // ..
        
      get name() { return this.firstName + " " + this.lastName; }
    }
    


2. 컬렉션 캡슐화하기

  • 컬렉션 자체를 getter로 제공하기보다 각 요소에 대한 add~~(), remove~~() 를 제공해준다. 이렇게 하면 클라이언트가 실수로 컬렉션 (혹은 가변 데이터)를 바꿀 가능성을 줄일 수 있다.

    • 그런다고 컬렉션을 제공하지 않도록하는 것은 여러모로 손해일 수 있다. 이러한 방법 중 하나로 읽기 전용을 제공하는 방법이 있다. (e.g) 복제 혹은 stream() 만 제공하는 방식)

      1
      2
      3
      
      public Stream<Person> stream() {
          return this.persons.stream();
      }
      
    • 코드 일관성: 보통 팀 규칙으로 이런걸 정할텐데, 새로운 팀원은 이러한 규칙을 파악하는데 어려움이 있을 수 있으니 일관성 있게 코드를 작성해야한다.


3. 기본형을 객체로 바꾸기

  • 데이터를 표현하는 변수를 클래스화한다. 프로그램 몸집이 커질수록 더더욱 유용하게 된다. 저자는 단순 출력 이상의 기능이 필요해지는 순간 클래스화한다고 한다.


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

  • 임시 변수를 함수로 추출해내면 많은 경우 불필요한 의존관계, 코드 중복을 줄일 수 있다.

    1
    2
    3
    4
    5
    
    // Before
    const name = this.firstName + " " + this.lastName;
      
    // After
    get name() { this.firstName + " " + this.lastName; }
    
    • 이 때의 질의함수는 한번만 계산하고 그 뒤에는 읽는 역할만 해야한다. 변경이 발생했는데 재사용이 된다면, 어디서 변경이 일어났는지 알아내기 어려울 수 있다.


5. 클래스 추출하기

  • 함께 변경되는 데이터 뭉치 끼리 분리하면서 클래스 몸집을 작게 유지한다.


6. 클래스 인라인하기

  • 클래스 역할이 줄어들어 더이상 필요 없을때 or 재배분하고 싶을 때 합쳤다가 다시 분리한다.


7. 위임 숨기기

  • A 객체의 필드가 가리키는 B 객체의 메서드를 호출하려면 클라이언트는 B를 알아야한다. 해당 객체의 인터페이스가 바뀌면 이 것을 사용하는 모든 클라이언트의 코드가 바뀌어야한다.

  • 객체간 결합도 측면: 객체간 결합도가 높다는 뜻. 보통 이러한 경우의 불필요한 결합도는 끊기 쉬운 경우가 많다.

    c.f) 롬복의 @Delegate 어노테이션을 사용하면 특정 메서드를 다른 클래스로 위임 할 수 있다


8. 중개자 제거하기

  • 너무 디미터 법칙을 따르다보면, 어느새 클라이언트와 맡닿는 A 서버 객체가 위임의 역할만 수행하고 있을 수 있다. 그렇게 느낄때마다 제거한다.

    보통 시스템이 바뀌면 ‘적절함’의 기준도 바뀐다. 그냥 지금 리팩터링이 필요하면 하면 된다.


9. 알고리즘 교체하기

  • 복잡하거나 예전 방식의 알고리즘을 개선하기.
  • 이 작업에 들어가기 전에, 교체하기 전의 알고리즘을 하나의 메서드로 나누는게 좋다. 거대한 알고리즘일수록 파악하고 교체하기가 어려우니, 간소화 작업은 필수인 것 같다.



Reference)

리팩터링 2판

This post is licensed under CC BY 4.0 by the author.

변수 네이밍

리팩터링 8장. 기능 이동