[TIL] @2025년 10월 17일 2. 의미 있는 이름
의도를 분명히 밝혀라
변수, 함수, 클래스의 이름은 [ 존재 이유, 수행 기능, 사용 방법 ] 을 명확히 드러내야 한다.
주석이 필요하다면 완벽한 이름을 짓지 못한 것.
측정하려는 값과 단위를 표현하는 이름을 사용하자
// 좋지 않은 예
int d; // 경과시간 (단위 : 날짜)
// 좋은 예
int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;
이렇게 의도가 드러나는 이름을 사용하면 코드를 이해하기 쉬워지고 그에따라 유지보수하기 쉬워진다.
// 좋지 않은 예
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for(int[] x : theList) // theList에 무엇이 들어있는가?
if(x[0] == 4) // theList에서 0번째 값이 어째서 중요한가? | 값 4는 무슨 의미인가?
list1.add(x);
return list1; // 함수가 반환하는 list1을 어떻게 사용하는건가?
}
// 좋은 예
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for(int[] cell : gameBoard) // 게임판에서
if(cell[STATUS_VALUE] == FLAGGED) // 0번째 값은 상태를 나타내고, 값 4는 깃발이 꽂힌 걸 뜻하구나
flaggedCells.add(cell);
return flaggedCells;
}
// 더욱 개선된 예
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for(Cell cell : gameBoard) // int[] 대신 클래스로 구현
if(cell.isFlagged()) // FLAGGED 상수 감춤
flaggedCells.add(cell);
retrun flaggedCells;
}
그릇된 정보를 피하라
이미 널리 쓰이고 있는 단어를 나 혼자 다른 의미로 사용하면 안된다.
여러 계정을 그룹으로 묶을 때, List 컨테이너를 사용하지 않는데, accountList 라는 변수명은 지양하자.
- 실제
List가 아닌데, 프로그래머에게 그릇된 정보를 제공하는 셈- [ 좋은 예 ]
accountGroup,bunchOfAccounts,Accounts - 실제 List 컨테이너라고 하더라도, 변수명에 컨테이너 유형을 넣는 것은 바람직하지 않다.
- [ 좋은 예 ]
서로 흡사한 이름을 사용하지 않는다.
[ 모듈1 ] XYZControllerForEfficientHandlingOfStrings
[ 모듈2 ] XYZControllerForEfficientStorageOfStrings
- 요즘 IDE에서 대부분 자동완성이 지원되는데, 흡사한 이름은 혼동을 주기 십상이다.
l과1,O와0도 혼동을 주는 방식으로 쓰지는 말자. 최악이다
의미있게 구분하라
- 연속된 숫자를 덧붙이는 것을 최소화하자.
// 좋지 않은 예 public static void copyChars(char a1[], char a2[]) { for(int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } } // 좋은 예 public static void copyChars(char source[], char destination[]) { for(int i = 0; i < source.length; i++) { destination[i] = source[i]; } }- 불용어(noise word)를 최소화하자.
Product라는 클래스가 있는데, 다른 클래스가ProductInfo,ProductData로 불린다면, 각각 클래스의 책임이 어떻게 구분되는 건지 이용자는 알 방법이 없다.- 불용어는 중복을 야기한다. 변수 이름에
variable, 테이블 이름에table이라는 단어를 붙이는 것은 아무런 의미가 없다.Customer라는 클래스와CustomerObject라는 클래스 중에 어디에 고객 급여 이력이 있겠는가?getActiveAccount()getActiveAccounts()getActiveAccountInfo()각자 어떤 역할을 가지고 있는 지 눈에 들어오는가?moneyAmount/money,customerInfo/customer,accountData/account,theMessage/message모두 불용어이다.
읽는 사람이 차이를 알도록 이름을 짓자. 이름이 달라야 한다면, 의미도 달라져야 한다.
발음하기 쉬운 이름을 사용하라
발음하기 어려운 단어는 토론하기도 어렵다.
genYMDHMS vs generationTimestamp
후자를 선택한다면 팀원들과 지적인 대화가 가능해질 것이다.
검색하기 쉬운 이름을 사용하라
문자 하나를 사용하는 변수명과 상수는 텍스트 코드에서 쉽게 눈에 띄지 않는다는 문제점이 있다.
MAX_CLASSES_PER_STUDENT 눈에 띄지만, 숫자 7 만 적혀있는 부분을 찾으려면 문서 전체를 뒤져야할 수도 있다.
e 라는 변수명도 문제가 많다. 영어에서 e는 가장 많이 쓰이는 문자이다.
이런 의미에서 긴 이름이 짧은 이름보다 좋으며, 검색하기 쉬운 이름이 상수보다 좋다.
(이름 길이는 범위 크기에 비례해야한다. 여러 곳에서 사용하는 이름일수록 검색하기 쉬워야함 )
// 좋지 않은 예
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;
}
인코딩을 피하라
인코딩은 [변수/클래스명]에 [타입/유형/부가정보]를 암호처럼 덧붙이는 명명 규칙을 뜻한다.
- 헝가리식 표기법 :
strName,iCount,bIsEnabled
인코딩한 이름은 발음하기도 어렵고 오타가 생기기도 쉽다.
예전엔 IDE의 한계로 타입을 바로바로 알기 힘들어서 해당 명명 규칙을 사용했지만, 이제 IDE와 컴파일러의 발전으로 오히려 사용하면 혼돈을 준다.
- 멤버 변수 접두어
멤버 변수에 m_의 접두어를 붙일 필요도 없다.
요즘 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;
}
}
- 인터페이스 클래스와 구현 클래스
인코딩이 필요한 경우도 있다.
추상 팩토리(ABSTRACT FACTORY) 패턴에서의 예 : 도형을 생성하는 ShapeFactory를 구현한다고 생각하면,
인터페이스에 IShapeFactory 를 사용하는 것 보다는, 구현 클래스에 ShapeFactoryImp 혹은 CShapeFactory 를 사용하는 게 좋다.
자신의 기억력을 자랑하지 마라
변수 이름을 문제 영역이나 해법 영역에서 가져오지 않고 나만 아는 단어로 선택을 한다면, 다른 사람들이 코드를 읽을 때, 불필요한 노력이 필요하다.
한 글자는 변수는 for문에서 반복 횟수를 세는 변수 i, j, k 정도는 관습적으로 허용하지만, 그 외의 경우에는 지양하자.
r이라는 변수명만 보고 이게 무슨 역할을 하는 변수인 지는 알 수있는 사람은 명명한 사람만이 기억할,, 아니 명명한 사람도 기억 못할 수도 있다.
클래스 이름
클래스 / 객체 이름은 명사나 명사구가 적합하다.
❇️ 좋은 예 : Customer, WikiPage, Account, AddressParser
🚫 나쁜 예 : Manager, Processor, Data, Info
메서드 이름
메서드 이름은 동사나 동사구가 적합하다.
❇️ 좋은 예 : postPayMent, deletePage, save
접근자 / 변경자 / 조건자는 javabean 표준에 따라 get / set / is를 붙인다.
string name = employee.getName();
customer.setName("mike");
if(paycheck.isPosted())
----
생성자를 중복정의(Overload)할 때는, 정적 팩토리 메서드를 사용한다.
메서드는 인수를 설명하는 이름을 사용한다.
// 좋지 않은 예
Complex fulcrumPoint = new Complex(23.0);
// 좋은 예
Complex fulcrumPoint = Complex.FromRealNumber(23.0);
// 만드는 방법을 설명하는 이름을 가진 메서드를 통해 객체 생성
// 생성자 사용을 private으로 제한해, 메서드 사용을 유도할 수 있다.
기발한 이름은 피해라
이건 “자신의 기억력을 자랑하지 마라” 규칙과 비슷한 건데, 농담을 이용한 이름은 어차피 농담이 기억날 때 까지만 무슨 뜻인지 이해가 가능하다.
Nasus’sQskill이라는 함수명보다는 incrementUserUsageTime 처럼 명료한 이름을 선택하는 게 좋다.
한 개념에 한 단어를 사용하라
똑같은 메서드를 각각의 클래스에서 fetch, retrieve, get으로 제각각 부르면 혼란스러우니까 하나로 통일해라.
controller, manager, driver도 섞어쓰면 혼란스러우니, 일관성있게 작성해라
말장난을 하지마라
한 단어를 두 가지 목적으로 사용하지 마라. 다른 개념에 같은 단어를 사용하는 것은 말장난이다.
“한 개념에 한 단어를 사용하라” 규칙을 따른다고 여러 클래스에 add라는 메서드를 구현했지만,
기존의 add 메서드는 모두 기존 값 두 개를 더하거나 이어서 새로운 값을 만든다고 가정했을 때,
새로 작성하는 add 메서드는 집합에 값을 하나 추가한다.
그렇다면 이 메서드는 add보다는 insert / append라는 이름이 적당할 것이다.
해법 영역에서 가져온 이름을 사용해라
코드를 읽는 사람도 프로그래머이므로, 전산 용어 / 알고리즘 이름 / 패턴 이름 / 수학 용어 등 프로그래밍 전문 용어를 사용해도 괜찮다.
문제 영역으로 변수명을 사용하면, 동료들이 매번 고객에게 의미를 물어야 한다.
VISITOR 패턴에 친숙한 우리 프로그래머들은 AcoountVisitor라는 이름을 바로 이해할 수 있지 않은가?
문제 영역에서 가져온 이름을 사용해라
적절한 프로그래밍 용어가 없다면 이제 문제 영역에서 이름을 가져온다.
그럼 코드를 보수하는 프로그래머가 분야 전문가에게 의미를 물어 파악할 수 있다.
문제 영역 개념과 관련이 깊은 고드라면, 문제 영역에서 이름을 가져와야 한다.
의미있는 맥락을 추가하라
PI 처럼 스스로 의미가 분명한 이름들도 있지만, 대부분의 이름은 그렇지 않다.
그래서 클래스 / 함수에 넣어서 의미있는 맥락을 부여한다. 모든 방법이 실패한다면 마지막 수단으로 접두어를 붙인다.
🚫 나쁜 예 : [ firstName, lastName, street, houseNumber, city, state, zipcode ] 라는 변수가 있을 때, 변수를 전체적으로 본다면 주소라는 사실을 알아채지만, firstName 하나만 따로 떼서 보면 주소라는 사실을 알아채기 힘들다.
Address 클래스를 생성해 의미있는 맥락을 부여하거나, addrFirstName과 같이 접두어를 추가해주면된다.
불필요한 맥락을 없애라
헬스장 사물함 예약 (Gym Locker Reserve)라는 애플리케이션이 있다고 해서, 모든 클래스 이름을 GLR로 짜는 것은 최악이다.
MailingAddress라는 좋은 이름을 가지고 회계 모듈에서 사용한다고 GLRAccountAddress라고 지으면, 나중에 고객 모듈에서 재사용하려고 하지 않을 가능성이 있다.
의미가 분명한 경우에 한해서 일반적으로 짧은 이름이 긴 이름보다 좋다.
accountAddress는 변수명으로는 좋지만, 클래스명으로는 적합하지 않다.
“이름은 최대한 짧고 명료하게 짓되, 이름만으로 모호할 때만 꼭 필요한 맥락을 추가하라.”