리팩터링 2판 정리- 기본적인 리팩터링(4)

초보개발자·2022년 3월 18일
0

리팩터링

목록 보기
5/13

1. 함수 추출하기

  • 코드 조각을 찾아 무슨일을 하는지 파악한다음, 독립된 함수로 추출하고 목적에 맞는 이름을 붙인다.
  • '목적과 구현을 분리'하는 방식이 가장 합리적인 기준으로 보인다.
  • 코드를 보고 무슨 일을 하는지 파악하는 데 한참이 걸린다면 그 부분을 함수로 추출한뒤 '무슨 일'에 걸맞는 이름을 짓는다.
  • 함수가 짧으면 캐싱하기가 더 쉽기 때문에 컴파일러가 최적화하는 데 유리할 때가 많다.
  • 짧은 함수의 이점은 이름을 잘 지어야만 발휘되므로 이름 짓기에 특별히 신경 써야 한다.

절차

  1. 함수를 새로 만들고 목적을 잘 드러내는 이름을 붙힌다.
  2. 추출할 코드를 원본 함수에서 복사하여 새 함수에 붙혀 넣는다.
  3. 추출한 코드 중 원본 함수의 지역 변수를 참조하거나 추출한 함수의 유효범위를 벗어나는 변수는 없는지 검사한다. 있다면 매개변수로 전달한다.
  4. 변수를 다 처리했다면 컴파일한다.
  5. 원본 함수에서 추출한 코드 부분을 새로 만든 함수를 호출하는 문장으로 바꾼다.
  6. 테스트한다.
  7. 다른 코드에 방금 추출한 것과 똑같거나 비슷한 코드가 없는지 살핀다. 있다면 방금 추출한 새 함수를 호출하도록 바꿀지 검토한다.

2. 함수 인라인하기

  • 목적이 분명히 드러나는 이름의 짤막한 함수를 이용하기 권한다. 그래야 코드가 명료해지고 이해하기 쉬워지기 때문이다.

절차

  1. 다형 메서드인지 확인한다.
  2. 인라인할 함수를 호출하는 곳을 모두 찾는다.
  3. 각 호출문을 함수 본문으로 교체한다.
  4. 하나씩 교체할 때마다 테스트한다.
  5. 함수 정의를 삭제한다.

3. 변수 추출하기

  • 표현식이 너무 복잡해서 이해하기 어려울 때가 있다. 이럴 때 지역 변수를 활용하면 표현식을 쪼개 관리하기 더 쉽게 만들 수 있다.
  • 그러면 복잡한 로직을 구성하는 단계마다 이름을 붙일 수 있어서 코드의 목적을 훨씬 명확하게 드러낼 수 있다.
  • 변수 추출을 고려한다고 함은 표현식에 이름을 붙이고 싶다는 뜻이다.
  • 덩치가 큰 클래스에서 공통 동작을 별도 이름으로 뽑아내서 추상화해두면 그 객체를 다룰 때 쉽게 활용할 수 있어서 매우 유용하다.

절차

  1. 추출하려는 표현식에 부작용은 없는지 확인한다.
  2. 불변 변수를 하나 선언하고 이름을 붙일 표현식의 복제본을 대입한다.
  3. 원본 표현식을 새로 만든 변수로 교체한다.
  4. 테스트한다.
  5. 표현식을 여러 곳에서 사용한다면 각가을 새로 만든 변수로 교체한다. 하나 교체할 때마다 테스트를 한다.

4. 변수 인라인하기

절차

  1. 대입문의 우변에서 부작용이 생기지 않는지 확인한다.
  2. 변수가 불변으로 선언되지 않았다면 불변으로 만든 후 테스트한다.
  3. 이 변수를 가장 처음 사용하는 코드를 찾아서 대입문 우변의 코드로 바꾼다.
  4. 테스트한다.
  5. 변수를 사용하는 부분을 모두 교체할 때까지 이 과정을 반복한다.
  6. 변수 선언문과 대입문을 지운다.
  7. 테스트한다.

5. 함수 선언 바꾸기

  • 연결부를 잘 정의하면 시스템에 새로운 부분을 추가하기가 쉬워지는 반면, 잘못 정의하면 지속적인 방해 요인으로 작용하여 소프트웨어 동작을 파악하기 어려워지고 요구사항이 바뀔 때 적절히 수정하기 어렵게 한다.
  • 연결부에서 가장 중요한 요소는 함수의 이름이다.
  • 이름이 좋으면 함수의 구현 코드를 살펴볼 필요 없이 호출문만 보고도 무슨 일을 하는지 파악할 수 있다.
  • 좋은 이름을 떠올리는 데 효과적인 방법이 하나있다. 바로 주석을 이용해 함수의 목적을 설명해 보는 것이다.

절차

  1. 매개변수를 제거하려거든 먼저 함수 본문에서 제거 대상 매개변수를 참조하는 곳은 없는지 확인한다.
  2. 메서드 선언을 원하는 형태로 바꾼다.
  3. 기존 메서드 선언을 참조하는 부분을 모두 찾아서 바뀐 형태로 수정한다.
  4. 테스트한다.

6. 변수 캡슐화하기

  • 리팩터링은 결국 프로그램의 요소를 조작하는 일이다.
  • 데이터는 함수보다 다루기가 까다로운데, 그 이유는 이런 식으로 처리할 수 없기 때문이다.
  • 데이터는 참조하는 모든 부분을 한 번에 바꿔야 코드가 제대로 작동한다.
  • 데이터는 유효범위가 넓어질수록 다루기가 어려워진다. 전역 데이터가 골칫거리인 이유도 바로 여기에 있다.
  • 접근할 수 있는 범위가 넓은 데이터를 옮길 때는 먼저 그 데이터로의 접근을 독점하는 함수를 만드는 식으로 캡슐화하는 것이 가장 좋은 방법일 때가 많다.
  • 데이터 재구성이라는 어려운 작업을 함수 재구성이라는 더 단순한 작업으로 변환되는 것이다.
  • 데이터를 변경하고 사용하는 코드를 감시할 수 있는 확실한 통로가 되어주기 때문에 데이터 변경 전 검증이나 변경 후 추가 로직을 쉽게 끼워 넣을 수 있다.
  • 데이터의 유효범위가 넓을수록 캡슐화해야 한다. 그래야 자주 사용하는 데이터에 대한 결합도가 높아지는 일을 막을 수 있다.
  • 불변 데이터는 가변 데이터보다 캡슐화할 이유가 적다.
  • 게다가 불변 데이터는 옮길 필요 없이 그냥 복제하면 된다.
  • 데이터를 복제해 저장하여 나중에 원본이 변경돼서 발생하는 사고를 방지할 수 있다.
  • 복제본 만들기가 번거로울 때가 많지만, 이런 복제가 서능에 주는 영향은 대체로 미미하다. 반면 원본을 그대로 사용하면 나중에 디버깅하기 어렵고 오래 걸릴 위험이 있다.

절차

  1. 변수로의 접근과 갱신을 전담하는 캡슐화 함수들을 만든다.
  2. 정적 검사를 수행한다.
  3. 변수를 직접 참조하던 부분을 모두 적절한 캡슐화 함수 호출로 바꾼다. 하나씩 바꿀 때마다 테스트를 한다.
  4. 변수의 접근 범위를 제한한다.
  5. 테스트한다.
  6. 변수 값이 레코드라면 레코드 캡슐화하기를 적용할지 고려해본다.

참고
리팩터링 2판

profile
주니어 개발자입니다!

0개의 댓글