냄새와 휴리스틱
다양한 코드 냄새(코드를 좋지 않게 짠 경우)와 코드를 짜면서 사용하는 기교, 휴리스틱을 소개한다.
아래의 경우들은 모두 바람직하지 않은 관습들의 나열임
주석
C1: 부적절한 정보
소스 코드 관리 시스템, 버그 추적 시스템, 이슈 추적 시스템 등 다른 시스템에 저장할 정보는 주석으로 적절치 않음
C2: 쓸모 없는 주석
오래된 주석, 엉뚱한 주석, 잘못된 주석은 더 이상 쓸모가 없음
=> 쓸모 없는 주석은 코드와 무관하게 따로 놀며 코드를 그릇된 방향으로 이끎
C3: 중복된 주석
코드만으로 충분한데 구구절절 설명하는 주석은 불필요함
C4: 성의 없는 주석
문법과 구두점을 올바로 사용하고, 간결하고 명료하게 작성한다.
C5: 주석 처리된 코드
주석 처리된 코드는 아무도 그 쓰임을 모르며, 매일매일 낡아감
소스 코드 관리 시스템이 기억하기 때문에 삭제해도 된다.
환경
E1: 여러 단계로 빌드하는 것
빌드는 간단히 한 단계로 끝나야 하며, 한 명령으로 빌드할 수 있어야 한다.
E2: 여러 단계로 테스트하는 것
모든 단위 테스트는 한 명령으로 돌려야 한다.
함수
F1: 너무 많은 인수
함수에서 인수 개수는 작을수록 좋다.
F2: 출력 인수
출력 인수는 직관적이지 못하다. 일반적으로 독자는 인수를 입력으로 간주
출력 인수 대신 함수가 속한 객체의 상태를 변경하는 방법을 쓰자.
F3: 플래그 인수
플래그 인수는 함수가 여러 기능을 수행한다는 증거 -> 혼란을 초래하므로 피해야 마땅
F4: 죽은 함수
아무도 호출하지 않는 함수는 삭제한다.
일반
G1: 한 소스 파일에 여러 언어를 사용하는 것
소스 파일 하나에 언어 하나만 사용하는 방식이 가장 좋다.
-> 소스 파일에서 언어 수와 범위를 최대한 줄여야 함
G2: 당연한 동작을 구현하지 않는 것
최소 놀람의 원칙에 의거해 함수나 클래스는 다른 프로그래머가 당연하게 여길 만한 동작과 기능을 제공해야 함
당연한 동작을 구현하지 않으면 코드를 읽거나 사용하는 사람이 함수 이름만으로 함수 기능을 직관적으로 예상하기 어렵다.
G3: 경계를 올바로 처리하지 않는 것
코드의 모든 경계 조건과 구석진 곳에서 잘 동작하는지를 증명해야 한다.
-> 모든 경계 조건을 찾아내고 모든 경계 조건을 테스트하는 테스트 케이스를 작성해야 함
G4: 안전 절차 무시
안전 절차를 무시하면 위험함.
-> serialVersionUID를 직접 제어한다든지, 컴파일러 경고를 끈다든지, 실패하는 테스트 케이스를 미뤄두는 태도는 위험함
G5: 중복
코드에서 중복이 있으면 안 됨 -> 중복을 발견할 때마다 추상화할 기회로 간주하라.
- 똑같은 코드가 여러 차례 나올 경우 : 중복을 간단한 함수로 교체
- 여러 모듈에서 일련의 switch/case나 if/else 문으로 똑같은 조건을 거듭 확인하는 경우 : 중복을 다형성으로 대체
- 알고리즘이 유사하나 코드가 서로 다른 중복 : TEMPLATE METHOD 패턴이나 STRATEGY 패턴으로 중복 제거
G6: 추상화 수준이 올바르지 못할 경우
모든 저차원 개념은 파생 클래스(자식 클래스)에 넣고, 고차원 개념은 기초 클래스(부모 클래스)에 넣는다.(기초 클래스는 구현 정보에 무지해야 함)
고차원 개념과 저차원 개념을 섞어서는 안 된다.
G7: 기초 클래스가 파생 클래스에 의존하는 것
추상화의 가장 흔한 이유는 고차원 기초 클래스 개념을 저차원 개념으로부터 분리해 독립성을 보장하기 위해서임
=> 기초 클래스가 파생 클래스를 아예 몰라야 마땅함.
G8: 과도한 정보
잘 정의된 모듈은 인터페이스가 아주 작으며, 잘 정의된 인터페이스는 많은 함수를 제공하지 않음
클래스가 제공하는 메서드 수는 작을수록 좋으며, 함수가 아는 변수 수도 작을수록 좋고, 클래스에 들어있는 인스턴스 변수 수도 작을수록 좋다.
=> 정보를 제한하면 결합도가 낮아진다.
G9: 죽은 코드
죽은 코드 : 실행되지 않은 코드. (ex: 불가능한 조건을 확인하는 if문, throw문이 없는 try문에서 catch 블록)
죽은 코드는 설계가 변해도 제대로 수정되지 않아 발견하는 대로 시스템에서 제거해야 함
G10: 수직 분리
변수와 함수는 사용되는 위치에 가깝게 정의하며, 비공개 함수는 처음으로 호출한 직후에 정의한다.
G11: 일관성 부족
어떤 개념을 특정 방식으로 구현했다면 유사한 개념도 같은 방식으로 구현한다.
한번 선택한 표기법을 그대로 따른다.
G12: 잡동사니
비어 있는 기본 생성자, 아무도 사용하지 않는 변수, 아무도 호출하지 않는 함수, 정보를 제공하지 못하는 주석 등 불필요한 코드들을 모두 제거해야 한다.
G13: 인위적 결합
서로 무관한 개념을 인위적으로 결합하지 않는다. (ex: enum을 특정 클래스에 속하도록 만드는 등)
=> 함수, 상수, 변수를 선언할 때는 올바른 위치를 고민한다.
G14: 기능 욕심
클래스 메서드는 다른 클래스의 변수와 함수에 관심을 가져서는 안 됨
-> 메서드가 다른 객체의 내용을 조작한다면 그 객체 클래스의 범위를 욕심내는 것임
어쩔 수 없는 경우를 제외하면, 한 클래스에서 다른 클래스의 속사정을 알아야 하는 기능 욕심은 제거하는 편이 좋다.
'독서일지 > 클린 코드' 카테고리의 다른 글
클린 코드 독서일지 - Day 41 (0) | 2023.12.18 |
---|---|
클린 코드 독서일지 - Day 40 (0) | 2023.12.17 |
클린 코드 독서일지 - Day 38 (0) | 2023.12.13 |
클린 코드 독서일지 - Day 37 (0) | 2023.12.13 |
클린 코드 독서일지 - Day 36 (0) | 2023.12.12 |