본문으로 바로가기

[Clean Code] 17장 냄새와 휴리스틱

category Prodo 독서 리뷰 2021. 3. 27. 00:36

1장부터 16장까지 정리한 내용의 요약본이 되는것 같다.

 

주석 (Comment)

 

C1 : 부적절한 정보

- 소스관리 시스템 등에 저장하는 정보는 주석으로 남길 필요가 없다.

 

C2 : 쓸모없는 주석

- 맞지 않는 주석은 삭제 한다.

 

C3 : 중복된 주석

- 코드로 알 수 있는 사실은 주석으로 남기지 않는다.

 

C4 : 성의 없는 주석

- 당연한 소리를 반복하지 않고, 간결하고 명료하게 작성한다.

 

C5 : 주석 처리된 코드

- 주석 처리된 코드는 다른 코드의 변경사항을 반영하지 않는다.

- 필요하면 소스 코드 관리 스셑메에서 불러 오도록 하자.

 

환경 (Environment)

 

E1 : 여러단계로 빌드해야 한다.

- 명령 하나로 빌드 될 수 있도록 해야한다.

 

E2 : 여러 단계로 테스트해야 한다.

- 명령 하나로 모든 테스트를 돌릴 수 있어야 한다.

 

함수 (Functions)

 

F1 : 너무 많은인수

- 인수 개수가 3개를 넘지 않도록 한다.

 

F2 : 출력 인수

- 사용자는 인수는 입력으로 간주하기 때문에 직관적이지 못하다.

- 함수가 속한 객체의 상태를 바꿔주는 것이 좋다.

 

F3 : 플래그 인수

- boolean인수는 함수가 여러 기능을 수행한다는 것을 의미한다.

 

F4 : 죽은 함수

- 아무도 호출하지 않는 함수는 삭제하라.

- 필요하면 코드 관리 시스템에서 다시 가져오면 된다.

 

일반 (General)

 

G1 : 한 소스 파일에 여러 언어를 사용한다.

- 소스파일에 쓰이는 언어의 수를 최대한 줄이도록 하자.

 

G2 : 당연한 동작을 구현하지 않는다.

- 다른 프로그래머가 당연하게 여길 만한 동작과 기능은 구현해야 한다.

 

G3 : 경계를 올바로 처리하지 않는다.

- 모든 경계 조건을 테스트하는 테스트 케이스를 작성하라.

 

G4 : 안전 절차 무시

- 테스트 케이스 작성하라

- 컴파일러 경고를 끄지 마라

 

G5 : 중복

case1. 똑같은 코드가 반복되는 경우 -> 함수로 묶어준다.

case2. switch/case나 if/else문으로 똑같은 조건을 거듭 확인 할 경우 -> 다형성으로 대체

case3. 알고리즘은 유사하나 코드가 다를 경우

-> TEMPLATE METHOD 패턴이나, STRATEGY 패턴으로 중복 제거

 

전략 패턴 : victorydntmd.tistory.com/292

 

[디자인패턴] 전략 패턴 ( Strategy Pattern )

전략 패턴 ( Strategy Pattern ) 객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여, 객체의 행위를 동적으로 바꾸고 싶은 경우

victorydntmd.tistory.com

템플릿 메서드 패턴 :  www.crocus.co.kr/1531

 

G6 : 추상화 수준이 올바르지 못하다.

- 저차원 개념은 파생 클래스에 넣고 고차원 개념은 기초 클래스에 넣어야 한다.

- 기초 클래스는 구현 정보를 몰라야 한다.

 

G7 : 기초 클래스가 파생 클래스에 의존한다.

- 기초 클래스는 파생 클래스를 몰라야 한다.

- FSM (Finte State Machine)의 경우 예외로 친다.

 

FSM이란?

AI 기법 중에 하나

유한한 상태의 개수를 가질 수 있는 추상 기계로 한 번에 하나의 상태를 가지며 현재 상태로부터

