좋은 이름을 짓는 것은 때로는 어렵지만 노력할 만한 가치가 있습니다.
많은 통합개발환경(IDE) 에서 Refactoring 메뉴를 제공하고 있는데,
가장 첫번째 메뉴는 "Rename" 인데,
이 메뉴는 해당 식별자를 한번에 모두다 변경합니다.
코딩을 하다 보면 처음에 지었던 이름을 변경해야할 필요가 있는데,
이때 사용하라는 것입니다.
이름 형식(스타일)
이름 짓는 스타일은 크게 4가지 정도로 나눌 수 있습니다.
| Style | Example |
|---|---|
| C style | product_list, display_products |
| All UPPER case | PRODUCT_LIST |
| Lower camel case | productList, displayProducts |
| Upper camel case | ProductList, DisplayProducts |
언어나 라이브러리 사용에 따라 스타일 가이드가 있으니 이에 맞게 사용하면 되지만,
class, type 이름은 Upper camel case
method, function 이름은 Lower camel case 를 주로 씁니다.
상수의 경우 모두 대문자로 쓰고 _ 를 사용하는 것이 관례입니다.
iCount, sName 등의 관례는 좋지 않습니다.
왜냐하면 타입은 쉽게 바뀔 수 있는데
그러한 경우 변수 이름과 타입이 맞지 않는 경우가 발생하기 때문입니다.
단어 선택
기본 원칙
- 비슷한 것에는 같은 단어를 사용하고, 서로 다른 것에는 서로 다른 단어를 사용한다.
- Class, Member, Variable 은 명사를, Method, Function 에는 동사를
의미 원칙
- 한 단어로 된 이름을 선호한다.
- 의사소통을 가장 중요한 가치로 생각한다.
- 의도를 표현한다.
- 검색하기 쉬운 단어를 사용
- 한영 사전, Thesaurus 이용
동사의 선택
객체 지향 프로그래밍이 일반화 되면서
S.V(O) 또는 S.V(C) 와 같은 형식을 사용하게 됩니다.
List<People> peoples = new ArrayList<People>();
peoples.add(new People()); // ---(1)
peoples.add(1, new People()) // ---(2)
if ( peoples.contains(theguy)) {
...
}
add 관련해서는 두가지 형태가 있습니다.
첫번째 경우 이름은 좀 못마땅한데 형식은 그럭저럭 SVO 갖추고 있습니다.
두번째 형태는 이름도 형식도 좀 이상합니다.
- 1을 넣으라는 것인지
- 1개만 넣으라는 것인지?
- 1번째 넣으라는 것인지?
3번째라면, insert 또는 insertAt 이라는 단어를 쓰는 것이 좋지 않을까 생각합니다.
두번째 인자로 원소 뿐만 아니라 배열형태가 오더라도 어색하지 않을 것 같습니다.
peoples.insertAt(n, new People())
peoples.insertAt(n, peopleList)
마지막에 추가하는 경우,
파이선에서는 append 자바스크립트는 push 를 사용합니다.
중간에 추가하는 경우,
파이선에서는 insert 함수를 제공하고 있으며, 자바스크립트는 splice 라는 함수를 제공합니다.
splice 는 몇번째에서 몇개를 빼고, 몇개를 추가해라라는 재밌는 함수입니다만,
직관적인 면에서는 안좋습니다.
그리고 splice 는 익숙하지 않은 단어라 의미를 잘 까먹습니다.
Array.prototype.insert = function(index, item) {
this.splice(index, 0, item)
}
좀 더 이해하기 쉽지요?
잠시만 딴 이야기를 더 해보면, (자바 유저들이 싫어할 이야기입니다.)
자바에서 List 는 peoples[i] 불가, peoples.get(i) 로 써야 합니다.
리스트를 기본형으로 갖지 않은 언어의 불편함이며, 직관적이지 않습니다.
더군다나 연산자 오버로딩도 지원하지 않는군요.
언어 간 일관성이 부족한데, 자바에 익숙해지면 다른 언어를 쉽게 익숙해지지 않습니다.
(사실 너무나 쉽게 보여서 우습게 보일런지도 모릅니다)
조금 더 나아가 볼까요?
자바에서 Integer 는 2^31-1 까지 수를 표현하고,
Long 은 2^63-1 까지 수를 표현합니다.
대문자입니다. int, long 이 아니라 이들의 wrapper 클래스입니다.
만일 int, long 을 쓰지 않고 wrapper 를 쓰면 속도가 많이 떨어집니다.
Python 에서 정수형은 limit 이 없습니다. 숫자 범위 때문에 고민할 필요가 없습니다.
자바에서도 BigInteger 가 있지만 많이 불편합니다.
꼭 동사여야만 하는가?
안드로이드 프로그래밍에서 LayoutInflater 를 가져오는 함수입니다.
LayoutInflater inflater = LayoutInflater.from(getContext());
from 이라는 함수가 쓰입니다. 동사는 아니지만 의사소통, 의도표현에는
가장 적합한 단어를 쓴 것 같습니다.
단어 뉘앙스
마지막에서 from 은 뉘앙스가 매우 좋습니다.
딱 들어맞는 단어임에 틀림 없습니다.
어떤 객체가 빈 객체인지 확인하는 함수가 있을 때 이름이 어떠할까요?
- object.empty()
- object.isEmpty()
- object.beEmpty()
두번째가 좋아 보이네요. 영어로 읽어도 Object is Empty 딱 맞네요.
이 함수의 반환값은 어떨까요? boolean 타입니다.
세번째 경우의 이름이 있는 경우, 이런 생각이 들 겁니다.
"object 여, 비운 상태가 되어라"
반환값은 없거나 boolean(성공, 실패)
첫번째도 비슷하게 명령하는 뉘앙스를 풍기기는 하네요.
두번째로 어떤 파일이 존재하는지 확인하는 함수의 이름은?
- file.exist()
- file.exists()
- file.isExist()
- file.doesExist()
아까는 형용사니까 is 가 필요하지만, exist 는 동사입니다.
이 경우 동사의 3인칭 단수형을 사용합니다.
대부분의 참/거짓 을 반환하는 함수는 3인칭 현재 단수형을 사용합니다.
isEmpty 도 비슷한 맥락입니다.
3인칭 단수형이 아닌 동사 원형을 쓴다면, 명령을 내리는 뉘앙스입니다.
세번째로 어떤 리스트에 객체가 존재하는지 확인하는 함수의 이름은?
- list.has(obj)
- list.contains(obj)
정도가 될 것같은데, have 는 너무나 의미가 많습니다.
하지만 contains 는 딱 하나의 의미를 가지고 있으므로 contains 를 씁니다.