1 of 25

2. 의미있는 이름 �이름을 잘 짓는 것이 중요하며, 관련 규칙을 소개한다

2 of 25

의도를 분명히 밝혀라

  • 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다.
  • 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말이다
  • 변수(혹은 함수나 클래스)의 존재 이유는? 수행 기능은? 사용 방법은?

int d; // 경과 시간(단위: 날짜)

int elapsedTimeInDays;

int daysSinceCreation;

int daysSinceModification;

int fileageInDays;

3 of 25

의도를 분명히 밝혀라

  • 지뢰찾기 게임, theList가 게임판 🡪 gameBoard

public List<int[]> getThem() {

List<int[]> list1= new ArrayList<int[]>();

for (int[] x : theList)

if (x[0] = 4)

list1.add(x);

return list1;

}

public List<int[]> getFlaggedCells() {

List<int[]> flaggedCells = new ArrayList<int[]>();

for (int[] cell: gameBoard)

if (cell[STATUS_VALUE] = FLAGGED)

flaggedCells.add(cell);

return flaggedCells;

}

4 of 25

의도를 분명히 밝혀라

public List<Cell> getFlaggedCells(){

List<Cell> flaggedCells = new ArrayList<Cell>();

for (Cell cell : gameBoard)

if (cell.isFlagged())

flaggedCells.add(cell);

return flaggedCells;

}

public List<int[]> getThem() {

List<int[]> list1= new ArrayList<int[]>();

for (int[] x : theList)

if (x[0] = 4)

list1.add(x);

return list1;

}

5 of 25

그릇된 정보를 피하라

  • 프로그래머는 코드에 그릇된 단서를 남겨서는 안 된다.
  • 나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용해도 안 된다.
  • 유닉스 플랫폼 이나 유닉스 변종을 가리키는 이름은 변수 이름으로 적합하지 않다.
  • 직각삼각형의 빗변을 구현할 때 hp라는 변수 이름은 독자에게 그릇된 정보를 제공한다.
  • 여러 계정을 그룹으로 묶을 때, List가 아니라면 accountList라 명명하지 않는다.
  • 서로 흡사한 이름을 사용하지 않도록 주의한다.
  • 유사한 개념은 유사한 표기법을 사용한다.
  • 최신 자바 환경은 코드 자동 완성 기능을 제공한다.
  • 이름으로 그릇된 정보를 제공하는 변수 이름은 사용하지 않는다.

6 of 25

의미 있게 구분하라

  • 코드를 구현할 때, 컴파일러나 인터프리터만 통과하려는 생각으로 이름을 지어서는 안 된다.
  • 이름이 달라야 한다면 의미도 달라져야 한다.
  • 클래스나 변수의 이름을 지을 때 읽는 사람이 차이를 알도록 지어야 한다.
    • customerInfo는 customer, accountData account, theMessage message와 구분이 안 된다.

7 of 25

의미 있게 구분하라

  • 연속된 숫자를 덧붙인 이름이나 불용어는 적절하지 못하다.
    • al, a2, ..., aN
    • 이름만 다르고 개념이 같은 경우에는 불용어(Info, Data, a, an, the)를 사용하지 말아야 한다.
    • 변수 이름에 variable이라는 단어는 단연코 금물이다. 
    • 표 이름에 table이라는 단어도 마찬가지다. 
    • NameString --> Name, CustomerObject --> Customer

public static void copyChars(char a1[], char a2[]) {

for (int i = 0; i < al.length; i++) {

a2[i] = al[i];

}

} �함수 인수 이름으로 source와 destination을 사용하면 코드 읽기가 쉬워진다.

8 of 25

발음하기 쉬운 이름을 사용하라

  • 발음하기 쉬운 이름을 선택하는 것이 중요
  • "genymdhms"와 같은 발음하기 어려운 변수명을 사용한 예시
  • 발음하기 쉬운 이름을 사용하면 코드 이해가 쉬워지며, 지적인 대화가 가능함

class DtaRcrd102 { private Date genymdhms; private Date modymdhms; private final String pszqint="102"; /* ... */ }; VSclass Customer { private Date generationTimestamp; private Date modificationTimestamp; private final String recordId="102"; /* ... */ };

class DtaRcrd102 { private Date genymdhms; private Date modymdhms; private final String pszqint="102"; /* ... */ }; VSclass Customer { private Date generationTimestamp; private Date modificationTimestamp; private final String recordId="102"; /* ... */ };

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";