전이 상태와, 이러한 전이를 유발하는 조건들의 집합으로서 정의된다.

 

 

G8 : 과도한 정보

- 구현 정보를 최소한으로 숨기면 겹할도를 낮출 수 있다.

- 인터페이스를 작게 만들어라.

- 상수와 임시변수를 숨겨라

- protected 변수나 함수를 마구 만들지 마라

- 유틸리티 함수를 숨겨라

 

G9 : 죽은 코드

- 실행되지 않는 코드는 설계가 변해도 제대로 수정되지 않기 때문에 제거해야 한다.

- 불가능한 조건을 확인하는 if문

- throw가 없는 try/catch문

 

G10 :  수직분리

- 변수와 함수는 사용되는 위치에 가깝게 정의한다.

 

G11 : 일관성 부족

- 어떤 개념을 특정 방식으로 구현했다면 유사한 개념도 같은 방식으로 구현해야 한다 (네이밍 포함)

 

G12 : 잡동사니

- 아무것도 하지 않는 함수, 절대 호출되지 않는 코드, 맞지 않는 주석 등을 제거하라.

 

G13 : 인위적 결합

- 서로 무관한 개념을 인위적으로 결합하지 않는다.

- class에 포함된 enum

- 특정 클래스에 포함된 범용 static 함수

 

G14 : 기능 욕심

- 클래스의 메서드는 자기 클래스가 아닌 다른 클래스의 변수와 함수에 관심을 가져서는 안된다.

- 다른 클래스의 인스턴스를 변경하는 것은 더욱 안 된다.

 

G15 : 선택자 인수

- 선택자 인수는 목적을 기억하기 어렵게 하고 여러 기능을 가진 함수를 하나로 조합한다.

 

G16 : 모호한 의도

- 행을 바꾸지 않고 표현한 수식, 형가리식 표기법, 매직 번호 등을 지양하라.

 

G17 : 잘못 지운 책임

- 독자가 자연스럽게 기대할 위치에 코드를 배치하라.

- 예시) PI 상수

- getTotalHours(), saveTimeCard() 어디서 총계를 계산해야 할까?

 

G18 : 부적절한 static 함수

- 재정의할 가능성이 있는 함수는 static으로 선언해서는 안 된다.

 

G19 : 서술적 변수

- 임시변수를 자주 쓰고 임시변수에 서술적인 이름을 붙인다.

 

G20 : 이름과 기능이 일치하는 함수

- Date newDate = date.add(5); 

- 5일을 더하는건지, 5주? 5시간? 코드만 봐서는 알수가 없기 때문에 알아볼수 있는 이름을 붙여야 한다.

 

G21 : 알고리즘을 이해하라.

- 구현이 끝나면 함수가 돌아가는 방식을 확실하게 이해하는지 확인하라.

 

G22 : 논리적 의존성은 물리적으로 드러내라.

 

G23 : if/else 혹은 switch/case문보다 다형성을 사용하라. 같은 조건문이 반복되면 클래스로 분리한다.

 

G24 : 표준 표기법을 따르라

- 팀 내에서 정한 표준을 지키자.

 

G25 : 매직 숫자는 명명된 상수로 교체하라

- 매직숫자는 의미가 분명하지 않은 토큰을 의미한다.

 

G26 : 정확하라

- 결정을 내리는 이유가 분명해야 한다.

- 예외가 발생할 가능성이 있다면 예외처리를 해주어야 한다.

 

G27 : 관례보다 구조를 사용하라

- 관례는 강제하기 어렵기 때문이다.

 

G28 : 조건을 캡슐화하라

- 조건의 의도를 분명히 밝히는 함수로 표현하라.

 

G29 : 부정 조건은 피하라

- 부정 조건은 긍정 조건보다 이해하기 어렵다.

 

G30 : 함수는 한 가지만 해야 한다.

 

G31 : 숨겨진 시간적인 결합

- 함수를 짤 때는 함수 인수를 적절히 배치해 함수가 호출되는 순서를 명백히 드러낸다.

 

