티스토리 뷰

의미 있는 이름

소프트웨어에서 이름은 어디나 쓰입니다. 변수, 함수, 인수, 클래스 심지어 디렉터리, jar, war, ear 등 다양한 곳에 쓰입니다. 이렇듯 많이 사용하므로 이름을 잘 지으면 여러모로 편합니다.

 

의도를 분명히 밝혀라

좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많습니다. 그러므로 이름을 주의깊게 살펴 더 나은 이름이 떠오르면 개선해야합니다. 

int d; // 경과 시간

int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;

이름 d는 아무 의미도 없고 이를 설명하기 위한 주석이 필요합니다. 하지만 변수 명을 좀 더 자세하게 지으면 의미도 명확하고 주석도 필요하지 않습니다.

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

    return list1
}

복잡한 구문이 없지만 코드를 해석하기 매우 어렵습니다. 문제는 코드의 단순성이 아니라 코드의 함축성입니다. 즉, 코드의 맥락이 코드 자체에 명시적으로 드러나지 않았습니다.

  • theList는 어떤 값이 들어있는가?
  • 0번째 값이 어째서 중요한가?
  • 4는 어떤 의미를 하는 상수인가?
  • 반환된 list1은 어떻게 사용하는가?
public List<int[]> getFlaggedCells() {
    List<int[]> flaggedCells = new ArrayList<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;
}

좀 더 나아가 int 배열을 클래스로 바꾸고 isFlagged를 사용하여 좀 더 명시적으로 표현할 수 있습니다. 단순히 이름만 고쳤는데도 함수가 하는 일을 이해하기 쉬워졌습니다.

 

그릇된 정보를 피하라

프로그래머는 코드에 그릇된 단서를 남기면 안됩니다. 그릇된 단서는 코드의 의미를 흐리기 때문입니다. 여러 계정을 그룹으로 묶을 때 실제 List가 아니라면 accountList로 명명하지 않습니다. 계정을 담는 컨테이너가 실제 List가 아니라면 그릇된 정보를 제공하기 때문입니다.

 

서로 흡사한 이름을 사용하지 않도록 주의해야 합니다. 한 모듈에서 XYZControllerForEfficientHandlingOfString이라는 이름을 사용하고, 다른 모듈에서 XYZControllerForEfficientStorageOfString라는 이름을 사용하면 차이점을 쉽게 알 수 있을까?? 두 단어는 매우 비슷하다.

 

유사한 개념은 유사한 표기법을 사용해야 합니다. 이것도 정보이며 일관성이 떨어지는 표기법은 그릇된 정보입니다. 최근 개발 환경에서는 자동 완성 기능을 제공합니다. 많은 개발자가 클래스나 메소드 내부의 상세 코드와 주석을 살피지 않고 이름을 보고 선택합니다. 이때 일관성 있는 표기법과 이해하기 쉬운 이름은 매우 효율적입니다.

 

의미 있게 구분하라

컴파일러나 인터프리터만 통과하려는 생각으로 코드를 구현하는 프로그래머는 스스로 문제를 일으킨다. 컴파일러를 통과할지라도 연속된 숫자를 덧붙이거나 불용어를 추가하는 방식은 적절하지 않습니다.

public static void copyChars(char a1[], char a2[]) {
    for (int i = 0;i < a1.length;++i) {
        a2[i] = a1[i];
    }
}

위와 같은 코드에서 source와 destination을 사용한다면 좀 더 코드를 읽기 쉬워집니다.

 

class ProductData {

}

class ProductInfo {

}

getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();

만약 위의 코드처럼 함수가 구현되어 있을 때 프로젝트에 참여한 프로그래머는 어떤 함수를 호출할 지 알까?? 명확한 관례가 없다면 구분되지 않습니다. 읽는 사람이 차이를 알도록 이름을 지어야합니다.

 

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

문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 쉽게 눈에 띄지 않는다는 문제점이 있다. MAX_CLASSES_PER_STUDENT는 grep으로 찾기 쉽지만, 숫자 7은 은근히 까다롭습니다. 7이 들어가는 이름이나 수식이 모두 검색

되기 때문입니다. 또한 검색은 되었지만 사용한 의도가 다를 수도 있습니다.

상수가 여러 자리 숫자이면 더욱 검색하기 힘들고, 상수에 버그가 있으면 검색으로 찾기 힘들기 때문에 문제는 더욱 심각해집니다.

private static final int MAX_CLASSES_PER_STUDENT = 7

 

인코딩을 피하라

헝가리안 표기법

유형이나 범위 정보까지 인코딩에 넣으면 그만큼 이름을 해독하기 어려워집니다. 이름 길이에 제한된 언어를 사용했던 옛날에는 어쩔 수 없이 인코딩을 했지만 컴파일러와 IDE의 발전으로 필요가 없어졌습니다. 따라서 이제는 헝가리식 표기법이나 기타 인코딩 방식이 오히려 방해가 됩니다.

헝가리안 표기법 : 변수 이름에 변수 타입을 명명하는 표기법.
// 타입이 바뀌어도 이름은 변하지 않습니다!
PhoneNumber phoneString;

 

멤버 변수 접두어

이제 멤버 변수에 m_이라는 접두어를 붙일 필요도 없습니다. 클래스와 함수는 접두어가 필요없을 정도록 작아야 마땅합니다. 게다가 사람들은 접두어를 무시하고 해독하는 방식을 빨리 익히고, 요즘 IDE는 멤버 변수를 눈에 띄게 보여주기 때문에 붙일 필요가 없습니다.

 

