코드의 구린내와 해결법

리팩토링의 기본

  • 한 클래스에서 다른 클래스로 상태와 기능을 옮기는 것은 리팩토링의 기본이다
  • 지금은 합리적이라고 판단되는 설계도 나중에는 그렇지 않을 수 있다
    • 문제는 이게 아니라, 이 상황에도 아무런 대처도 하지 않는 것이다

중복 코드(Duplicated Code)

최대의 구린내는 누가 뭐라해도 중복 코드이다
코드가 중복되면 한쪽만 수정하고, 다른 한쪽은 수정하지 않는 위험천만한 실수를 저지르기 쉽다

  • 한 클래스의 두 메서드안에 같은 코드가 들어있는 경우

    메서드 추출을 적용해서 겹치는 코드를 별도의 메서드로 분리하고, 그 메서드를 두 곳에서 호출하면 된다

  • 한 클래스의 두 하위클래스에 같은 코드가 들어있는 경우

    메서드 추출을 적용해서 중복을 없앤 후, 메서드 상향을 적용하면 된다.

    • 두 메서드의 코드가 똑같지 않고 비슷하다면?

      메서드 추출을 적용해서 같은 부분과 다른 부분을 분리해야 한다
      경우에 따라 템플릿 메서드 형성을 적용해야 할 수도 있다

    • 두 메서드의 기능이 같은데 알고리즘만 다르다면?

      두 알고리즘 중 더 간단한 것을 택해서 알고리즘 전환을 적용하면 된다

  • 중복코드가 메서드 가운데에 있는 경우

    주변 메서드 추출을 적용한다

  • 서로 상관없는 두 클래스안에 중복 코드가 있을 경우

    중복코드를 클래스 추출이나 모듈 추출을 적용해서 클래스나 모듈로 떼어낸 후, 그것을 호출한다
    두 클래스 중 한쪽에서 다른쪽을 호출할수도 있고, 제 3의 클래스로 추출하고 양쪽에서 호출할수도 있다

장황한 메서드

메서드가 길수록 이해하기 어렵기 때문에 메서드들은 작은 단위로 쪼개주는 것이 좋다
(최적의 상태로 장수하는 객체 프로그램들을 보면 공통적으로 메서드 길이가 짧다)

하지만 하나의 덩어리가 여러개로 나뉘어졌기 때문에, 읽으려면 화면간 전환이 생기기 되고, 이로 인해 사람의 머릿속에 오버헤드가 생기게 된다
그러므로 메서드의 기능을 한눈에 알 수 있는 메서드명을 사용하여 그 메서드 안의 코드를 분석하지 않아도 되게끔 해야한다

  • 메서드명은 기능 수행 방식이 아니라 목적(기능 그 자체)를 나타내는 이름으로 정해야한다

  • 메서드 호출이 원래 코드보다 길어지는 한이 있더라도, 메서드명은 그 코드의 의도를 잘 반영하는 것으로 정해야 한다

  • 메서드의 크기를 줄이려면 십중팔구는 메서드 추출 기법을 적용해야 한다

    • 메서드에서 하나로 묶으면 좋을 만한 부분들을 찾아서 메서드로 만든다
    • 주석을 참고하는 것도 방법이다
      • 주석으로 처리된 코드 구간을 메서드로 만든다
      • 주석에 설명된 기능을 참고해서 메서드명을 짓는다
  • 메서드에 매개변수와 임시변수가 많을 경우

    • 임시 변수를 메서드 호출로 전환이나 임시변수를 메서드 체인으로 전환을 사용하면 대부분의 임시변수는 제거된다
    • 길게 열거된 매개변수는 매개변수 세트를 객체로 전환객체를 통째로 전달을 적용하면 간결해진다
  • 위의 기법을 적용했음에도 불구하고 여전히 임시변수가 너무 많을 때는 메서드를 메서드 객체로 전환을 적용한다

  • 조건문과 루프도 메서드로 빼야 한다

    • 조건문을 추출하려면 조건문 쪼개기를 적용한다
    • 루프를 추출하려면 루프를 컬렉션 클로저 메서드로 전환을 적용한 후, 그 클로저 메서드 호출과 클로저 자체에 메서드 추출을 적용하면 된다

참고 : 마틴 파울러, 『리팩토링』, 김지원 옮김, 한빛미디어(2012)