/* ... */

};

9 of 25

검색하기 쉬운 이름을 사용하라

  • 문자 하나를 사용하는 이름과 상수는 검색이 어려울 수 있다.
  • 숫자를 사용하는 상수도 검색이 어렵고, 다른 의도로 사용되는 경우가 있을 수 있다.
  • 긴 이름이 짧은 이름보다 검색하기 쉽다.
  • 간단한 메서드에서 로컬 변수는 한 문자를 사용할 수 있지만, 변수나 상수를 여러 곳에서 사용할 경우 검색하기 쉬운 이름이 좋다.

10 of 25

검색하기 쉬운 이름을 사용하라

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;

}

11 of 25

헝가리식 표기법과 인코딩

  • 인코딩한 이름은 거의가 발음하기 어려우며 오타가 생기기도 쉽다.
  • 과거에는 변수 이름의 길이가 제한되어 있어 헝가리식 표기법 등의 명명 규칙이 필요했다.
  • 현재는 프로그래밍 언어가 다양한 타입을 지원하고 컴파일러가 타입을 강제하므로 변수 이름에 타입을 인코딩할 필요가 없어졌다.
  • 변수, 함수, 클래스 이름이나 타입을 바꾸기가 어려워지며, 인코딩 방식이 읽기도 어려워지고 독자를 오도할 가능성이 커진다.
  • 헝가리식 표기법은 변수의 목적과 의미를 더 쉽게 이해할 수 있도록 하기 위해 만들어졌으나, 현대 프로그래밍 언어에서는 덜 일반적으로 사용된다.

12 of 25

멤버 변수 접두어

  • 클래스와 함수는 접두어가 필요없을 정도로 작아야 마땅하다. 
  • 멤버 변수를 다른 색상으로 표시하거나 눈에 띄게 보여주는 IDE를 사용해야 마땅하다. �

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;

}

}

13 of 25

인터페이스 클래스와 구현 클래스

  • ABSTRACT FACTORY 패턴을 구현할 때, 인터페이스 클래스와 구현 클래스의 이름을 어떻게 지어야 할지 고민해야 한다.
  • 인터페이스 이름에 접두어를 붙이지 않는 편이 좋다고 생각한다.
  • 인터페이스 이름에 접두어 I는 주의를 흐트리고 과도한 정보를 제공할 수 있다.
  • 인터페이스 클래스 이름과 구현 클래스 이름 중 하나를 인코딩해야 한다면 구현 클래스 이름을 선택하는 것이 좋다.
  • 내가 다루는 클래스가 인터페이스라는 사실을 남에게 알리고 싶지 않다. 클래스 사용자는 그냥 ShapeFactory라고만 생각하면 좋겠다.

14 of 25

자신의 기억력을 자랑하지 마라

  • 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못하다.
  • 자신만 아는 이름으로 작명하지 말라
  • 기존에 a,b 를 사용한다고 c를 사용하면 안된다.

15 of 25

클래스 이름과 메서드 이름

  • 클래스 이름과 객체 이름은 명사나 명사구가 적합하다. Customer, WikiPage, Account, AddressParser 등이 좋은 예다. 
    • Manager, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다. 
  • 메서드 이름은 동사나 동사구가 적합하다. postPayment, deletePage, save 등이 좋은 예다. 
    • 접근자(Accessor), 변경자(Mutator), 조건자(Predicate)는 javabean 표준에 따라 값 앞에 get, set, is를 붙인다. 

16 of 25

기발한 이름은 피하라

  • 재미난 이름보다 명료한 이름을 선택하라.
    • kill() 대신에 whack()이라 부르거나 Abort() 대신 eatMyShort()라 부르면 안된다.
  • 특정 문화에서만 사용하는 농담은 피하는 편이 좋다. 

17 of 25

의도를 분명하고 솔직하게 표현하라

  • 한 개념에 한 단어를 사용하라 
  • 추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다. 
  • 예> 똑같은 메서드를 클래스마다 fetch, retrieve, get으로 제각각 부르면 혼란스럽다.
  • 예> 동일 코드 기반에 controller, manager, driver를 섞어 쓰면 혼란스럽다.

18 of 25

말장난을 하지 마라

  • 한 단어를 두 가지 목적으로 사용하지 마라. 다른 개념에 같은 단어를 사용한다면 그것은 말장난에 불과하다.

