# 2장 의미 있는 이름

## 의도를 분명히 밝혀라

`좋은 이름`을 지으려면 시간이 걸리지만 좋은 이름으로 `절약`하는 시간이 훨씬 더 많다. `변수`나 `함수` 그리고 `클래스` 이름은 다음과 같은 질문에 모두 답해야 한다.

* **변수(혹은 함수나 클래스)의 존재 이유는?**
* **수행 기능은?**
* **사용 방법은?**

주석이 필요하다면 의도를 분명히 드러내지 못했다는 말이다.

#### 다음 코드는 무엇을 할까?

```java
public List<int[]> getThem() {
		List<int[]> list1 = new ArrayList<int[]>();
		for (int[] x : thisList) {
				if (x[0] == 4) {
						list1.add(x);
				}
		}
		return list1;
}
```

위 코드는 코드 맥락이 코드 자체에 명시적으로 드러나지 않는다.

* `thisList`에 무엇이 들어있는가?
* `thisList`에서 0번째 값이 어째서 중요한가?
* 값 `4`는 무슨 의미인가?
* 함수가 반환하는 리스트 `list1`을 어떻게 사용하는가?

위 코드 샘플은 `지뢰찾기` 게임이었다. 이 코드는 각 `개념`에 이름만 붙여도 코드가 상당히 나아진다.

```java
public List<int[]> getFlaggedCells() {
		List<int[]> flaggedCells = new ArrayList<int[]>();
		for (int[] cell : gameBoard) {
				if (cell[STATUS_VALUE] == FLAGGED) {
						flaggedCells.add(cell);
				}
		}
		return flaggedCells;
}
```

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

발음하기 어려운 이름은 토론하기도 어렵다.

```java
class DtaRcd102 {
		// generate date, year, month, day, hour, minutes, seconds
		private Date genymdhms;
		private Date modymdhms;
		private final String pszqint = "102"
}
```

**A> 젠 와이 엠 디 에이취 엠 에스는 어떤 값이 들어가나요?**

**B> 젠 야 무다 힘즈는 말씀이신가요?**

