들어가면서
소프트웨어에서 이름은 어디나 쓰인다. 변수, 함수, 클래스, 패키지 등 이름을 붙인다.
그래서 이름을 잘 지으면 여러모로 편하다. 이 장에서는 이름을 잘 짓는 규칙을 몇 가지 소개한다.
의도를 분명히 밝혀라
변수의 존재 이유는? 수행 기능은? 사용 방법은? 이에 따로 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말이다.
int d; // 경과 시간(단위: 날짜)
int elpasedTimeInDays;
이름 d는 아무 의미도 드러나지 않는다. elapsedTimeInDays처럼 측정하려는 값의 단위를 표현하는 이름이 필요하다.
그릇된 정보를 피하라
프로그래머는 코드에 그릇된 단서를 남겨서는 안 된다.
나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용해도 안 된다. 예를 들어, hp는 유닉스 플랫폼을 가리키는 이름이기 때문에 직각삼각형의 빗변(hypotenuse)의 변수로 사용하기 적합하지 않다.
여러 계정을 그룹으로 묶을 때, 실제 List가 아니라면, accountList라 명명하지 않는다. 프로그래머에게 List는 특수한 의미다. 단순히 accounts라 명명한다.
서로 흡사한 이름을 사용하지 않도록 한다. 한 모듈에서 XYZ와 ABC가 있는데, 조금 떨어진 모듈에서 XYZABC를 사용한다면? 차이를 알아채겠는가?
그릇된 정보의 가장 끔찍한 예가 소문자 L이나 대문자 O 변수다. 소문자 L은 숫자 1처럼 보이고 대문자 O는 숫자 0처럼 보인다. 쓰지말자.
의미 있게 구분하라
불용어(의미가 없는 단어)는 적절하지 못하다.
public static void copyChars(char a1[], char a2[]) {
for (int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
a1, a2는 아무런 정보를 제공하지 못한다. 대신 source, destination을 사용한다면 코드 읽기가 훨씬 더 쉬워진다.
또한 불용어는 중복이다. 변수 이름에 variable, 표 이름에 table이라는 단어는 금물이다. NameString이 Name보다 뭐가 나은가? Customer과 CustomerObject 클래스가 있다면 차이를 알겠는가? 고객 급여 이력을 찾으려면 어느 클래스를 뒤져야 빠를까?
읽는 사람이 차이를 알도록 이름을 지어라.
발음하기 쉬운 이름을 사용하라
발음하기 어려운 이름은 토론하기도 어렵다.
검색하기 쉬운 이름을 사용하라
MAX_CLASSES_PER_STUDENT는 찾기 쉽지만, 숫자 7은 찾기 어렵다. 7이 들어가는 파일이름이나 수식이 모두 검색되기 때문이다.
e라는 문자도 변수 이름으로 적합하지 못하다. e는 영어에서 가장 많이 쓰이는 문자다. 마찬가지로 검색이 어렵다.
이런 관점에서 긴 이름이 짧은 이름보다 좋다. 이름 길이는 범위 크기에 비례한다. 여러 곳에 사용한다면 검색하기 쉬운 이름이 바람직하다.
인코딩을 피하라
이름에 해독해야하는 정보를 넣지말자. 명확하지않고 발음하기도 어려우며 오타도 자주 생긴다.
<헝가리식 표기법>
이름 길이가 제한된 언어를 사용하던 옛날에는 어쩔 수 없이 이 규칙을 위반했다. 포트란은 첫 글자로 유형을 표현했다.
그러나 요즘 나오는 프로그래밍 언어는 컴파일러가 타입을 기억하고, IDE는 컴파일하지 않고도 타입 오류를 감지할 정도로 발전했기 때문에 인코딩 방식을 사용할 필요가 없다.
<멤버 변수 접두어>
이제 멤버 변수에 m_이라는 접두어를 붙일 필요도 없다. 또한 멤버 변수를 다른 색상으로 표시하거나 눈에 띄게 보여주는 IDE를 사용한다.
<인터페이스 클래스와 구현 클래스>
때로는 인코딩이 필요한 경우도 있다. 인터페이스에 대한 구현 클래스를 생성할 때, 인터페이스Impl과 같이 사용할 수 있다.
자신의 기억력을 자랑하지 마라
독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 바람직하지 못하다. 예를 들어, 문자 하나만 사용하는 변수 이름은 독자가 실제 개념으로 변환해야 하기 때문에 적절하지 않다. (반복 변수 i, j, k 정도는 괜찮다)
클래스 이름
클래스 이름과 객체 이름은 명사가 적합하다.
메서드 이름
메서드 이름은 동사가 적합하다. 접근자, 변경자, 조건자는 javabean 표준에 따라 앞에 get, set, is를 붙인다.
생성자를 중복정의할 때는 정적 팩토리 메서드를 사용한다. 메서드는 인수를 설명하는 이름을 사용한다.
Complex fulcrumPoint = new Complex(23.0);
Complex fulcrumPoint = Complex.FromRealNumber(23.0);
아래 코드가 위 코드보다 좋다.
기발한 이름은 피하라
HolyHandGrenade라는 함수가 무엇을 의미하는지 알겠는가? 기발한 이름이지만 DeleteItems가 더 좋다. 특정 문화에서만 사용하는 농담은 피하는 편이 좋다. 의도를 분명하고 솔직하게 표현하라.
- HolyHandGrenade: 몬티 파이썬에 나오는 가상의 무기
한 개념에 한 단어를 사용하라
추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다. 예를 들어, 같은 메서드를 클래스마다 fetch, get으로 제각각 부르면 혼란스럽다.
마찬가지로, 동일 코드 기반에 controller, manager를 섞어 쓰면 혼란스럽다. DeviceManager와 ProtocolController는 근본적으로 어떻게 다른가? 어째서 둘 다 Controller가 아닌가?
말장난을 하지 마라
한 단어를 두 가지 목적으로 사용하지 마라. '한 개념에 한 단어를 사용하라' 규칙을 따르기 위해 여러 클래스에 add라는 메서드가 생겼다.
어떤 클래스에서 add는 두 값을 더하는 기능을 하는데, 어떤 클래스의 add는 집합에 값 하나를 추가한다. 이 메서드를 add라고 불러도 괜찮을까? 맥락이 다르기 때문에 insert나 append라는 이름이 적당하다.
다시 강조하지만 코드를 최대한 이해하기 쉽게 짜야 한다.
해법 영역에서 가져온 이름을 사용하라
코드를 읽을 사람도 프로그래머라는 사실을 명심한다. 그러므로 전산 용어, 알고리즘 이름, 수학 용어 등을 사용해도 괜찮다.
모든 이름을 문제 영역(domain)에서 가져오는 것은 현명하지 못하다.
문제 영역에서 가져온 이름을 사용하라
적절한 '프로그래머 용어'가 없다명 문제 영역에서 이름을 가져온다. 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와야한다.
의미 있는 맥락을 추가하라
firstName, lastName, street, houseNumber, city, state,zipcode라는 변수가 있다. 변수를 훑어보면 주소라는 사실을 금방 알아챈다. 하지만 어느 메서드가 state라는 변수 하나만 사용한다면? 변수 state가 주소 일부라는 사실을 금방 알아챌까?
addr라는 접두어를 추가해 addrFirstName, addrLastName, addrState라 쓰면 맥락이 좀 더 분명해진다.
물론 Address라는 클래스를 생성하면 더 좋다. 그러면 변수가 좀 더 큰 개념에 속한다는 사실이 분명해진다.
불필요한 맥락은 없애라
accountAddres와 customerAddress는 Address 클래스 인스턴스로는 좋은 이름이나 클래스 이름으로는 적합하지 못하다.
의미가 분명한 경우에 한해 짦은 이름이 긴 이름보다 좋다.
마치면서
이 장에서 소개한 규칙 몇 개를 적용해 코드 가독성이 높아지는지 살펴보라. 단기적인 효과는 물론 장기적인 이익도 보장한다.
'book > clean code' 카테고리의 다른 글
[Clean Code] 6. 객체와 자료 구조 (0) | 2021.09.11 |
---|---|
[Clean Code] 5. 형식 맞추기 (0) | 2021.09.02 |
[Clean Code] 4. 주석 (0) | 2021.08.30 |
[Clean Code] 3. 함수 (2) | 2021.08.27 |
[Clean Code] 1. 깨끗한 코드 (5) | 2021.08.27 |