ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 로버트 C.마틴의 클린코드(Clean Code) - 2) 의미 있는 이름
    개발 공부/Clean Code 2020. 11. 28. 17:28

     

    안녕하세요! 오늘은 Uncle Bob의 클린 코드에서 2장 의미 있는 이름에 대해서 써보려고 합니다.

    사실 저는 여태까지 코딩이라고 해봤자 졸업 프로젝트나 알고리즘 문제를 푸는 정도였는데요.

    계속 변수나 함수의 이름을 진짜 그냥 data, list, a, b, x, y 이런 식으로 짓는 경우가 많았던 것 같아요.

    책을 읽으면서 이런 자신을 반성하게 되었고 정말 습관이라는 게 굉장히 중요하다고 느꼈습니다.

     

    그럼 이제부터 한번 변수, 함수, 클래스에 어떻게 의미 있는 이름을 짓는지 알아보도록 하겠습니다.

     

     

    1. 의도를 분명히 밝혀라


    좋은 이름을 지으려면 시간이 오래 걸리지만, 좋은 이름으로 절약하는 시간이 훨씬 많다.

     

    변수, 함수, 클래스의 이름은 다음과 같은 굵직한 질문에 모두 답해야 한다.

    변수, 함수, 클래스의 존재 이유는? 사용 방법은?

     

    만약 따로 주석이 필요하다면 그 이름은 개발자의 의도를 분명히 드러내지 못한 것이다.

    // 의도가 드러나지 않는 이름
    int d;
    String data;
    
    // 의도가 드러나는 이름
    int elapsedTimeInDays;
    int daySinceModification;

     

    변수, 함수, 클래스의 이름을 의미 있게 짓는 것도 중요하지만, 배열의 인덱스나 상수에 대해서도 의미 있는 이름을 부여하는 것은 매우 중요하다.

    // 0과 4가 의미하는 것은 무엇인가?
    if (x[0] == 4) {
        ...
    }

    물론 당연히 코드만 봐서는 0과 4가 의미하는 것이 무엇인지 모른다. 단순히 if 조건문만 가져왔기 때문이다.

    하지만 여기서 말하고자 하는 것은, 전체 코드를 다 가져오더라도 0과 4가 의미하는 것이 무엇인지 알기 위해서는 앞 뒤 맥락을 훑어야 한다는 점이다.

     

    그런데 0과 4에게 의미 있는 이름을 부여해준다면 좀 더 직관적이고 효율적으로 의미를 파악할 수 있게 된다.

    // "상태가 OFF라는 의미"를 파악 가능 하다.
    if (x[STATUS] == OFF) {
        ...
    }

    만약 0을 STATUS로, 4를 OFF로 이름을 지어준다면 대충 봐도 "아, 어떤 상태가 OFF라는 거구나"라고 알 수 있다.

    정확히 어떤 상태인지는 맥락을 봐야 알겠지만, 이전 코드보다 훨씬 직관적이고 의미를 수월하게 파악할 수 있다.

     

     

    2. 그릇된 정보를 피하라


    프로그래머는 코드에 그릇된 단서를 남겨서는 안 된다.

     

    책의 예시에 따르면 빗변(Hypotenuse)을 구현할 때 hp라는 약어로 나타낼 수 있지만, hp라는 변수는 읽는 사람으로 하여금 그릇된 의미로 받아들일 수 있다. 따라서 약어를 사용할 때는 조심해야 한다.

     

    또한 프로그래밍에는 특수한 용어들이 존재한다. List, Set, Map 등등 과 같은 컬렉션의 이름들도 그중 하나다. 그러나 자료형이 List가 아닌데, 단순히 사용자의 이름이 모여있는 리스트를 나타낸다는 의미로 userList라고 이름을 지으면 이는 그릇된 단서이다. 다른 사람이 읽었을 때, 변수명이 userList라면, 자료형도 List라고 오해할 소지가 충분하기 때문이다. 그럴 때는 그냥 변수명을 users 혹은 userGroup이라고 짓는 게 훨씬 낫다.

     

    알파벳 대문자 O(오)와 소문자 l(엘)은 숫자 0(영)과 1(일)과 혼동될 가능성이 다분하다. 따라서 변수, 함수, 클래스 명으로 O 혹은 l을 단독적으로 사용하거나 충분히 헷갈릴만하게 사용하면 엄청나게 그릇된 정보를 제공할 수 있다. 따라서 직관적으로 보기에도 확실히 구분될 수 있도록 이름을 지어야 한다.

     

     

    3. 의미 있게 구분하라

     


    연속된 숫자를 덧붙이거나 불용어를 추가하는 방식은 적절하지 못하다.

     

    연속된 숫자를 덧붙인다는 의미는 다음과 같다.

    // 연속된 숫자를 덧붙여서 변수명을 지었을 때
    int a1 = 0;
    int a2 = 1;
    int a3 = 4;
    
    if (a1 == a2) {
        return a3;
    } else {
        return a1;
    }

    변수들은 모두 a로 시작하고 뒤에 붙는 숫자 1, 2, 3으로만 구분된다. 당연히 가독성도 떨어지고 헷갈릴만한 여지가 된다. 이러한 연속된 숫자를 덧붙여서 만드는 이름은 굉장히 지양해야 한다.

     

    불용어를 추가한다는 의미는 다음과 같다.

    // 원래 의미
    String product;
    
    // Data와 Info가 붙을 필요가 있을까?
    String productData;
    String productInfo;
    
    // product와 productString은 도대체 뭐가 다른가?
    String productString;

    보통 변수 이름을 지을 때 많이 하는 실수 중 하나이다. 아무 생각 없이 변수명 뒤에 List, Number, Info, Data 등의 불용어를 붙이는 행위 말이다. 물론 뒤에 단어를 붙였을 때, 더 의도가 드러나거나 기존 의미와 많이 달라진다면 상관없다. 하지만 product와 productString은 무슨 차이일까???? 이렇게 차이가 거의 없는 경우는 불필요하게 수식어를 붙일 필요가 없다. 단순히 product 만으로도 충분하다.

     

    읽는 사람이 차이를 알도록 확실히 의미 있게 구분하여 이름을 지어야 한다.

     

     

    4. 발음하기와 검색하기가 쉬운 이름을 사용하라.


    발음하기가 어려운 변수명을 짓는 사람들도 간혹 있다. 이름이 너무 길어서 엄청나게 축약을 한다던지, 스펠링 하나 씩 따로따로 부르는 그런 변수명들 말이다. 그런데 이렇게 발음하기 어려운 이름은 개발자들 사이에서 토론하거나 회의할 때 어렵다. 토론하거나 회의를 할 때 그 이름을 언급하는 경우가 많은데, 발음하기 어려우면 당연히 비효율적이다. 그리고 새로운 팀원이 추가되는 경우에는 그 이름의 뜻을 일일이 설명해 줘야 한다. 항상 이름은 발음하기 쉽고 직관적인 것으로 짓는 것이 좋다.

     

    그리고 검색하기 쉬운 이름을 사용하는 것이 좋다. 문자 하나를 사용하는 이름과 상수는 텍스트에서 쉽게 눈에 띄지 않기 때문이다. 예를 들면 'e' 라던가 '7' 하나만 사용하는 경우, 이 변수가 어디서 쓰였는지 찾고 싶을 때 엄청나게 많은 검색 결과나 나타날 수 있다. 왜냐면 'e'나 '7'은 어디에서나 쓰일 수 있고 각 단어 안에 철자로 포함될 가능성이 크기 때문이다. 따라서 검색하기 쉬운 이름을 사용할 수 있도록 이름을 짓고, 상수는 따로 선언을 해주어야 한다.

     

     

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


    코드를 작성하는 일은 반드시 해당 코드를 읽는 독자를 생각하면서 수행되어야 한다. 독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못하다.

     

    보통 관례적으로 반복문에서 자주 사용하는 i, j, k 같은 경우는 괜찮다. 하지만 a, b, c, x, y 같은 변수 이름은 코드를 작성하는 사람만이 그 의미를 알 뿐, 독자는 그 의미를 모르기 때문에 일일이 하나씩 파악해가며 읽어야 한다.

     

    코드를 작성하는 일에서는 명료함이 최고라는 사실을 이해해야 한다. 반드시 남들이 잘 이해할 수 있는 코드를 작성하도록 항상 노력해야 하는 것이다.

     

     

    6. 클래스 이름과 메서드 이름


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

    Customer, Account, Parser 등이 적합하다.
    Manager, Processor, Data, Info와 같은 단어는 피하는 것이 좋다.

     

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

    save, deletePage, postPayment 등이 적합하다.

    접근자(get), 변경자(set), 조건자(is)는 javabean 표준에 따라 get, set, is를 앞에 붙이고 시작하면 좋다.

     

     

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


    추상적인 개념 하나에 단어 하나를 선택해서 이를 고수하는 것이 좋다. 한글도 마찬가지지만 영어에서도 동의어가 굉장히 많다. 예를 들면 say, speak, tell 이 대표적인 비슷한 단어들이다. control, manage, drive 도 마찬가지다. 같은 뜻을 표현하는데 여러 단어가 있을 수 있다. 그런데 이를 코드를 작성할 때 혼용해버리면 문제가 된다.

    // cost에 해당하는 값을 가져올 때는 get인데,
    public void getCost() {
        ...
    }
    
    // change에 해당하는 값을 가져올 때는 fetch라면 헷갈린다.
    public void fetchChange() {
        ...
    }

    get과 fetch'가져오다'라는 뜻이 있다. 위 코드처럼, cost와 change에 해당하는 값을 가져오기 위해서 get과 fetch라고 써버리면 읽는 사람 입장에서는 다른 동작을 하는 함수라고 착각할 수 있다. 본질적으로 두 함수는 모두 특정 값을 '가져오는' 기능을 하는데도 말이다. 따라서 getcost, getChange 혹은 fetchCost, fetchChange로 통일해야 한다.

     

     

    이와 반대로 한 단어가 여러 개의 의미를 갖는 경우도 있다. 예를 들면 'add'의 경우 말 그대로 값 자체를 '더하다'라는 의미도 있지만, 어딘 가에 무엇을 '추가하다'라는 의미도 있다. 이런 경우, 내가 만약 '더하다'라는 의미를 선택하고 그 의미로만 메소드 명을 지었다면 일관적이어야 한다. add를 '추가하다'라는 의미로 써버리게 되면 헷갈린다.

    // add를 '더하다'라는 의미로 쓴 경우
    public int add(int left, int right) {
        return left + right;
    }
    
    // add를 '추가하다'라는 의미로 쓴 경우
    public void add(int element) {
        arrList.add(element);
    }

    위의 add는 plus의 의미이지만, 아래의 add는 insert의 의미다. 그러므로 둘 다 add라고 지으면 헷갈릴 여지가 충분하다. 따라서 내가 add를 plus의 의미로 쓸지, insert의 의미로 쓸지 확실히 정하고 한 가지 의미로만 밀고 나가야 한다.


     

     

     

    이번 게시물은 여기서 마치겠습니다.

     

    Uncle Bob의 클린 코드를 아직 2장까지 밖에 읽지는 않았지만 정말 많은 것을 배우는 것 같습니다. 뭐든지 초반에는 자세와 습관을 잘 잡아야 한다는 말이 있습니다. 저는 이 책을 학생 때 보게 되어서 너무 기쁘네요.

     

    한 번 잡힌 습관은 쉽게 고쳐지지 않기 때문에 처음부터 올바른 습관으로 코딩하는 것이 좋은 것 같습니다.

    앞으로도 올바른 습관으로 코딩을 할 수 있도록 책을 계속 읽어나갈 예정입니다.

     

    부족하지만 읽어주셔서 감사합니다. 다음에는 3장 함수 게시물로 찾아뵙겠습니다.

    댓글

Designed by Tistory.