CHAPTER 5 리팩터링 기법

CHAPTER 5 리팩터링 기법

5.1 리팩터링의 네 가지 요소: 목적, 대상, 시기, 방법

5.1.1 리팩터링의 목적

코드에 대한 이해를 쉽게 하기 위해 소프트웨어의 내부 구조를 개선하는 것으로
소프트웨어의 외부 동작을 변경하지 않고 수정 비용을 줄이는 것을 목적으로 한다

고품질 코드는 훌륭한 설계 한 번에 나오는 것이 아니라 반복적인 작업의 결과로 나오는 것이다

5.1.2 리팩터링의 대상

리팩터링의 종류

  • 대규모 리팩터링 : 시스템, 모듈, 코드 구조, 클래스 간 관계의 리팩터링을 포함하여 최상위 설계를 리팩터링하는 것
  • 소규모 리팩터링 : 표준 명명, 표준 주석, 초대형 클래스와 함수 제거, 중복코드 추출, 같이 주로 클래스, 함수, 변수 수준에서 코드 세부 정보를 리팩터링하는 것을 말한다

5.1.3 리팩터링의 시기

코드가 망가지고 한꺼번에 해결하려는 수단으로 리팩터링은 옳지 않다

지속가능하고 진화적인 리팩터링 계획을 탐구 해야 된다 - 지속적인 리팩터링

5.1.4 리팩터링의 방법

대규모 리팩터링 일때

  • 사전에 종합적인 리팩터링 계획을 수립해, 질서 있고 단계적으로 진행해야 한다

소규모 리팩터링 일때

  • 시간 있을 때마다 소규모 리팩터링을 할수 있다

5.2 단위 테스트

잘못된 리팩터링을 방지하는 방법?

  • 단위테스트로 할수 있지 않을까?

5.2.1 단위 테스트에 대해

단위 테스트는 코드의 정확성을 테스트하기 위한 것이지만, 테스트 엔지니어가 아닌 개발 엔지니어가 작성하는 것이며 통합 테스트 보단 작다

  • 테스트 포괄성을 보장하기 위해 테스트 케이스 설계
  • 코드로 변환

5.2.2 단위 테스트 코드를 작성하는 이유

  • 프로그래머가 코드에서 버그를 찾는 데 도움이 될 수 있다
  • 프로그래머가 코드 설계에서 문제를 찾는데 도움이 될 수 있다
  • 통합 테스트를 보완하는 강력한도구다
  • 단위 테스트 코드를 작성하는 과정은 코드 리팩터링 과정에 해당한다
  • 단위 테스트는 프로그래머가 코드에 빠르게 익숙해지도록 도와준다
  • 단위 테스트는 테스트 주도 개발을 개선하고 대체할 수 있다

    5.2.3 단위 테스트를 설계하는 방법

  • 단위 테스트를 설계하는 것은 시간이 많이 걸리는 일인가?
  • 단위 테스트 코드의 품질에 대한 요구 사항이 있는가?
  • 단위 테스트의 커버리지가 높으면 그것만으로 충분한가?
  • 단위 테스트 코드를 작성할 떄 코드의 구현 논리를 이해하는 것이 필요한가?
  • 단위 테스트 프레임워크를 선택하는 방법은 무엇인가?

    5.2.4 단위 테스트를 작성하기 어려운 이유

  • 단위 테스트 코드의 작성은 사실 인내심을 테스트하는 일이기도 하다
  • 리더의 의지와 감독만으로는 불가능한 일이며 팀원들에게 코드에 대한 강한 주인의식이 있어야 가능하다
  • 테스트 팀이 별도로 있기 때문에

5.3 코드 테스트 용이성

5.3.1 테스트 가능한 코드를 작성하는 방법

  • 클래스의 독립성 - 해당 클래스가 높은 응집도와 낮은 결합도를 만족하는지에 달려 있다

5.3.2 테스트가 불가능한 코드

  • 보류 중인 동작
  • 전역 변수
  • 정적 메서드
  • 복잡한 상속 관계

5.4 디커플링

대규모 리팩터링의 주 목적은 디커플링이다

5.4.1 디커플링이 중요한 이유

코드의 복잡성을 제어하는 방법은 매우 많지만 그중에서 가장 효과적인 방법이 디커플링이다

높은 응집도와 낮은 결합도를 가진 코드의 특징

  • 코드 구조가 명확
  • 계층화와 모듈화가 합리적
  • 의존성이 간단
  • 모듈이나 클래스 사이의 결합도가 낮다

5.4.2 코드를 디커플링해야 하는지 판단하기

  • 기능 코드이 일부가 수정되면 전체 코드를 모두 건드려야 하는 상황을 발생한다는것
  • 의존성 그래프의 복잡성에 따라 프로젝트의 코드를 분리해야 하는지 판단

5.4.3 코드 디커플링 방법

  • 캡슐화와 추상화로 디커플링하기
  • 중간 계층으로 디커플링하기
  • 모듈화 계층화로 디커플링하기
  • 고전적인 코드 설계 원칙과 사상을 이용한 디커플링
    • 단일 책임 원칙
    • 구현이 아닌 인터페이스 기반의 프로그래밍
    • 의존성 주입
    • 상속보다는 합성을 더 많이 사용
    • 디미터의 법칙을 따르는것

참조