Clean Code 2장 - 의미 있는 이름
2021-02-08 12:00:02 # Clean_Code
  • 의도가 분명한 이름 짓기
  • 그릇된 정보를 남기지 않기
  • 의미 있게 구분하기
  • 발음하기 쉬운 이름 사용하기
  • 검색하기 쉬운 이름 사용하기
  • 인코딩한 이름을 사용하지 않기
  • 한 개념에 한 단어
  • 말장난 하지 않기
  • 해법 영역, 문제 영역에서 가져온 이름을 사용하기
  • 의미 있는 맥락 추가하기
  • 불필요한 맥락 없애기
  • 결론

의도를 분명히 밝혀라

  • 좋은 이름을 짓는 시간도 있지만, 좋은 이름으로 절약하는 시간이 훨씬 더 많다
  • 코드가 하는 일을 짐작할 수 있게 하자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 지뢰찾기 예시
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 ArrayLiist<int[]>();
for (int[] cell : gameBoard)
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}
// 이름을 좀 더 고쳐보자
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}

그릇된 정보를 피하라

  • 코드에 그릇된 단서를 남겨 의미를 흐리지 말자
  • 서로 흡사한 이름을 사용하지 않도록 주의하자

의미 있게 구분하라

  • 연속적인 숫자를 덧붙인 이름은 의도적인 이름과 정반대다.
1
2
3
4
5
public static void copyChars(char a1[], char a2[]) {
for(int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
  • 의미가 불분명한 불용어를 사용하지 말라
  • 불용어는 중복이다.
  • 변수 이름에 variable은 금물
  • Customer가 있는데 CustomerObject가 있다면 헷갈린다.

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

  • 팀의 대화를 위해서 발음하기 쉽게 이름을 짓자

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

  • 이름을 의미있게 짓다보면 함수 이름이 길어지고 검색하기도 쉬워진다.
  • 문자 하나를 사용하는 이름이면 텍스트 코드에서 쉽게 눈에 띄지 않는다.

인코딩을 피하라

  • 굳이 이름에 인코딩까지 할 필요는 없다.

  • 문제 해결에 집중하는 개발자에게 인코딩은 불필요한 정신적 부담이다.

    • 헝가리식 표기법(변수 및 함수의 인자 이름 앞에 데이터 타입을 명시하던 규칙)

    • 멤버 변수 접두어(m_)

    • 인터페이스 클래스와 구현 클래스 인코딩은 어떻게 하지

      ShapeFactory - ShapeFactoryImp

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

  • 문자 하나만 사용하는 변수 이름은 문제가 있다.
  • 루프에서 반복 횟수를 세는 변수 i, j, k 는 괜찮다.(l은 안된다!)
  • 명료한 코드로 남들이 이해하기 쉬운 코드가 되도록 하자

클래스 이름, 객체 이름

  • 명사나 명사구가 적합하다.
    • 좋은 예: Customer, WikiPage, Account, AddressParser
    • 피해야하는 예: Manager, Processor, Data, Info 등
    • 동사도 사용하지 말라

메서드 이름

  • 동사나 동사구가 적합하다.

    • postPayment, deletePage, save emd

    • Accessor, Mutator, Predicate는 자바빈 표준에 따라 값 앞에 get, set, is를 붙인다.

    • 생성자를 중복정의할 때는 정적 팩토리 메서드를 사용한다.

    • 메서드는 인수를 설명하는 이름을 사용한다.

      1
      2
      3
      Complex fulcrumPoint = new Complex(23.0);	// 인수를 직접 넣음

      Complex fulcrumPoint = Complex.FromRealNumber(23.0); // 팩토리 메서드 사용하여 인수 넣음

기발한 이름은 피하라

  • 재미난 이름보다 명료한 이름을 선택하라
  • 특정 문화에서의 농담이나 구어체, 속어 등을 피해라
  • 의도를 분명하고 솔직하게 표현하라.

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

  • 추상적인 개념 하나에 단어 하나를 선택해 이를 고수해라
  • 이름을 제각각 부르면 혼란스러워지고 어느 클래스에서 어느 이름을 썼는지 기억하기 어렵다.
  • 일관성 있는 어휘는 코드를 사용할 프로그래머가 반갑게 여긴다.

말장난을 하지 마라

  • 다른 개념에 같은 단어를 사용하는 것은 말장난이다.
  • 집중적인 탐구가 필요한 코드가 아니라 대충 훑어봐도 이해할 코드 작성이 목표다.
  • 의미를 해독할 책임이 독자에게 있는 논문이 아니라 의도를 밝힐 책임이 저자에게 있는 잡지 모델이 바람직하다

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

  • 코드를 읽을 사람도 프로그래머이다.
  • 모든 이름을 domain에서 가져올 필요는 없다.
    • 같은 개념을 다른 이름으로 이해하던 동료들이 매번 고객에게 의미를 물어야한다.

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

  • 적절한 ‘프로그래머 용어’가 없다면 문제 영역에서 이름을 가져온다.

  • 해법 영역과 문제 영역을 구분할 줄 알아야 한다.

  • 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와야 한다.

의미 있는 맥락을 추가하라

  • 스스로 의미가 분명한 이름이 없지 않다.(있다, 하지만 대다수는 그렇지 못하다)
    • 그래서 클래스, 함수, 이름 공간에 넣어 맥락을 부여한다.
    • 모든 방법이 실패하면 마지막 수단인 접두어 사용(거의 안할듯)

불필요한 맥락을 없애라

  • 이름에 불필요한 맥락을 추가하지 않도록 주의한다.
    • accountAddress와 customerAddress는 Address 클래스의 인스턴스로는 바람직하지만
    • 클래스 이름으로는 적합하지 않다.
    • Addresss는 클래스 이름으로 적합하다.
    • PostalAddress, MAC, URI로 구분하면서 이름을 분명하게 할 수도 있다.

결론(마치면서)

  • 좋은 이름을 선택하려면 설명 능력이 뛰어나야 하고 문화적인 배경이 같아야 한다. (이게 제일 어렵다고 한다…)

  • 사람들이 이름을 바꾸지 않으려는 이유 하나는 다른 개발자가 반대할까 두려워서이다.

    • 좋은 이름으로 바꿔주면 반갑고 고마워 하자
  • 암기는 요즘 나오는 도구에게 맡기고, 우리는 문장이나 문단처럼 읽히는 코드 아니면, 적어도 표나 자료 구조처럼 읽히는 코드를 짜는 데만 집중해야 마땅하다.