#3 깨끗한 변수명 - 1

KangMyungJoe·2021년 1월 1일
0

cleancode

목록 보기
3/3
post-thumbnail

Clean Code는 총 17장으로 이루어져 있으며, 그 중 2장 변수명을 읽고 작성하는 글이다.

개발자라면 한번 쯤 고민했을 문제에 대해 알아본다.

변수명 짓는 방법은 예전부터 개발자들의 골치를 아프게 한다.


실제로 개발자들은 프로젝트에 사용되는 이름을 짓는 과정에서 큰 고충을 겪는다.


그렇다면 깨끗한 변수명이란 무엇일까?

책의 저자는 의도가 분명한 이름을 강조한다. 좋은 이름을 지으려면 시간이 걸리지만, 좋은 이름으로 절약하는 시간이 훨씬 더 많다.

예를 들어, 다음과 같은 코드가 있다. int형 변수 d는 아무 의미도 드러나지 않는다. 하지만 동일한 int형의 다른 이름의 변수들은 변수들의 의미가 명확하게 드러난다.

int d; //경과 시간(단위: 날짜)

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

의도가 드러나는 이름을 사용하면 코드 이해와 변경이 더욱 쉬워진다.

또 다른 예시는 다음과 같다.

public void getThem()  {
        List<int[]> list1 = new ArrayList<int[]>();         // 아래 코드와 동일한 내용의 코드
        int[][] theList = new int[0][];                     // 변수명만 잘 사용해도 어떤 일을 하는 코드인지 파악 가능
        for (int[] x : theList) {
            if (x[0] == 4) {
                list1.add(x);
            }
        }
    }
    
***************************************************

public void getFlaggedCells() {   // getThem()과 같은 일을 하는 코드 --> 잘 짜여진 코드
        List<int[]> flaggedCells = new ArrayList<int[]>();
        int[][] gameBoard = new int[0][];
        for(int[] cell : gameBoard) {
            if (cell[STATUS_VALUE] == FLAGGED) {
                flaggedCells.add(cell);
            }
        }
    }

동일한 일을 수행하는 코드이지만, 명확한 변수명으로 이루어진 함수가 이해하기 쉽고 명확하다.


그릇된 정보를 피하자

저자는 프로그래머가 코드에 그릇된 단서를 남겨서는 안 된다고 말한다.
예를 들어, 다음과 같은 변수명은 마치 변수가 List형으로 선언된 듯하다. (실제로 List형이더라도, 변수명에 들어가지 않는게 바람직하다)

int accountList; 

또한, 서로 흡사한 이름을 사용하지 않도록 주의해야 한다. 일관성이 떨어져 그릇된 정보를 제공할 수 있기 때문이다.

String XYZControllerForEffecientHandlingOfStrings;
String XYZControllerForEffecientStorageOfStrings;

물론, 요즘 IDE는 많은 발전이 이루어져 자동완성 기능을 제공하지만, 모든 변수명의 의미가 드러나는 게 좋다.


의미 있게 구분하기

프로그래머가 컴파일러나 인터프리터만 통과하려는 생각으로 코드를 작성하는 경우 스스로 문제를 일으킨다. 이런 경우, 프로그래머들은 컴파일러를 통과할지라도 연속된 숫자를 덧붙이거나 불용어를 추가하는 방식을 취하는데, 이런 방식은 적절하지 못하다.

예를 들어, a1 a2 a3...aN과 같은 변수명은 의도적인 이름과 정반대다.
이런 이름은 그릇된 정보를 제공하는 이름도 아니고, 아무런 정보를 제공하지 못한다.

다음과 같은 코드가 있을 때
copyChars 함수 속 파라미터로 쓰인 a1[] a2[]는 아무런 의미도 갖지 않는다.주석으로 작성한 것 처럼 각각의 이름을 source, destination으로 변경하면 명확한 코드를 얻을 수 있다.

public static void copyChars(String a1[], String a2[]) {   // a1[] --> source, a2[] --> destination 으로 변경하면 깨끗함
        for(int i = 0; i < a1.length; i ++) {
            a2[i] = a1[i];
        }
    }

불용어를 추가한 이름 역시 아무런 정보를 제공하지 못한다. 예를 들어,
Product 클래스가 있을 때, productInfo, productData와 같은 변수는 특정 개념을 구분하지 않은 채 이름만 변경한 경우다.

또 다른 예시로, 다음과 같은 함수들이 존재한다.

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

코드를 작성한 프로그래머를 제외한 다른 프로그래머들이 이 함수들의 차이점을 알 수 있을까? 그럴 수 없다.