G32 :  일관성을 유지하라

- 구조가 일관성이 있다면 남들도 일관성을 따르고 보존한다.

 

G33 : 경계 조건을 캡슐화하라

- 코드 여기저기에 +1이나 -1을 흩어 놓지 않는다.

 

G34 : 함수는 추상화 수준을 한 단계만 내려가야 한다.

- 함수 내 모든 문장은 추상화 수준이 동일해야 한다.

- 추상화 수준은 함수 이름이 의미하는 작업보다 한 단계만 낮아야 한다.

 

G35 : 설정 정보는 최상위 단계에 둬라

- 저차원 함수에 상수 값을 정의하면 안 된다.

 

G36 : 추이적 탐색을 피하라

- a.getB().getC().doSomething()  -> a는 c를 알 필요가 없다

- a.doSomeThing()  -> 으로 충분하다.

 

자바 (JAVA)

 

J1 : 긴 import 목록을 피하고 와일드카드를 사용하라

- import package.*;   -> 의존성을 줄일 수 있다.

 

J2 : 상수는 상속하지 않는다.

- 상수를 인터페이스에 넣은 다음 그 다음 인터페이스를 상속해 해당 상수를 사용하면 안된다!

- 대신 static import를 사용한다.

- 예시) import static PayrollConstants.*;

 

J3 : 상수 대 enum

- 상수를 enum으로 대체할 수 있으면 enum으로 바꿔라.

 

이름 (NAME)

 

N1 : 서술적인 이름을 사용하라

- 숫자와 기호가 섞이게 사용하지 마라.

 

N2 : 적절한 추상화 수준에서 이름을 선택하라

- 구현을 드러내는 이름은 피하라.

- 작업 대상 클래스나 함수가 위치하는 추상화 수준을 반영하는 이름을 선택하라.

 

N3 : 가능하다면 표준 명명법을 사용하라.

- 프로젝트에 유효한 의미가 담긴 이름을 많이 사용

 

N4 : 명확한 이름

- 함수나 변수의 목적을 명확히 밝히는 일므을 선택하라.

 

N5 : 긴 범위는 긴 이름을 사용하라

- 이름 길이는 범위 길이에 비례해야 한다.

 

N6 : 인코딩을 피하라

- 요즘 IDE는 인코딩 정보를 대부분 지원해준다.

 

N7 : 이름으로 부수효과를 설명하라

- 함수, 변수, 클래스가 하는 일을 모두 기술하는 이름을 사용한다.

 

테스트 (TEST)

 

T1 : 불충분한 테스트

- 테스트는 잠재적으로 깨질 만한 부분을 모두 테스트해야 한다.

 

T2 : 커버리지 도구를 사용하라

- 테스트가 빠진 부분이나 죽은 코드를 쉽게 발견할 수 있다.

 

T3 : 사소한 테스트를 건너뛰지 마라.

- 사소한 테스트가 제공하는 문서적 가치는 구현에 드는 비용을 넘어선다.

 

T4 : 무시한 테스트는 모호함을 뜻한다.

- 선택 기준은 모호함이 존재하는 테스트 케이스가 컴파일이 가능한지 불가능한지에 달려있다.

 

T5 : 경계 조건을 테스트하라

- 경계 조건에서 버그가 나오는 경우가 흔하다.

 

T6 : 버그 주변은 철저히 테스트하라.

- 버그는 모여있는 경향이 있다.

 

T7 : 실패 패턴을 살펴라

- 테스트 케이스를 꼼꼼하게 작성하면 실패하는 패턴으로 문제를 파악할 수 있다.

 

T8 : 테스트 커버리지 패턴을 살펴라

- 통과하는 테스트가 실행하거나 실행하지 않는 코드를 살펴보면 실패하는

  테스트케이스의 실패 원인이 드러난다.

 

T9 : 테스트는 빨라야 한다.

- 느린 테스트 코드는 실행하지 않게 된다.