의도를 분명히 밝혀라
- 변수, 함수, 클래스의 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말이다.
// Bad
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList) {
if (x[0] == 4) {
list1.add(x);
}
}
return list1;
}
// Good
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard) {
if (cell[STATUS_VALUE] == FLAGGED) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
`if (cell[STATUS_VALUE] == FLAGGED)` 또한
`if (cell.isFlagged())` 로 바꿔주면 좋다.
그릇된 정보를 피하라
- 중의적으로 해석할 수 있는 이름 지양하기
- 여러 계정을 그룹으로 묶을 때, 실제 List가 아니라면 `accountList`라 명명하지 말 것
- 차라리 accounts로 하기
- 소문자 L, 대문자 O 조심 → 소문자 L은 숫자 1처럼, 대문자 O는 숫자 0처럼 보인다.
의미 있게 구분하라
- 연속적인 숫자를 덧붙인 이름 (a1, a2..)은 아무런 정보를 제공하지 못하고 저자 의도가 전혀 드러나지 않는다.
- 클래스에 Info, Data와 같은 불용어를 붙이지 말자.
- ProductInfo / ProductData
- Customer / CustomerObject
- theMessage / message
발음하기 쉬운 이름을 사용하라
- 축약어를 사용해서 발음하기 어렵게 만들지 말자.
//bad
private Date genymdhms;
private Date modymdhms;
//good
private Date generationTimestamp;
private Date modificationTimestamp;
검색하기 쉬운 이름을 사용하라
- 상수를 사용하자
- 문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 쉽게 눈에 띄지 않는다는 문제점이 있다.
- 이름 크기는 범위 크기에 비례해야 한다.
- 변수나 상수를 코드 여러 곳에서 사용한다면 검색하기 쉬운 이름이 바람직하다.
인코딩을 피하라
- 변수명에 해당 변수의 타입(String, Int..)을 적지 말자
- 멤버 변수에 접두어를 붙이지 말자
- private String m_desc; → private String description;
- 인터페이스와 구현 클래스
- 구현 클래스에 인코딩하자.
- ShapeFactory / ShapeFactoryImpl
자신의 기억력을 자랑하지 마라
독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못하다.
문자 하나만 사용하는 변수 이름은 문제가 있다.(루프에서 반복 횟수를 세는 변수 i, j, k는 괜찮다.)
클래스 이름
- 명사나 명사구가 적합하다.
- Customer, WikiPage, Account, AddressParser
- Manager, Processor, Data, Info와 같은 단어는 피하자
- 동사는 사용하지 않는다.
메서드 이름
- 동사 혹은 동사구가 적합하다.
- postPayment, deletePayment, deletePage, save
- 접근자, 변경자, 조건자는 get, set, is로 시작하자. (추가: should, has 등도 가능)
- 생성자를 오버로드할 경우 정적 팩토리 메서드를 사용하고 해당 생성자를 private으로 선언한다.
- `Complex fulcrumPoint = Complex.FromRealNumber(23.0);`
- 위 코드보다 아래 코드가 좋다.
- `Complex fulcrumPoint = new Complex(23.0);`
기발한 이름은 피하라
- 특정 문화에서만 사용되는 농담은 피하는 편이 좋다.
- 은어 지양
한 개념에 한 단어를 사용하라
- 추상적인 개념 하나에 단어 하나를 사용하자.
- 똑같은 메서드를 클래스마다 fetch, retrieve, get으로 제각각 부르면 혼란스럽다.
- Controller, Manager도 동일함 뭐가 다른지 모른다.
말장난을 하지 마라
- 한 단어를 두 가지 목적으로 사용하지 마라. 기존 add메서드와 맥락이 다르면 add 말고 append나 isnert를 사용할 것
- = 맥락이 다른 메서드의 이름을 구분하자.
해법 영역 용어를 사용하자
- 전산용어, 알고리즘 이름, 패턴 이름, 수학 용어 등은 사용하자.
문제 영역에서 가져온 이름을 사용하라
- 적절한 프로그래머 용어가 없거나 문제영역과 관련이 깊은 용어의 경우 문제 영역 용어를 사용하자.
의미 있는 맥락을 추가하라
firstName, lastName, street, city, state, zipcode라는 변수가 있으면 이는 주소라는 사실을 금방 알아챈다.
하지만 어느 메서드가 state라는 변수 하나만 사용한다면 주소 일부라는 사실을 금방 알아챌까?
addr라는 접두어를 추가해 addrFirstName, addrState라 쓰면 맥락이 좀 더 분명해진다.
물론 Address라는 클래스를 생성하는 게 best!
⭐예시
// Bad
private void printGuessStatistics(char candidate, int count) {
String number;
String verb;
String pluralModifier;
if (count == 0) {
number = "no";
verb = "are";
pluralModifier = "s";
} else if (count == 1) {
number = "1";
verb = "is";
pluralModifier = "";
} else {
number = Integer.toString(count);
verb = "are";
pluralModifier = "s";
}
String guessMessage = String.format("There %s %s %s%s", verb, number, candidate, pluralModifier );
print(guessMessage);
}
// Good
public class GuessStatisticsMessage {
private String number;
private String verb;
private String pluralModifier;
public String make(char candidate, int count) {
createPluralDependentMessageParts(count);
return String.format("There %s %s %s%s", verb, number, candidate, pluralModifier );
}
private void createPluralDependentMessageParts(int count) {
if (count == 0) {
thereAreNoLetters();
} else if (count == 1) {
thereIsOneLetter();
} else {
thereAreManyLetters(count);
}
}
private void thereAreManyLetters(int count) {
number = Integer.toString(count);
verb = "are";
pluralModifier = "s";
}
private void thereIsOneLetter() {
number = "1";
verb = "is";
pluralModifier = "";
}
private void thereAreNoLetters() {
number = "no";
verb = "are";
pluralModifier = "s";
}
}
불필요한 맥락을 없애라
고급 휘발유 충전소(Gas Station Deluxe)라는 애플리케이션을 짠다고 해서 모든 클래스 이름을 GSDxx로 짜지 말자.
IDE 자동 완성 기능을 방해한다.
'📝 끄적끄적 > 📖 Clean Code' 카테고리의 다른 글
3. 함수 (0) | 2023.10.29 |
---|---|
1. 깨끗한 코드 (0) | 2023.10.17 |