[책 정리] 리팩터링

1장. 리팩터링 : 첫 번째 예시

B# 2023. 12. 31. 20:38

리팩터링의 필요성

  • 코드 수정은 사람이 한다. 사람은 코드의 미적 상태에 민감하다.
  • 설계가 나쁜 시스템은 수정하기 어렵다. 원하는 동작을 수행하도록 하기 위해 수정해야할 부분을 찾고,
    기존 코드와 맞물려 작동하게 방법을 강구하기가 어렵기 때문이다.
  • 프로그램이 새로운 기능을 추가하기에 편한 구조가 아니라면, 먼저 기능을 추가하기 쉬운 형태로
    리팩터링하고 나서 원하는 기능을 추가한다.
    =
    프로그램의 작동 방식을 쉽게 파악할 있도록 코드를 여러 함수와 프로그램 요소로 재구성
  • 프로그램이 변경될 가능성이 없다면 해도 되지만, 기능추가 할거야? 그럼 해야 .
  • 다른 사람이 코드를 읽고 이해해야 일이 생겼는데 로직을 파악하는 어렵다면 리팩터링이 필요

 

테스트 코드의 필요성

  • 리팩터링에서 테스트의 역할은 굉장히 굉장히 중요하다.
  • 리팩터링 기법들이 버그 발생 여지를 최소화하도록 구성되어 있지만, 실제 작업은 사람이 한다.
  • 언제든 실수할 있다.
  • 프로그램이 클수록 수정 과정에서 예상치 못한 문제가 발생할 가능성이 크다.
  • 테스트 실행은 간단하게 만든다. 복잡하다면 테스트 방법을 정리해둔다.
  • 리팩터링 전에 제대로 테스트부터 마련한다. 테스트는 반드시 자가진단하도록 만든다.
  • 테스트를 작성하는 시간이 걸리지만, 신경 써서 만들어두면 디버깅 시간이 줄어서 전체 작업 시간은 오히려 단축된다.

 

 

리팩터링

  • 함수를 리팩터링할 때는 먼저 전체 동작을 각각의 부분으로 나눌 있는 지점을 찾는다.
  • 코드를 분석해서 얻은 부분 (예시에서는 " 번의 공연에 대한 요금 계산") 다음에
    분석하지 않고도 뭐하는 부분인지 있도록 코드에 반영한다.
    분석한 부분은 머릿 속에 저장되고, 머릿 저장공간은 휘발성이 매우 높다.
  • 코드 분석된 부분을 함수로 추출한다.
  • 함수에는 코드가 하는 일을 설명해주는 함수명을 지어준다.
  • 변수의 유효범위가 바뀌어서 새로 만든 함수에서 바로 사용할 없고, 값이 바뀌지 않는 변수는 매개변수로 받아서 사용
  • 함수 내에서 값이 바뀌는 함수는 함수 안에서 초기화해준다.
  • 수정 후에는 곧바로 컴파일 후에 테스트하여 실수한 없는지 확인한다.
  • 아무리 간단한 수정이라도 리팩터링 후에는 항상 테스트
  • 가지를 수정할 때마다 테스트하면, 오류가 생기더라도 변경 폭이 작기 때문에 살펴볼 범위도 좁아서 문제를 찾고 해결하기가 훨씬 쉽다.
  • 조금씩 변경하고 매번 테스트하는 것이 리팩터링의 핵심이다. (리팩터링은 프로그램 수정을 작은 단계로 나눠 진행한다. 그래야 중간에 실수하더라도 버그를 쉽게 찾을 있다.)
  • 번에 너무 많이 수정하려다 실수하면 디버깅하기 어려워져 결과적으로 작업시간이 늘어난다.
  • 수정 테스트하여 문제가 없다면, 변경사항을 로컬 버전관리 시스템에 커밋한다. 하나의 리팩터링을 끝낼 때마다 커밋하면, 중간에 문제가 생겨도 이전의 정상 상태로 쉽게 돌아갈 있다.
    (
    Git 쓰면 이게 가능해진다.)
  • 함수를 추출하고 나면, 추출된 함수 코드를 자세히 들여다보면서 지금보다 명확하게 표현할 있는 간단한 방법은 없는지 검토한다.
  • 임시 변수를 질의 함수로 바꾸기 : 어떤 값에 따라 달라지는 값을 갖는 변수를 추출
  • 변수 인라인 하기 : 추출부 생략 -> 필요한 곳에서 바로 사용
  • 방법으로 지역 변수 지우는 것의 장점 : 추출 작업이 훨씬 쉬워짐. 유효범위를 신경써야할 대상이 줄어들기 때문
  • amoutFor 뽑아낸 thisAmount 변하지 않으므로 이것을 사용하는 곳도 변수 인라인 하기 적용
  • 이름 짓기는 매우 중요한 작업. 단번에 좋은 이름 짓기 쉽지 않다. 따라서 처음에는 당장 떠오르는 최선의 이름을 사용하다가, 나중에 좋은 이름이 떠오를 바꾸자
  • 반복문 쪼개기 : 반복문을 도네..?? 성능에 좋은 아닌가
  • 문장 슬라이드 하기 : 관련 값들을 곳에 모으기
  • 코드가 복잡할수록 단계를 작게 나누자
  • 중간 데이터로 옮기는 건 꼭 써봐야겠다.
  • 반복문을 파이프라인으로 바꾸기 : 여러줄인 for, while 문을 1줄로 만들기 (java stream, 람다식 사용)
  • 다형성을 활용해 계산 코드 재구성하기
  • 리팩터링은 대부분 코드가 하는 일을 파악하는 데서 시작한다.
  • 좋은 코드를 가늠하는 확실한 방법은 '얼마나 수정하기 쉬운가'.

 

[마틴 파울러 - 리팩터링] 발췌