![https://pengsuu.tistory.com/category/%EC%9B%80%EC%A7%A4%20%7C%20%EC%97%90%ED%94%BC%EC%86%8C%EB%93%9C%2001\~05](https://2649832514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5HOStxvx-Jr0fqZhyW%2F-MWwBpvMl03QcMjh_Gj_%2F-MWwEYZp3LYRrTkKU7gH%2F111.gif?alt=media\&token=01a04c6c-e44f-47b7-9a4a-7b2eb3c34ceb)

#### 변수명을 발음하기 쉽게 수정해보자.

```java
class Customer {
		// generate date, year, month, day, hour, minutes, seconds
		private Date generationTimeStamp;
		private Date modificationTimestamp;
		private final String recordId = "102"
}
```

**A> 펭수씨, 이 레코드 좀 보세요. "Generation Timestamp" 값이 내일 날짜입니다. 어떻게 이럴수 있죠?**

**B> 아, 잘못 들어간거 같네요. 오늘 날짜로 수정하겠습니다.**

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

문자 하나를 사용하는 `이름`과 `상수`는 텍스트 코드에서 쉽게 눈에 띄지 않는다는 문제점이 있다. `MAX_CLASSES_PER_STUDENT`는 찾기가 쉽지만, 숫자 `7`은 은근히 찾기 어렵고 의미를 해석하기도 어렵다.

```java
for (int j=0; j<34; j++) {
		s += (t[j]*4)/5;
}
```

위 코드를 보면 몇가지 해석하기 어려운 부분이 있다.

* 34는 무엇을 의미하는지?
* 4를 왜 곱하였는지?
* 5를 나눈 의미는 무엇인지?

단순히 숫자를 사용하게 되면 코드를 해석하기 어려운 부분이 있다.

```java
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;
}
```

상수를 의미있는 변수로 표현하면 위와 같이 좀 더 해석하기 쉽다.

* 일한 일수를 구한다. (일한 시간 \* 실제 일한 일수)
* 일한 일수를 5일로 나누어 총 일한 주를 구한다.
* 총일한 주를 더해준다.

![https://pengsuu.tistory.com/category/%EC%9B%80%EC%A7%A4%20%7C%20%EC%97%90%ED%94%BC%EC%86%8C%EB%93%9C%2001\~05](https://2649832514-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5HOStxvx-Jr0fqZhyW%2F-MWwBpvMl03QcMjh_Gj_%2F-MWwEaEfwkQliFxAhshF%2F222.jpg?alt=media\&token=fc66ae95-9a90-4909-88db-a350487da16b)

## 한 개념에 한 단어를 사용하라

`추상적인 개념` 하나에 단어 하나를 선택해 이를 고수한다. 예를 들어, 똑같은 메서드를 클래스마다 `fetch`, `retrive`, `get`으로 제각각 부르면 혼란스럽다. 어느 클래스에서 어느 이름을 썼는지 기억하기 어렵다. 따라서 메서드 이름은 `독자적`이고 `일관적`이어야 한다.

> Q. 그렇다면 이렇게 사용하는건 어떨까..?

클래스 이름이 명확하다면 클래스에서 수행하는 메서드는 도메인이나 메뉴명을 넣지 않아도 되지 않을까?

```java
// option 1. 메서드에도 메뉴를 표현
public class MarketplaceService {
		public List<Marketplace> getMarketplaceList() { ... }
		public void saveMarketplace(Marketplace marketplace) { ... }
		public void updateMarketplace(Marketplace marketplace) { ... }
		public void deleteMarketplace(Integer marketplaceId) { ... }
}

// option 2. 메서드에는 메뉴를 생략
public class MarketplaceService {
		public List<Marketplace> getItems() { ... }
		public void save(Marketplace marketplace) { ... }
		public void update(Marketplace marketplace) { ... }
		public void delete(Integer marketplaceId) { ... }
}
```

## 말장난을 하지 마라

한 단어를 두 가지 목적으로 사용하지 마라. 예를 들어, 여러 클래스에 `add`하는 메서드가 생겼다. 지금까지 구현한 add 메서드는 모두가 기존 값 두개를 더하거나 이어서 새로운 값을 만든다고 가정하자.

```java
public int add(int num1, int num2) {
		return num1 + num2;
}
```

**그런데 새로 작성하는 메서드는 집합에 값 하나를 추가한다.**

#### 이 메서드에도 add라 불러도 괜찮을까?

`add`라는 메서드가 많으므로 일관성을 지키려면 add라 불러야 하지 않을까? 하지만 새 메서드는 기존 add 메서드와 `맥락`이 다르다. 그러므로 `insert`나 `append`라는 이름이 적당하다.

프로그래머는 코드를 최대한 이해하기 쉽게 짜야 한다. 집중적인 탐구가 필요한 코드가 아니라 대충 훑어봐도 이해할 코드 작성이 목표다.

## 의미 있는 맥락을 추가하라

**스스로 의미가 분명한 이름이 없지 않다.** 하지만 대다수 이름은 그렇지 못하다. 예를 들어, firstName, lastName, street, houseNumber, city, state, zipcode 라는 변수가 있다. 변수를 훑어보면 주소라는 사실을 금방 알아챈다.

#### 하지만 어느 메서드가 state라는 변수 하나만 사용한다면?

사용하는 이는 변수 state가 주소 일부라는 사실을 금방 알수 있을까?

`addr`라는 접두어를 추가해 `addrFirstName`, `addrLastName`, `addrState`라 쓰면 맥락이 좀 더 분명해진다. 변수가 좀 더 큰 구조에 속한다는 사실이 적어도 독자에게는 분명해진다. 물론 `Address`라는 클래스를 생성하면 더 좋다. 그러면 변수가 좀 더 큰 개념에 속한다는 사실이 컴파일러에게도 분명해진다.

다음은 갯수에 따라 다르게 표현되는 표현법을 제공하는 기능이다.

```java
private void printGuessStatistics(char candiate, 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);
}
```

일단 함수가 좀 길다. 그리고 세 변수를 함수 전반에서 사용하다. 함수를 작은 조각으로 쪼개고자 `GuessStaticsMessage`라는 클래스를 만든 후 세 변수를 클래스에 넣었다. 그러면 세 변수는 맥락이 분명해진다. 즉, 세 변수는 확실하게 `GuessStaticsMessage`에 속하게 된다. 이렇게 맥락을 개선하면 함수를 쪼개기가 쉬워지므로 알고리즘도 좀 더 명확해진다.

```java
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";
	}
}
```

## 결론

좋은 이름을 선택하려면 설명 능력이 뛰어나야 하고 문화적인 배경이 같아야 한다. 우리들 대다수는 자신이 짠 클래스 이름과 메서드 이름을 모두 암기하지 못한다. 여느 코드 개선 노력과 마찬가지로 이름 역시 나름대로 바꿨다가는 누군가 질책할지도 모른다. 그렇다고 코드를 개선하려는 노력을 중단해서는 안 된다.
