들어가면서
소프트웨어에서 이름은 어디나 쓰인다. 여기저기 도처에서 이름을 사용한다. 이름을 잘 지으면 여러모로 편하다.
의도를 분명히 밝혀라
좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다. 그러므로 이름을 주의깊게 살펴 더 나은 이름이 떠오르면 개선해야 한다.
굵직한 질문에 모두 답할수 있어야 한다. ( 변수의 존재 이유는?, 수행 기능은?, 사용 방법은? 따로 주석이 필요한지?)
int d; // 경과 시간(단위: 날짜)
위의 이름 d는 아무 의미가 없다.
int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;
위와 같이 의도가 드러나는 이름을 사용하면 코드 이해와 변경이 쉽다.
다음 코드는 무엇을 할까?
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
코드가 하는 일을 짐작하기 어렵다. 문제는 코드의 단순성이 아니라 코드의 함축성이다. 코드 맥락이 코드 자체에 명시적으로 드러나지 않는다. 위 코드는 암암리에 독자가 다음의 정보를 안다고 가정한다.
- theList에 무엇이 들었는가?
- theList에서 0번째 값이 어째서 중요한가?
- 값 4는 무슨 의미인가?
- 함수가 반환하는 리스트 list1을 어떻게 사용하는가?
단순 이름을 고치는 것만으로 함수가 하는 일을 이해하기 쉬워진다.
그릇된 정보를 피하라
프로그래머는 코드에 그릇된 단서를 남겨서는 안 된다. 이는 코드의 의미를 흐린다.
예를 들어 hp라는 변수는 유닉스 변종을 가리키는 이름이기 때문에 직각삼각형의 빗변(hypotenuse)의 약어로 좋아 보일지라도 독자에게 혼란을 줄 수 있다.
서로 흡사한 이름을 사용하지 않도록 주의한다. 한 모듈에서 XYZController orEfficientHandlingOfStrings라는 이름을 사용하고, 조금 떨어진 모듈에서 XYZControllerForEfficientStorageOfStrings 을 사용하면 ..... 겁나 헷갈린다.
유사한 개념은 유사한 표기법을 사용한다. 일관성이 떨어지는 표기법은 그릇된 정보다.
의미 있게 구분하라
이름이 달라야 한다면 의미도 달라져야 한다. 컴파일러를 통과할지라도 연속된 숫자를 덧붙이거나 불용어를 추가하는 방식은 적절하지 못하다.
public static void copyChars(char a1[], char a2[]) {
for (int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
함수 이름으로 source와 destination을 사용한다면 코드 읽기가 훨씬 쉬워진다.
불용어는 중복이다. variable이나 table같은 단어는 이름으로 쓰면 안된다.
getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();
위와 같이 애매한 변수로 이름을 지으면 혼란만 야기한다.
발음하기 쉬운 이름을 사용하라
사람들은 단어에 능숙하고 단어는 개념의 전달이 용이하다.
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
/* ... */
};
class Customer {
private Date generationTimestamp;
private Date modificationTimestamp;
private final String recordId = "102";
/* ... */
}
위의 코드를 보면 명확해진다.
검색하기 쉬운 이름을 사용하라
문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 눈에 띄지 않는다.
또한 나중에 grep을 이용한 검색에서 모든 단어가 검색되어 제대로 된 검색이 불가능해진다.
for (int j=0; j<34; j++) {
s += (t[j]*4)/5;
}
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int j=0; j < NUMBER_OF_TASKS; j++) {
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK);
sum += realTaskWeeks;
}
인코딩을 피하라
유형이나 범위 정보 까지 인코딩에 넣으면 해독도 어려워지고 또 인코딩을 익히느라 시간또한 쓰게 된다. 개발자는 할게 많다......불필요한 부담은 없애자!
- 헝가리식 표기법
요즘 시대는 변수이름에 타입을 인코딩할 필요가 없다(실제로 나는 사용해본적 없음). 그러므로 이름에 변수이름에 헝가리안 표기법으로 변수 타입을 넣지 않아도 된다.
- 멤버 변수 접두어
이전에는 멤버 변수 접두어에 m_를 붙였었나 보다. 그러지 말자.
public class Part {
private String m_dsc; // 설명 문자열
void setName(String name) {
m_dsc = name;
}
}
_________________________________________________
public class Part {
String description;
void setDescription(String description) {
this.description = description;
}
}
- 인터페이스 클래스와 구현 클래스
인터페이스와 구현클래스의 명명을 어떻게 할 것인가. 이건 사람마다 다르겠지만 쉽게 글쓴이는 인터페이스 뒤에 Impl이라고 붙이는 것을 선호한다고 한다.
ShapeFactoryImp나 심지어 CShapeFactory가 IShape Factory보다 좋다고 한다.
자신의 기억력을 자랑하지 마라
보통 프로그래머는 머리가 똑똑하다고 한다. 그렇다고 그들이 만능은 아니다.
클래스 이름
클래스 이름과 객체 이름은 명사나 명사구가 적합하다.
메서드 이름
메서드 이름은 동사나 동사구가 적합하다. 접근자, 변경자, 조건자는 javabean 표준에 따라 값 앞에 get,set,is를 붙인다.
기발한 이름은 피하라
이름이 너무 기발하면 공감대가 비슷한 사람만 이름을 기억해 낸다. 재미난 이름보다 명료한 이름을 선택하라
한 개념에 한 단어를 사용하라
추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다.
말장난을 하지 마라
한 단어를 두 가지 목적으로 사용하지 마라. 다른 개념에 같은 단어를 사용한다면 이는 말장난에 불과하다.
해법 영역에서 가져온 이름을 사용하라
코드를 읽을 사람도 프로그래머이다. 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어를 사용하면 서로에게 친숙하다.
문제 영역에서 가져온 이름을 사용하라
적절한 프로그래밍 언어가 없다면 문제 영역에서 이름을 가져온다. 그러면 그 배경지식을 습득하면서 배울수 있다.
의미 있는 맥락을 추가하라
스스로 의미가 분명한 이름이 없지 않다. 하지만 대다수 이름은 그렇지 못하다. 그래서 클래스, 함수, 이름 공간에 넣어 맥락을 부여한다. 모든 방법이 실패하면 마지막 수단으로 접두어를 붙인다.
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);
}
함수 이름은 맥락 일부만 제공하며, 알고리즘이 나머지 맥락을 제공한다. 위의 함수를 끝까지 읽어보고 나서야 변수 세 개가 통계 추측 메시지에 사용된다는 사실이 드러난다.
불필요한 맥락을 없애라
일반적으로는 짧은 이름이 긴 이름보다 좋다. 단, 의미가 분명한 경우에 한해서다. 이름에 불필요한 맥락을 추가하지 않도록 주의한다.
마치면서
좋은 이름을 선택하려면 설명 능력이 뛰어나야 하고 문화적인 배경이 같아야 한다. 이것이 제일 어렵다. 좋은 이름을 선택하는 능력은 기술, 비즈니스, 관리 문제가 아니라 교육 문제다.
여느 코드 개선 노력과 마찬가지로 이름 역시 나름대로 바꿨다가는 누군가 질책할지도 모른다. 그렇다고 코드를 개선하려는 노력을 중단해서는 안 된다.
'책 > Clean Code' 카테고리의 다른 글
[Clean Code] 4장 주석 (0) | 2022.09.20 |
---|---|
[Clean Code] 3장 함수 (0) | 2022.09.19 |
[Clean Code] 1장 깨끗한 코드 (1) | 2022.09.16 |
[Clean Code] 8장 경계 (2) | 2022.09.15 |
[Clean Code] 7장 오류 처리 (0) | 2022.09.14 |