인터페이스 클래스와 구현 클래스

때로는 인코딩이 필요한 경우도 있습니다. 예를 들어, 도형을 생성하는 ABSTRACT FACTORY를 구현한다고 가정하자. 이 팩토리는 인터페이스 클래스이며 구현은 구체 클래스에서 합니다. 이러한 상황에서 두 클래스의 이름을 구분하기 위해 Imp같은 인코딩을 사용해도 될 것 같습니다.

 

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

독자가 코드를 읽으변서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못합니다. 이는 일반적으로 문제 영역이나 해법 영역에서 사용하지 않는 이름을 선택했기 때문에 생기는 문제입니다.

대충 지은 이름을 오랜 시간 지난 후에 다시 봐도 기억한다면 분명 똑똑한 사람입니다. 똑똑한 프로그래머와 전문가 프로그래머 사이에서 나타나는 차이점 하나만 들자면, 전문가 프로그래머는 명료함이 최고라는 사실을 이해합니다.

 

클래스 이름

클래스 이름과 객체 이름은 명사나 명사구가 적합합니다. Customer, WikiPage, Account 등이 좋은 예입니다. Manager, Processor 등과 같은 단어를 피하고 동사를 사용하지 않습니다.

 

메서드 이름

메서드 이름은 클래스와 반대로 동사나 동사구가 적합합니다. postPayment, deletePage, save 등이 좋은 예입니다. 접근자, 변경자, 조건자는 javabean 표준에 따른 get, set, is를 메서드 앞에 붙입니다.

 

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

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

 

말장난을 하지 마라

한 단어를 두 가지 목적으로 사용하면 안됩니다. 다른 개념에 같은 단어를 사용한다면 그것은 말장난에 불과합니다. 예를들어 '한 개념에 한 단어를 사용하라' 규칙을 따랐더니 add라는 메서드가 생겼을 때 새로 작성하는 메서드가 집합에 값을 추가하는 경우 이 메소드의 이름은 add보다 insert나 append가 적당합니다.

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

 

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

코드를 읽을 사람도 프로그래머라는 사실을 명심해야합니다. 그러므로 전산 용어, 알고리즘 이름, 패턴 이름 등을 사용해도 괜찮습니다. 너무 간단 명료하게 이름을 짓기 위해 쉬운 단어만 고집할 필요는 없습니다.

 

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

적절한 '프로그래머 용어'가 없다면 문제 영역에서 이름을 가져옵니다. 그렇다면 코드를 보수하는 프로그래머가 분야 전문가에게 의미를 물어 파악할 수 있습니다. 우수한 프로그래머는 해법 영역과 문제 영역을 구분할 줄 알아야 합니다.

 

의미 있는 맥락을 추가하라

스스로 의미가 분명한 이름이 없지는 않습니다. 하지만 대다수 이름은 그렇지 못합니다. 그래서 클래스, 함수, 이름 공간에 넣어 맥락을 부여하거나 모든 방법이 실패하면 마지막 수단으로 접두어를 붙입니다.

 

예를들어 firstName, lastName, street, houseNumber, city, state, zipcode라는 변수가 있다면 주소에 관련된 변수라는 것을 눈치챌 수 있습니다. 하지만 어느 메서드에서 state라는 변수 하나만 사용한다면 주소인지 상태값인지 눈치채기 힘들 것 입니다. 이러한 상황에서 addr라는 접두어를 붙여 주소의 맥락을 부여할 수 있지만, Address라는 클래스를 만들어서 관리하면 더욱 좋을 것 입니다.

 

불필요한 맥락을 없애라

고급 휘발유 충전소(Gas Station Deluxe)라는 프로그램을 만든다고 가정했을 때 모든 클래스 이름을 GSD로 시작한다고 생각하는 것은 매우 부적합합니다. IDE에서 G를 입력하는 순간 모든 클래스가 나올 것 입니다. 비슷한 예시로 Address라는 클래스안에 state를 의미를 부여하기 위해 address 접두어를 붙여 addressState로 만드는 것은 이름만 길게 만드는 행위입니다.

 

마치면서

  • 사람이라면 모든 이름을 외울 수는 없습니다. 암기는 IDE에 맞기고 우리는 문장이나 문단처럼 읽히는 코드 또는 표나 자료 구조처럼 읽히는 코드 즉, 쉽게 읽히는 코드를 작성하는 데만 집중해야합니다.
  • 변수나 클래스 명을 바꾸지 않으려는 이유는 다른 개발자가 반대할까 두려움 혹은 누군가 질책할지도 모른다는 두려움이 있기 때문입니다. 그렇다고 코드를 개선하려는 노력을 중단해서는 안됩니다.

 

느낀점

개발자라면 이름을 어떻게 잘 지어야 하는지 많이 고민 했을 것입니다. 제가 느낀 점은 진행하는 프로젝트, 프로젝트 구성원 등 다양한 환경에 의해 적절한 변수명이 달라지는 것 같습니다. 결론은 공식은 없고 주어진 상황에서 다른 사람들이 이해할 수 있는지 초점을 두고 위에 나온 공식을 참고하면 좋을 것 같습니다.

'CS > Clean Code' 카테고리의 다른 글

CS Clean Code - 객체와 자료 구조  (0) 2022.03.03
CS Clean Code - 형식 맞추기  (0) 2022.02.23
CS Clean Code - 주석  (0) 2022.02.22
CS CleanCode - 함수  (0) 2022.02.17
CS Clean Code - 깨끗한 코드  (0) 2022.02.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함