19 of 25

해법 영역에서 가져온 이름을 사용하라

  • 코드를 읽을 사람도 프로그래머라는 사실을 명심한다. 그러므로 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등을 사용해도 괜찮다. 
  • 모든 이름을 문제 영역(domain)에서 가져오는 정책은 현명하지 못하다. 
  • 같은 개념을 다른 이름으로 이해하던 동료들이 매번 고객에게 의미를 물어야하기 때문이다. 

20 of 25

문제 영역에서 가져온 이름을 사용하라

  • 적절한 '프로그래머 용어'가 없다면 문제 영역에서 이름을 가져온다.
  • 코드를 보수하는 프로그래머가 분야 전문가에게 의미를 물어 파악할 수 있다. 
  • 우수한 프로그래머와 설계자라면 해법 영역과 문제 영역을 구분할 줄 알아야 한다. 
  • 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와야 한다. 

21 of 25

의미 있는 맥락을 추가하라 

  • 스스로 의미가 분명한 이름이 없지 않다. 하지만 대다수 이름은 그렇지 못하다. 그래서 클래스, 함수, 이름 공간에 넣어 맥락을 부여한다. 모든 방법이 실패하면 마지막 수단으로 접두어를 붙인다.� 예를 들어, firstName, lastName, street, houseNumber, city, state, zipcode 라는 변수가 있다. 변수를 훑어보면 주소라는 사실을 금방 알아챈다. 하지만 어느 메서드가 state라는 변수 하나만 사용한다면? 변수 state가 주소 일부라는 사실을 금방 알아챌까? addr라는 접두어를 추가해 addrFirstName, addrLastName, addrState라 쓰면 맥락이 좀 더 분명해진다. 변수가 좀 더 큰 구조에 속한다는 사실이 적어도 독자에게는 분명해진다. 물론 Address라는 클래스를 생성하면 더 좋다.

22 of 25

의미 있는 맥락을 추가하라 

목록 2-1 맥락이 불분명한 변수

private void printGuessStatistics (char candidate, int count) {

String number;

String verb;

String pluralModifier;

if (count = 0) {

number = "no";

verb = "are";

pluralModifier= "";

} else if (count = 1) {

number = "1";

verb = "is";

pluralModifier = "";

} else {

}

number = Integer.toString(count);

verb = "are";

plura Modifier = "s";

String guessMessage = String.format(

"There %s %s %s%s", verb, number, candidate, pluralModifier

);

print(guessMessage);

}

23 of 25

의미 있는 맥락을 추가하라 

목록 2-2 맥락이 분명한 변수

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, plura Modifier );

}

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 = "";

}

}

24 of 25

불필요한 맥락을 없애라

  • '고급 휘발유 충전소Gas Station Deluxe'라는 애플리케이션을 짠다고 가정하자. 모든 클래스 이름을 GSD로 시작하겠다는 생각은 전혀 바람직하지 못하다.�솔직히 전봇대로 이 쑤시는 격이다. IDE에서 G를 입력하고 자동 완성 키를 누르면 IDE는 모든 클래스를 열거한다. 현명하지 못하다. IDE는 개발자를 지원하는 도구다. IDE를 방해할 이유는 없다.
  • 일반적으로는 짧은 이름이 긴 이름보다 좋다. 단, 의미가 분명한 경우에 한해 서다. 이름에 불필요한 맥락을 추가하지 않도록 주의한다. accountAddress와 customerAddress는 Address 클래스 인스턴스로는 좋은 이름이나 클래스 이름으로는 적합하지 못하다. Address는 클래스 이름으로 적합하다. 포트 주소, MAC 주소, 웹 주소를 구분해야 한다면 PostalAddress, MAC, URI라는 이름도 괜찮겠다. 그러면 의미가 좀 더 분명해진다. 

25 of 25

마치면서 

  • 사람들이 이름을 바꾸지 않으려는 이유 하나는 다른 개발자가 반대할까 두려워서다. 
  • 우리들 대다수는 자신이 짠 클래스 이름과 메서드 이름을 모두 암기하지 못한다. 
  • 암기는 요즘 나오는 도구에게 맡기고, 우리는 문장이나 문단처럼 읽히는 코드 아니면 (정보를 표시하는 최선의 방법이 항상 문장만은 아니므로) 적어도 표나 자료 구조처럼 읽히는 코드를 짜는 데만 집중해야 마땅하다.