발음하기 쉬운 변수명

사람들은 단어에 능숙하다. 발음하기 쉬운 단어는 토론하거나 회의를 할 때도 유용하다. 만약, genymdhms 라는 변수명이 있을 경우, 어떻게 발음할 것인가? (genymdhms는 generate date, year, month, day, hour, minute, second를 뜻함)

다음과 같은 코드가 있을 경우 어떤 코드로 회의하는 게 유용할까?

class DtaRcrd102 {          // 잘못된 코드
    private Date genydhms;
    private Date modymdhms;
    private final String pszqint = "102";
}

******************************************

class Customer {            // 깨끗한 코드
    private Date generationTimeStamp;
    private Date modificationTimeStamp;
    private final String recordId ="102";
}

동일한 내용의 코드지만, Customer 코드의 변수명을 발음하는 게 훨씬 간편하다.


검색이 쉬운 변수명

문자 하나를 사용하는 변수명과 상수는 코드에서 쉽게 눈에 띄지 않는다.
코드를 작성하는 과정에서 검색은 필수적이며, 추후 유지보수에도 중요한 역할을 한다.

다음과 같은 코드가 있을 경우, 어떤 코드의 검색이 편할까?

for(int j = 0; j< 34; j++) {    // 검색하기 매우 어려운 이름을 가지고 있음
    sj += (t[j]*4)/5;           // 이름을 변경해야 함
}

***********************************************************

int realDaysPerIdealDay = 4;
int WORK_DAYS_PER_WEEK = 5;
        
for(int j = 0; j<NUMBER_OF_TASKS; j++) {        // for 문의 논리를 한 눈에 파악 가능
    int realTaskDays = taskEstimate[j] * realDaysPerIdealDay; // 상수 설정으로 검색이 매우 쉬움
    int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK);
    sum += realTaskWeeks;
}

당연히 상수와 적절한 변수명을 이용한 아래 코드가 편하다.
항상 명확한 변수명을 사용할 수 있도록 해야한다.


추가로, 최근 IDE의 발전으로, 더 이상 멤버 변수 접두어를 사용하지 않아도 좋다.

class Part1 {
    private String m_dsc;   // 멤버 변수 접두어를 사용한 예 (구닥다리)
    void setName(String name) {
        m_dsc = name;
    }
}

class Part2 {
    String Description;     // IDE의 발전, 접두어를 사용하지 않아도 되는 시스템으로 발전
    void setDescription(String description) {
        this.Description = Description;
    }
}

오히려 코드를 이해하는 데 방해가 된다. 변수, 함수, 클래스 이름, 타입 등을 바꾸기가 어려워지며 독자의 오도를 유발할 수 있다.


기억력을 자랑하지 말자

독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 하는 이름은 바람직하지 못하다. loop 반복 문에서 사용하는 1글자 변수를 제외하고는, 문자 하나만 사용하는 변수명은 문제가 있다.

똑똑한 프로그래머전문가 프로그래머의 차이는 명료함에 대한 다른 이해다.

전문가 프로그래머는 자신의 능력을 좋은 방향으로 사용해 남들이 잘 이해할 수 있는 코드를 만들어낸다.


클래스 이름

클래스 이름과 객체 이름은 명사, 명사구가 적당하다. 동사는 사용하지 않는다.

class Customer {} // 좋은 이름
class WikiPage {} // 좋은 이름

class Info {}     // 나쁜 이름
class Manager {}  // 나쁜 이름

메서드 이름

메서드 이름은 동사나 동사구가 적합하다.

public void postPayment() {} // 좋은 이름
public void deletePage() {}  // 좋은 이름
public void save() {}        // 좋은 이름

public void name() {}        // 나쁜 이름
public void desk() {}        // 나쁜 이름

필요에 따라 메서드 이름 앞에 get set is를 붙히는 것도 의미를 명확하게 하는데 도움을 준다.

public void getName() {}
public void setName(Stirng name) {}
public void isLogged() {}

기발한 이름은 피하자

이름이 너무 기발하면 코드를 작성한 프로그래머와
유머 감각이 비슷하거나, 농담을 기억하는 동안만 변수를 기억한다.

결코 좋은 코드라고 할 수 없다. (추후 신입 프로그래머가 읽는다면? )

kill() --> whack() // 좋지 않음

Abort() --> eatMyShort()  // 좋지 않음

항상 의도를 분명하고 솔직하게 표현해야 한다.


앞으로 내용이 많은 장들은 몇개의 게시글로 나누어 게시할 예정이다.

profile
소통을 잘하는 개발자가 되고 싶습니다.

0개의 댓글