본문 바로가기

programming study/Refactoring

Refactoring - 코드에서 나는 악취(3)

본 내용은 마틴 파울러의 Refactoring 2판을 토대로 작성되었습니다.

코드에서 나는 악취

기본형 집착

  • 대부분의 프로그래밍 언어는 정수, 부동소수점 수, 문자열 같은 다양한 기본형(Primitive Type)을 제공
    • 라이브러리를 통해 날짜 같은 간단한 객체를 추가로 제공하기도 함
  • 주어진 문제에 맞는 기초 타입(화폐, 좌표, 구간 등)을 직접 정의하기를 몹시 꺼리는 사람이 많음
    • 금액을 그냥 숫자형으로 계산
    • 물리량을 계산할 때 단위형을 무시
  • 최소한 사용자에게 보여줄 때는 일관된 형식으로 출력해주는 기능이라도 갖춰야 함
  • 문자열화된 변수(Stringify Typed): 자료형들을 문자열로만 표현하는 악취
  • 기본형을 객체로 바꾸기
  • 기본형으로 표현된 코드가 조건부 동작을 제어하는 타입 코드로 사용되었다면
    • 타입 코드를 서브클래스로 바꾸기
    • 조건부 로직을 다형성으로 바꾸기
  • 자주 몰려다니는 기본형 그룹도 데이터 뭉치
    • 클래스 추출하기
    • 매개변수 객체 만들기

 

반복되는 switch문

  • switch문과 조건부 로직을 다형성으로 바꾸기
  • 독같은 조건문 로직(switch/case, if/else)이 여러 곳에서 반복해 등장하는 코드에 집중하기
  • switch문은 조건절을 추가할 때마다 다른 switch 문들도 모두 찾아서 함께 수정해야 함

 

반복문

  • 반복문을 파이프라인으로 바꾸기
    • filter, map 같은 파이프라인 연산을 사용하면 코드에서 각 원소들이 어떻게 처리되는지 쉽게 파악할 수 있음

 

성의없는 요소

  • 코드의 구조를 잡을 때 프로그램 요소를 사용
    • 프로그램 요소: 프로그래밍 언어가 제공하는 함수(메서드), 클래스, 인터페이스 등 코드 구조를 잡는 데 활용되는 요소를 뜻함
  • 실질적으로 메서드가 하나이거나, 본문 코드를 그대로 쓰는 것과 같은 함수 등인 경우 필요 없음
    • 함수 인라인하기, 클래스 인라인 하기, 계층 합치기 등으로 제거

 

추측성 일반화

  • '나중에 필요할 거야'라는 생각으로 당장은 필요 없는 모든 종류의 후킹 포인트와 특이 케이스 처리 로직을 작성해둔 코드에서 풍김
    • 그 결과로, 이해하거나 관리가 어려워진 코드가 됨
  • 당장 걸리적 거리는 코드는 눈 앞에서 치우기
  • 하는 일이 없는 추상 클래스는 계층 합치기로 제거
  • 쓸데없이 위임하는 코드는 함수 인라인 하기, 클래스 인라인 하기로 삭제
  • 본문에서 사용되지 않는 매개변수는 함수 선언 바꾸기로 없앰
  • 테스트 케이스부터 삭제한 뒤에 죽은 코드 제거하기로 날리기

 

임시 필드

  • 특정 상황에서만 값이 설정되는 필드를 가진 클래스
  • 객체를 가져올 때는 당연히 모든 필드가 채워져 있으리라 기대하는 것이 보통이므로 임시 필드를 갖도록 작성하면 코드를 이해하기 어려움
  • 떨어져 있는 필드들을 발견하면 클래스 추출하기로 제 자리를 찾아 줌
  • 그 후, 함수 옮기기로 임시 필드들과 관련된 코드를 모조리 새 클래스에 몰아 넣음
  • 임시 필드들이 유효한지를 확인한 후 동작하는 조건부 로직이 있을 수 있는데 특이 케이스 추가하기로 필드들이 유효하지 않을 때를 위한 대안 클래스를 만들어서 제거

 

메시지 체인

  • 메시지 체인은 클라이언트가 한 객체를 통해 다른 객체를 얻은 뒤 방금 얻은 객체에 또 다른 객체를 요청하는 것
    • 다른 객체를 요청하는 작업이 연쇄적으로 이어지는 코드
  • 게터가 꼬리에 꼬리를 물고 이어지거나 임시 변수들이 줄줄이 나열되는 코드
  • 클라이언트가 객체 내비게이션 구조에 종속됐음을 의미
  • 내비게이션 중간 단계를 수정하면, 클라이언트 코드도 수정해야 함
  • 위임 숨기기로 해결
  • 최종 결과 객체가 어떻게 쓰이는 지부터 살펴보는 것이 좋음
  • 함수 추출하기로 결과 객체를 사용하는 코드 일부를 따로 빼낸 다음 함수 옮기기로 체인을 숨길 수 있는지 살펴보기
  • 객체 중 특정 하나를 사용하는 클라이언트 중 그 이후의 객체들도 사용하기 원하는 클라이언트가 제법 된다면, 이 요구를 처리해줄 메서드를 추가