ETC

클린코드 작성하기 Part 1

5_ssssseung 2021. 8. 31. 23:21

1. 클린코드란 무엇일까?

클린코드를 올바르게 이해하기에 앞서 소프트웨어 대가들은 클린코드가 무엇이라고 생각할까

우아하고 효율적인 코드를 좋아한다. 논리가 간단해야 버그가 숨어들지 못한다. ··· 클린코드는 한가지를 제대로 한다. 비야네 스트롭스트룹 (C++ 창시자)

훌륭한 프로그래머는 사람이 이해할 수 있는 코드를 짠다. 마틴파울러 (리팩토링 저자)

클린코드는 단순하고 직접적이다. 클린코드는 잘 쓴 문장처럼 읽힌다. 클린코드는 결코 설계자의 의도를 숨기지 않는다. - 그레디 부치 (객체지향 대가)

코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행한다면 클린코드라 불러도 되겠다. 워드 커닝엄 (위키 창시자, 익스트림 프로그래밍 창시자)

 

대가들은 클린코드를 표현하는데 있어 공통적으로 다음을 뜻을 내포하고 있다.

코드를 작성한 의도와 목적이 명확하며 다른 사람이 쉽게 읽을 수 있어야 한다는 점이다.

코드의 가독성이 좋다는 것은 다른 사람이 코드를 이해하는데 들이는 시간을 최소화 하는 방식으로 작성되는 것을 의미한다.

 

2. 클린코드는 왜 필요할까?

개발자가 새로운 기능을 추가하거나 수정하기 위해 코드를 읽고 쓰는 비율을 따져본다면 읽기 : 쓰기 = 10 : 1과 같이 읽기 비율이 상당히 높을 것이다.

 

그렇기 때문에 읽기 쉬운 코드를 짜는 것이 개발자에게는 매우 중요하다.

개발시간을 단축하기 위해서는 처음부터 읽기 쉬운 코드로 짜면 되는 것이다.

 

새로운 프로젝트에 착수하고 개발을 시작했다고 하더라도 이후에 유지보수는 피할 수 없을 것이다.

최초 개발 단계에서는 설계나 코드 품질에 대해 많은 노력을 기울이지만, 완료 시점이 다가올수록 시간이 부족하는 등의 이유로 테스트나 리펙토링에 소홀해지기 쉽다.

 

제품 및 서비스가 론칭되고 새로운 요구사항이 들어오면 변경과 결함수정을 반복할 것이다.

점점 코드의 크기와 복잡도는 증가할 것이고 기존 기능에 대해 이슈가 발생할까 두려워 리팩토링도 어려워지게 된다.

 

이러한 악순환으로 소위 냄새나는 코드 (code smell)가 만들어지고 소프트웨어는 노후화된다..

 

3. 클린코드를 만드는 규칙들

냄새나는 코드를 일부러 만드는 것은 아니지만 잘못된 클래스의 책임 설정이나 부적합한 이름, 모호한 경계설정 등의 설계 상의 약점들이 쌓이다보면 냄새나는 코드를 피하기 어려워진다.

개발자가 개발과정에서 어떠한 점들을 유의해야 하는지 대표적인 규칙들을 알아보고자 한다.

 

3.1 의미있는 이름 (naming)

변수나 클래스, 메서드의 이름을 지을 때 아래와 같은 질문을 통해 의도가 뚜렷한 이름을 사용해야 한다.

  • 왜 존재해야 하는가?
  • 무슨 작업을 하는가?
  • 어떻게 하는가?

클래스는 행위의 주체로써 명사나 명사구로 표현하고, 함수 이름은 클래스가 행하는 행위로서 동사 또는 동사구로 사용한다.

클래스 멤버 함수
CIOCPServerDlg startStationServer
CIOCPServerDlg makeLogPath
CIOCPServerDlg writelog

 

코드 상에 나만 아는 숫자를 쓴다든지 추상적인 변수명으로 무엇을 하는지 알 수 없는 이름도 사용하지 않도록 한다.

// 어떤 의미인지 알 수 없는 25

if (count > 25) {
    return;
}

---
// 언제 호출해야 하는지 의미 파악이 어려운 메서드

do()
process()

 

아래와 같이 변수명을 i, j, k로 쓰는 것도 혼동을 가져다준다.

이러한 경우 club_i, member_i, user_k와 같이 변수명이 길어져도 구분할 수 있는 변수명을 사용하도록 한다.

for (int i = 0; i < clubs.size(); i++)
    for (int j = 0; j < clubs[i].members.size(); j++)
        for (int k = 0; k < users.size(); k++)
            if (clubs[i].members[k] == users[j])
                count << "user[" << j << "] is in club[" << i << "]" << endl;

 

문맥에 맞는 단어를 사용하고 일관성 있는 단어를 사용한다. 한 단어를여러 목적으로 사용하는 것도 피한다.

아래와 같이 select로 시작하는 메서드 중간에 갑자기 find로 시작하는 메서드가 나온다던지, get 이외에 fetch를 쓰는 경우 처음보는 개발자는 다른 메서드라고 생각하고 동일 기능을 하는 코드가 있음에도 불구하고 새로운 코드를 추가할 수 있다.

selectBook(...),
selectMusic(...),
findVideo(...)	// select로 통일 지향

---

public class Vehicle{

    public double getFuelRemaining();
    public double retrieveDegreeOfTireAbrasion();
    public double fetchCurrentSpeed();	// get으로 통일 지향

}

 

3.2 명확하고 간결하게 주석달기 (Comment)

이해를 돕기 위해 주석을 코드에 적게 되는데, 왜 주석을 달아야 하는지 생각해봐야한다.

간혹 필요 없는 주석이나 이상한 주석은 코드를 읽는 것을 더 방해한다.

따라서 주석이 필요한 경우 최대한 간결하고 명확하게 작성하여 읽는데 많은 시간을 사용하지 않도록 주의한다.

 

3.3 보기좋게 배치하고 꾸며라 (Aesthetics)

인터넷 글을 읽을 때, 같은 내용이라도 문단, 폰트, 배열에 따라 가독성이 달라진다.

마찬가지로 코드에서도 읽는 사람이 편하게 구성하는 것이 중요하다.

  • 반복되는 구문은 함수 등으로 선언하여 정리한다.
  • 선언시점에 유사한 속성들로 분리해서 정리한다.