Code Smell

언제 리팩토링이 필요한지 정리한다.

Mysterious Name

함수, 모듈, 변수, 클래스 등은 이름만 봐도 무슨 일을 하고, 어떻게 사용해야하는지 명확히 알수 있어야한다.
이름만 잘 지어도, 문맥을 파악하는 시간을 줄일 수 있다.

Duplicated Code

코드가 중복되면, 볼 때마다 차이가 있는지 살펴봐야하는 부담이 있다.
만약 그 중 하나를 변경을 하게되면 다른 비슷한 코드들을 모두 살펴봐야한다.

Long Function

함수가 길 수록, 이해하기 어렵다.
짧은 함수를 읽는 사람 입장에서는 함수가 하는 일을 파악하기 위해 왔다 갔다 해야하는 비용이 든다.
하지만, 함수 이름을 잘 지어두면 본문 코드를 볼 이유가 없다.
적극적으로 함수를 쪼개고, 함수 이름은 동작 방식이 아니라 “의도” 가 드러나게 짓자.

Long Parameter List

매개 변수 목록이 길어지면, 이해하기 어려울 때가 많다.

Global Data

전역 데이터는 코드베이스 어디에서든 건들릴 수 있고 값을 누가 바꿨는지 찾아낼 메커니즘이 없다.
그래서, 버그는 계속 발생하는데 원인이 되는 코드를 찾아내기가 어렵다.

Mutable Data

데이터를 변경했더니, 예상치 못한 결과나 버그가 발생하는 경우가 있다.
코드의 다른 곳에서 다른 값을 기대한다는 사실을 인식하지 못한 채 수정하면, 프로그램이 오작동한다.

Divergent Change

뒤엉킨 변경은, SRP (Single Responsibility Principle) 이 제대로 지켜지지 않으면 발생한다.
즉, 하나의 모듈이 서로 다른 이유들로 인해 여러 가지 방식으로 변경되는 일이 많으면 발생한다

예를 들면,

  1. 새로 지원해야하는 DB 가 추가되면, 함수 세 개를 모두 바꿔야하는 모듈이 있거나
  2. 새로운 금융 상품을 추가할 때마다, 함수 네 개를 모두 바꿔야하는 모듈이 있거나

Shotgun Surgery

산탄총 수술은, 코드를 변경할 때마다 자잘하게 수정해야하는 클래스가 많을 때 발생한다.

Feature Envy

기능 편애는 흔히 어떤 함수가 자기가 속한 모듈의 함수나 데이터보다,
다른 모듈의 함수나 데이터와 상호작용하는 일이 많을 때 발생한다.

Data Clumps

데이터 항목 서너 개가 여러 곳에서 같이 뭉쳐져 있는 경우이다.
클래스 두 어개의 필드에서, 또는 메서드의 시그니처에서 발견되기도 한다.
이렇게 몰려다니는 데이터 뭉치는 새로운 보금자리를 만들어줘야한다.

Primitive Obsession

주어진 문제에 대해서 기초 타입 (화폐, 좌표, 구간..) 을 직접 정의하지 않고
금액을 그냥 숫자로 계산하거나, 밀리피터나 인치 같은 단위를 무쉬하고 처리하는 경우가 있다.

Repeated Switches

중복된 switch 문의 문제는 조건절을 추가할 때마다 다른 switch 문들도 함께 수정해야한다는 것이다.

Loops

filter 나 map 같은 파이프라인 연산을 사용하면, 각 원소들이 어떻게 처리되는지 쉽게 파악 가능하다.

Lazy Element

코드 구조를 잡는데 활용하는 요소인 함수, 클래스, 인터페이스 등이 필요 없을 때가 있다.
본문 코드를 그대로 쓰는 것과 별 차이 없는 함수이거나, 실질직으로 메서드가 하나뿐인 함수가 있을 수 있다.

Speculative Generality

미래를 대비해 작성한 부분이 실제로 사용되지 않는다면 낭비일 뿐이다.

Temporary Field

특정 상황에서만 값이 설정되는 필드를 가진 클래스가 있다.
하지만, 객체를 가져올 때는 당연히 모든 필드가 채워져 있으리라 기대하는게 보통이다.
그래서 이렇게 임시 필드가 있으면 코드를 이해하기 어렵다.

Message Chains

메세지 체인은 , 다른 객체를 요청하는 작업이 연쇄적으로 이어지는 코드이다.
클라이언트가 한 객체를 통해 다른 객체를 얻은 뒤에, 방금 얻은 객체에서 또 다른 객체를 요청하는 경우이다.
그래서, 네비게이션 중간 단계를 수정하면 클라이언트 코드도 수정해야한다.

Middle Man

클래스가 제공하는 메서드 중 절반이 다른 클래스에 위윔하는 경우이다.
실제로 일을 하는 객체와 직접 소통하게 수정해야한다.

Insider Trading

모듈 사이의 데이터 거래가 많으면 coupling 이 많아진다.
이 양을 최소화하고 모두 투명하게 처리해야한다.

Large Class

한 클래스가 너무 많은 일을 하면, 필드 수가 많아진다.
그리고 클래스에 필드가 많아지면 중복 코드가 생긴다.

Alternative Classes with Different Interfaces

필요에 따라 언제든 다른 클래스로 교체하기 위해서는, 인터페이스가 같아야한다.

Data Class

데이터 클래스란, 데이터 필드의 getter/setter 메서드로만 구성된 클래스이다.
이런 클래스에 public 필드가 있다면 레코드 캡슐화를 하거나 세터를 제거해야한다.

Refused Bequest

상속 포기는, 서브클래스가 부모의 동작을 필요로하지만 인터페이스는 따르고 싶지 않을 때 발생한다.
이러 경우는, 상속 메커니즘에서 벗어날 필요가 있다.

Comments

주석이 많으면 위의 code smell 이 발생할 코드가 나오기 쉽다.


REFACTORING <마틴 파울러>

Comments