Chapter 02 - 의미 있는 이름
의도를 분명히 밝혀라
- 변수, 함수, 클래스는 존재 이유, 수행 기능, 사용 방법을 주석 없이 이름만으로도 파악할 수 있어야 한다.
- 예시1:
int d는 아무 의미도 드러나지 않는다. 주석없이, 측정하려는 값과 단위를 표현하는 이름이 필요하다.1 2 3 4 5 6 7 8
// Bad int d; // 경과 시간(단위: 날짜) // Good int elapsedTimeInDays; int daysSinceCreation; int daysSinceModification; int fileAgeInDays;
- 예시2
- Bad:
theList에 무엇이 들어있는지, 0번째 인덱스는 왜 중요한지, 값 4는 무슨 의미인지 등을 알 수 없다.
1 2 3 4 5 6 7 8 9 10
// Bad List<int[]> theList; public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>(); for (int[] x : theList) if (x[0] == 4) list1.add(x); return list1; }
- 개선1: 변수와 값이 어떤 의미를 갖는지 파악하도록 이름을 지은다.
1 2 3 4 5 6 7 8 9 10 11
List<int[]> gameBoard; static final int STATUS_VALUE = 0; static final int FLAGGED = 4; public List<int[]> getFlaggedCells() { List<int[]> flaggedCells = new ArrayList<>(); for (int[] cell : gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.add(cell); return flaggedCells; }
- 개선2:
int[]대신 클래스로 만들고,FLAGGED상수를 감추는 대신 명시적인 함수를 사용하자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class Cell { private static final int STATUS_VALUE = 0; private static final int FLAGGED = 4; private int[] value; public boolean isFlagged() { return value[STATUS_VALUE] == FLAGGED; } } List<Cell> gameBoard; public List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new ArrayList<>(); for (Cell cell : gameBoard) if (cell.isFlagged()) flaggedCells.add(cell); return flaggedCells; }
- Bad:
그릇된 정보를 피하라
- 나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용하지 마라
- 예를 들어, hp, aix, sco는 유닉스 플랫폼이나 변종을 가리키는 이름이기 때문에 변수 이름으로 적합하지 않다.
List등 컨테이너 유형을 이름에 넣지 마라- 서로 흡사한 이름을 사용하지 않도록 주의하라
- 유사한 개념은 유사한 표기법을 사용하라
- 특히 IDE의 코드 자동 완성 기능을 사용하기 위해(물론 각 개념의 차이는 명백히 드러나야 한다.)
- 비슷해 보이는 문자를 주의하라
- l vs 1 (소문자 L과 숫자 1)
- O vs 0 (대문자 O와 숫자 0)
의미 있게 구분하라
아무런 정보를 제공하지 않는 이름이나 저자 의도가 전혀 드러나지 않는 이름을 사용하지 마라
1 2 3 4 5 6
// Bad public static void copyChars(char[] a1, char[] a2) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } }
1 2 3 4 5 6
// Good public static void copyChars(char[] source, char[] destination) { for (int i = 0; i < source.length; i++) { destination[i] = source[i]; } }
불용어(noise word)를 추가한 이름은 아무 정보도 제공하지 못한다.
- 불용어 예시: info, data, a, an, the, 변수타입
- Product, ProductInfo, ProductData
- NameString, Name
- Cusomer, CusomerInfo, CustomerObject
- moneyAmount, money
- theMessage, message
발음하기 쉬운 이름을 사용하라
1
2
3
4
5
6
// Bad
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
}
1
2
3
4
5
6
// Good
class Customer {
private Date generatonTimestamp;
private Date modificationTimestamp;
private final String recordId = "102";
}
검색하기 쉬운 이름을 사용하라
- 짧은 이름보다는 긴 이름을 사용하자
- 이름 길이는 범위 크기(scope)에 비례해야 한다.
1 2 3 4 5
// Bad int s = 0; for (int j = 0; j < 34; j++) { s += (t[j] * 4) / 5; }
1 2 3 4 5 6 7 8 9 10
// Good int realDaysPerIdealDay = 4; final int WORK_DAYS_PER_WEEK = 5; final int NUMBER_OF_TASKS = 34; 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; }
인코딩을 피하라
- 헝가리식 표기법
- 컴파일러와 IDE의 발전으로 인해 사용하지 마라
- 접두어(또는 접미어)를 사용하지 마라
string m_dsc보다는string description을 사용하라
- 인터페이스 클래스와 구현 클래스
- 인터페이스와 구현클래스는 구분을 위해 인코딩이 필요하다
IShapeFactory,ShapeFactory또는ShapeFactory,ShapeFactoryImp-> 선택
- 인터페이스와 구현클래스는 구분을 위해 인코딩이 필요하다
자신의 기억력을 자랑하지 마라
- 코드 읽는이가 변수 이름을 머리속으로 재변환하게 하지마라
- 루프 범위가 아주 작고 다른 이름과 충돌하지 않을 때는 문자 하나의 변수 이름(
i,j,k)는 괜찮다.- 그 외에는 코드 독자가 머리속으로 실제 개념으로 변환이 필요하게하므로 적절하지 못하다.
클래스 이름과 메서드 이름
- 클래스 이름, 객체 이름: 명사, 명사구
- 좋은 예) Customer, WikiPage, Account, AddressParser
- 나쁜 예) Manager, Processor, Data, Info와 같은 단어, 동사
- 메서드 이름: 동사, 동사구
- 좋은 예) postPayment, deletePage, save
- 접근자, 변경자, 조건자에는
get,set,is을 변수명 앞에 붙인다.
- 생성자를 오버로딩할 때는 정적 팩토리 메서드를 사용한다. 이때 메서드명은 인수를 설명하는 이름을 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13
public class Cell { double value; private Cell(double value) { this.value = value; } public static Cell FromRealNumber(double x) { return new Cell(x); } } Cell cell = Cell.FromRealNumber(23.0);
기발한 이름은 피하라
- 기발하거나 재미난 이름보다는 명료한 이름을 선택하라
- 의도를 분명하고 솔직하게 표현하라
한 개념에 한 단어를 사용하라
- 메서드 이름은 독자적이고 일관적이어야 한다.
- 이름이 다르면 독자는 당연히 클래스가 다르고, 타입도 다르리라 생각한다.
- 예를 들어, 동일 코드 기반에
controller,manager,driver를 섞어 쓰면 혼란스럽다.
- 예를 들어, 동일 코드 기반에
말 장난을 하지 마라
- 다른 개념에 같은 단어를 사용하지 마라
- 기존 값 2개를 더하거나 이어서 새로운 값을 만드는 메서드를
add()로 만들었다고 해서, 집합에 값 하나를 추가하는 메서드를add()로 이름 짓는건 옳지 않다.
- 기존 값 2개를 더하거나 이어서 새로운 값을 만드는 메서드를
- 프로그래머는 집중적인 탐구가 필요한 코드가 아니라 대충 훑어봐도 이해할 코드 작성이 목표다.
해법 영역에서 가져온 이름을 사용하라
- 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등은 사용해도 괜찮다.
- 예를 들어,
JobQueue라는 이름는 프로그래머라면 이해한다. - 적절한 프로그래머 용어가 없다면 문제 영역(domain)에서 이름을 가져온다.
의미 있는 맥락을 추가하라
- 클래스, 함수, 이름 공간(namespace)에 넣어서 맥락(context)을 부여하라
- 모든 방법이 실패하면, 마지막 수단으로 접두어를 붙인다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// 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); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
// 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라는 애플리케이션을 만든다고 해서, 모든 클래스 이름 앞에GSD를 붙이는 것은 좋지 않다.accountAddress와customerAddress는Address클래스의 인스턴스로는 좋은 이름이 아니다.
This post is licensed under CC BY 4.0 by the author.