[TSL] 읽기 좋은 코드가 좋은 코드다 (1)

intersoom·2024년 9월 21일
0

TSL

목록 보기
9/11
post-thumbnail
post-custom-banner

Intro

더스틴 보즈웰의 <읽기 좋은 코드가 좋은 코드다>라는 책을 읽고 인상 깊은 내용들을 위주로 정리해보고자 한다.

가독성의 기본 정리

코드는 다른 사람이 그것을 이해하는 데 들이는 시간을 최소화하는 방식으로 작성되어야 함

Part 1. 표면적 수준에서의 개선

표면적 수준이란?

  1. 좋은 이름 짓기
  2. 좋은 설명 달기
  3. 코드를 보기 좋게 정렬하기

이와 같은 것들은 바로 수정은 가능하지만, 코드 베이스에 큰 변화를 야기할 수 있다.

최근에 <Javascript로 작성된 legacy code를 Typescript로 개선>하는 작업을 진행한 적이 있는데, 해당 작업도 일종의 표면적 수준에서의 개선이라고 여길 수 있을 듯 하다.

하지만, 해당 작업을 하면서 느낀 점은... 간단한 작업들도 코드 베이스에 꽤나 큰 변화를 야기한다는 것이다.

예를 들면, undefined or null 처리 되어있는 값들을 Type을 수정하며 불가피하게 수정해야하는 경우들이 존재한다. 이러한 경우들 모두, 기존 코드 베이스에 대한 완벽한 이해도 없이는 버그를 야기할 가능성들이 존재한다.

그래서 표면적 수준에서의 개선을 할 때에도 스스로 조사를 하거나, 기존 코드에 대한 이해도가 있는 팀원들과의 소통을 통해서 완벽하게 코드에 대해서 이해를 한 후, 수정해야한다는 사실을 배웠다.

1) 이름에 정보 담기

매우 구체적인 단어를 선택하여 “무의미한” 단어를 피하기

  • 😈 : get / size → 정확히 의도한 정보를 전달하지 못함
  • 😇 : FetchPage, DownloadPage / Height, NumNodes, MemoryBytes

재치 있는 이름보다 명확하고 간결한 이름이 좋다

  • 유의어 색인집, 동료에서 어떤 변수가 나은지 물어보기
  • 적합한 단어 고르기
    • send → deliver, dispatch, announce, distribute, route
    • find → searchh, extract, locate, recover
    • start → launch, create, begin, ope
    • make → create, set up, build, generate, compose, add, new

temp, retval 같은 보편적인 이름 피하기

  • tmp

    • 변수의 목적이나 담고 있는 값을 설명해줘야함 → 버그를 잡는 데 도움이 됨
    • 하지만 보편적인 이름이 의미를 잘 전달하는 경우도 존재 temp → 임시 저장소 이외에 다른 의도가 없음을 전달 temp라는 이름은 대상이 짧게 존재 + 임시적 존재 자체가 중요한 용도일 경우에만 사용

    😈 :

    Stirng tmp = user.name();
    tmp += " " + user.phone_number();
    tmp += " " + user.email()
    template.set("user_info", tmp);

    😇 :

    if (right < left) {
        tmp = right;
        right = left;
        left = temp;
    }
  • 루프 반복자
    단순히 i, j, k를 사용하기보다
    e.g.

    😈 :

    for (int i = 0; i < clubs.size(); i++){
        for (int j = 0; j < clubs.size(); j++){
            for (int k = 0; k < clubs.size(); k++){
                if (clubs[i].members[k] == users[j]){
                    cout << .. << endl;
                }
            }
        }
    }
    clubs[i].members[k] == users[j]

    → 버그는 코드를 따로 떼어놓고 보면 잘못된게 없어 보여서 찾기 힘들다

    😇 :

    clubs[ci].members[ui] == users[mi] // 처음 문자가 일치하지 않음

    club_i, members_i, users_i 로 떼어놓고 생각하면 버그를 찾기 더 쉽다 !

보편적인 이름이 항상 나쁜 것은 아니지만, 이를 사용하려면 꼭 그렇게 해야하는 이유가 있어야함

추상적인 이름보다 구체적인 이름을 선호하라

  • 서버가 TCP/IP port 사용할 수 있는지 검사하는 메소드
    😈 : SeverCanStart()
    😇 : CanListenOnPort()
  • 두 가지 기능(디버깅 정보 출력 + 로컬 데이터베이스 설정)을 수행하는 플래그
    😈 : —- run locally
    😇 : —- use_local_db, --extra_loggin
    → 두 가지를 모두 포괄하는 것을 사용하는 것보다는 플래그를 2개 만드는게 좋음

추가적인 정보를 이름에 추가하기

  • 변수 이름 == 작은 설명문

  • 단위를 포함하기
    e.g

    • hex_id
    • start_ms
  • 다른 중요한 속성 포함하기
    어떤 변수에 위험한 요소 혹은 나중에 놀랄만한 내용이 있다면 사용
    e.g

    • 패스워드가 ‘plaintext’에 담겨 있고, 추가적인 처릴 위해 반드시 암호화 되어야 함
      😈 : password
      😇 : plaintext_password

    • 사용자에게 보여지는 설명문이 화면에 나타나기 전에 이스케이프 처리가 되어야 함
      😈 : comment
      😇 : unescaped_comment

이름은 얼마나 길어야 하는가?

  • 단어 하나 / 문자 하나로 된 이름 사용 함 vs 길게
    → 변수의 정확한 용도에 따라서 그때그때 판단
  • 좁은 범위(이름이 나타는 코드의 줄 수를 의미하는)에서는 짧은 이름 ok
    하지만, 그런 이름이 클래스의 멤버이거나 전역 변수일 때는 이야기가 달라짐
    → 타입이나 목적이 드러나지 않으므로 코드의 가독성이 떨어짐
  • 긴 이름 입력 - 더 이상 문제가 되지 않음
    • 문서 편집기에는 “단어 완성 기능” 존재
  • 약어와 축약형
    → 약어와 축약이 나중에 일어날지 모르는 혼란을 무릅쓸만한 가치가 있는가?
    → 팀에 새로 합류한 사람이 이름의 의미를 이해할 수 있는가? → ok
    e.g
    😈 : BEManager → BackendManager
    😇 : string → str

이름 포맷팅으로 의미를 전달하라

  • 밑줄, 대시, 대문자를 잘 이용하면 이름에 더 많은 정보를 담을 수 있음
    e.g
    포맷팅 방식
    • 클래스명 - camelCase
    • 변수명 - lower_seperated
    → 규칙에 따라서 이게 어디에 소속되는 변수인지 파악 가능
    (e.g. 클래스 멤버 or 지역 변수)
post-custom-banner

0개의 댓글