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

변경하기 쉬운 코드로 리팩터링하기

Key Points

  • 리팩터링하기 전에 제대로 된 테스트부터 마련한다. 테스트는 반드시 자가진단하도록 만든다.

    • 이후는 컴파일-테스트-커밋의 반복이다.

    • 매우 작은 단위(변수/함수 이동, 분리, 삭제 등)로 반복한다.

  • 프로그램 수정을 작은 단계로 나눠서 진행한다.

  • 설사 심각하게 느려지더라도 제대로 리팩터링된 코드베이스는 그렇지 않은 코드보다 성능을 개선하기가 훨씬 수월하다.

  • 거의 항상 지역변수부터 제거한다.

    • "변수 인라인하기"를 자주 활용하자.

  • 이름이 좋으면 함수 본문을 읽지 않고도 무슨 일을 하는지 알 수 있다.

    • 처음에는 당장 떠오르는 최선의 이름을 사용하다가, 나중에 더 좋은 이름이 떠오를 때 바꾸는 식이 좋다.

  • 리팩터링과 기능 추가 사이의 균형을 맞출 때 이것을 기억하자.

    • "항시 코드베이스를 작업하기 전보다 더 건강하게 고친다"

Details

  • 가변(mutable) 데이터는 금방 상하기 때문에 데이터를 최대한 불변(immutable)으로 취급하자.

    • e.g., result = Object.assign({}, aPerformance)

  • 반복문(for...)을 파이프라인(reduce, map, ...)으로 바꾸는 것도 좋다.

  • 다음 리팩터링 기법을 잘 활용하자.

    • 함수 추출하기 (6.1절)

    • 변수 인라인하기 (6.4절)

    • 함수 옮기기 (8.1절)

    • 조건부 로직을 다형성으로 바꾸기 (10.4절)

조건부 로직 - 다형성으로 변경

  • 조건부 로직을 다형성으로 바꿀 수 있다. (JS의 경우 ES6부터 객체지향을 사용하기 좋아졌다.)

  • 클래스에 로직을 담았다면 다형성을 지원하자.

    • 가장 먼저 할 일은 타입 코드 대신 서브클래스를 사용하도록 변경하는 것이다.

    • JS는 생성자가 서브클래스의 인스턴스를 반환할 수 없다. 대신 생성자를 팩터리 함수로 바꾸기를 적용할 수 있다. (switch, case 이용)

  • JS는 게터 메소드를 호출하는 코드와 일반적인 데이터 접근 코드의 모양이 똑같은 장점이 있다. (calculator.amount 코드가 get amount() 게터 메서드를 호출하도록 하면 된다.)

리팩터링

리팩터링은 코드가 하는 일을 파악하는 데서 시작한다.

코드를 읽고, 개선점을 찾고, 리팩터링 작업을 통해 개선점을 코드에 반영한다.

그 결과 코드가 명확해지고 이해하기 더 쉬워진다.

그러면 또 다른 개선점이 떠오르며 선순환이 형성된다.

좋은 코드

좋은 코드를 가늠하는 확실한 방법은 '얼마나 수정하기 쉬운가'다.

  • 프로그래머 사이에서 어떤 코드가 좋은 코드인지에 대한 의견은 다분하다.

  • 저자가 선호하는 '적절한 이름의 작은 함수들'로 만드는 방식에 반대하는 사람도 있을 것이다.

하지만 취향을 넘어서는 관점은 분명 존재하며, 코드를 '수정하기 쉬운 정도'야말로 좋은 코드를 가늠하는 확실한 방법이라고 믿는다.

  • 코드는 명확해야 한다.

  • 코드를 수정해야 할 상황이 되면 고쳐야 할 곳을 쉽게 찾을 수 있고, 오류 없이 빠르게 수정할 수 있어야 한다.

  • 건강한 코드베이스는 생산성을 극대화하고, 고객에게 필요한 기능을 더 빠르고 저렴한 비용으로 제공하도록 해준다.

  • 코드를 건강하게 관리하려면 프로그래밍 팀의 현재와 이상의 차이에 항상 신경 쓰면서, 이상에 가까워지도록 리팩터링해야 한다.

리팩터링하는 리듬

  • 이 챕터에서 가장 중요한 건 리팩터링하는 리듬이다.

    • 각 단계를 잘게 나누고 매번 컴파일하고 테스트하여 작동하는 상태로 유지하자.

  • 리팩터링을 효과적으로 하는 핵심은, 단계를 잘게 나눠야 더 빨리 처리할 수 있고, 코드는 절대 깨지지 않으며, 이러한 작은 단계들이 모여서 상당히 큰 변화를 이룰 수 있다는 사실을 깨닫자.

Last updated