Clean Code 2.의미 있는 이름


의도를 분명히 밝혀라

더 나은 이름이 떠오르면 개선해라. 다음 질문에 모두 답할 수 있는 이름이어야 한다. 존재 이유는? 수행 기능은? 사용 방법은?

ex. 1

// Bad
int d; // elapsed time in days

// Good
int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;

ex. 2

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

// Good
public List<int[]> getFlaggedCells() {
    List<int[]> flaggedCells = new ArrayList<int[]>();
    for (int[] cell : gameBoard) {
        if (cell[STATUS_VALUE] == FLAGGED) {
            flaggedCells.add(cell);
        }
    }
    return flaggedCells;
}

그릇된 정보를 피하라

  • 직각삼각형의 빗변(hypotenuse)의 변수명을 hp로 한다면 다른 사람들은 다른 hp로 생각할 수 있다.
  • 실제 List가 아니라면 AccountList라는 이름을 사용하지 말자.
  • 서로 비슷한 이름을 사용하지 않는다.
  • 유사한 개념은 유사한 표기법을 사용한다.

의미있게 구분하라

  • 숫자를 붙인 이름 (a1, a2…)를 사용하지 않는다.
  • 불용어(noise word)를 사용하지 않는다.
    • Product, ProductInfo, ProductData 는 모두 같은 뜻이다.
    • NameString와 Name
    • Customer과 CustomerObject

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

// Bad
class DtaRcrd102 {
    private Date genymdhms;
    private Date modymdhms;
    private final String pszqint = "102";
};
// Good
class Customer {
    private Date generationTimestamp;
    private Date modificationTimestamp;
    private final String recordId = "102";
};

genymdhms와 generationTimestamp

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

  • 한글자 단어, 숫자는 검색으로 찾기 어렵다. 7보다는 MAX_CLASS_PER_STUDENT가 더 찾기 쉽다.
  • 변수 이름의 길이는 변수의 범위에 비례해서 길어진다.

인코딩을 피하라

  • 헝가리안 표기법 : 타입 + 명칭. phoneString
  • 멤버 변수 접두어 : m_dsc
  • 인터페이스 클래스와 구현 클래스 : 인터페이스에 I접두사를 붙이는 것보다는 구현 클래스에 Imp접미사나 C접두사를 붙이는 것을 더 선호한다.

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

독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못하다. 전문가 프로그래머는 명료함(clarity)이 최고라는 사실을 이해한다.

클래스 이름

  • 명사나 명사구
  • Manager, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다.

메서드 이름

  • 동사나 동사구
  • postPayment, deletePage, save등
  • 접근자(Accessor): get, 변경자(Mutator): set, 조건자(Predicate): is
  • 생성자를 오버로드 할 경우 static method를 사용하고 해당 생성자를 private로 선언
// Bad
Complex fulcrumPoint = new Complex(23.0); 
// Good
Complex fulcrumPoint = Complex.FromRealNumber(23.0);  

기발한 이름을 피하라

특정 문화에서만 사용하는 농담은 피하는 것이 좋다.

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

  • fetch, retrieve, get
  • controller, manager, driver

말장난을 하지 마라

한 계념에 한 단어를 사용하라는 규칙을 따른다 하더라도 일관성을 고려하여야 한다. add라는 메서드를 2개의 값을 더하는 용도로 사용중인데, Collection에 element를 하나 추가하는 메서드를 add라고 한다면 이건 말장난이다.

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

코드를 읽는 사람도 프로그래머이다. 모든 이름을 문제영역(domain)에서 가져오는 것은 현명하지 못하다. 전산 용어, 알고리즘, 패턴, 수학 용어 등은 사용해도 괜찮다. (JobQueue, AccountVisitor)

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

적절한 해법 영역 용어가 없으면 문제 영역에서 이름을 가져온다. 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와야 한다.

의미 있는 맥락을 추가하라

모든 단어가 분명한 의미가 있는 것은 아니다. 그래서 클래서, 함수, namespace에 넣어서 맥락을 부여하거나 접두어를 붙인다. firstName, lastName, street, houseNumber, city, state, zipcode를 보면 주소에 관련된 변수라는 것을 알 수 있지만, state만을 보고 주소인지 알수는 없다. addr이라는 접두어를 추가하여 addrFirstName, addrState라 쓰면 맥락이 좀 더 분명해진다. 이것보다는 Address라는 클래스를 생성하면 더 좋다.

// Bad
private void printGuessStatistics(char candidate, int count) {
    String number;
    String verb;
    String pluralModifier;
    if (count == 0) {  
        number = "no";  
        verb = "are";  
        pluralModifier = "s";  
    }  else if (count == 1) {
        number = "1";  
        verb = "is";  
        pluralModifier = "";  
    }  else {
        number = Integer.toString(count);  
        verb = "are";  
        pluralModifier = "s";  
    }
    String guessMessage = String.format("There %s %s %s%s", verb, number, candidate, pluralModifier );

    print(guessMessage);
}
// Good
public class GuessStatisticsMessage {
    private String number;
    private String verb;
    private String pluralModifier;

    public String make(char candidate, int count) {
        createPluralDependentMessageParts(count);
        return String.format("There %s %s %s%s", verb, number, candidate, pluralModifier );
    }

    private void createPluralDependentMessageParts(int count) {
        if (count == 0) {
            thereAreNoLetters();
        } else if (count == 1) {
            thereIsOneLetter();
        } else {
            thereAreManyLetters(count);
        }
    }

    private void thereAreManyLetters(int count) {
        number = Integer.toString(count);
        verb = "are";
        pluralModifier = "s";
    }

    private void thereIsOneLetter() {
        number = "1";
        verb = "is";
        pluralModifier = "";
    }

    private void thereAreNoLetters() {
        number = "no";
        verb = "are";
        pluralModifier = "s";
    }
}

불필요한 맥락을 없애라

일반적으로는 짧은 이름이 긴 이름보다 좋다. accountAddress와 customerAddress는 Address 클래스의 인스턴스로는 좋은 이름이다. AccountAddress라는 클래스를 만들었는데, 다른 프로그램의 고객주소가 필요해서 저 클래스를 사용하면 이름이 적절한가 ? 그냥 Address라는 이름으로도 충분하다.

이 글이 도움이 되셨다면 공감 및 광고 클릭을 부탁드립니다 :)