Clean Code 책 요약. 챕터 1~3 : 깨끗한 코드, 의미있는 이름, 함수

작성 : 2021-04-03수정 : 2021-04-03

목차 펼치기

 출처 : yes24

출처 : yes24


1장 - 깨끗한 코드


  • 코드는 요구사항을 상세히 표현하는 수단이다.

  • 프로그래밍은 기계가 실행할 정도로 상세히 요구사항을 명시하는 작업이다.

  • 나쁜 코드에 발목이 잡혀 고생하는 걸 우리는 고행(wading)이라 부른다.

  • 우리 모두는 자신이 짠 코드를 나중에 리팩토링 하겠다고 생각한 경험이 있지만,

    그 나중은 결코 오지 않는다.
  • 나쁜 코드는 개발 속도를 떨어뜨리고, 계속 나쁜 코드가 더해지고, 매번 해독하게 만들어 팀 생산성이 떨어진다.

    • 이를 위해 추가되는 인력은 기존 시스템 설계를 잘 알지 못하기 때문에 더욱 나쁜 코드가 늘어난다.

    • 그러다 재설계를 위한 프로젝트가 진행되고, 우리는 깨끗한 코드를 만드는 노력이 전문가로서 살아남는 길이라는 것을 알게 된다.


태도

  • 프로젝트의 실패는 프로그래머에게도 커다란 책임이 있고, 나쁜 코드가 초래했다면 더더욱 크다.

    • 사용자 요구사항에 대한 현실적 자문에 올바르게 대답하지 못했다.

    • 프로젝트 관리자가 일정을 잡을 때 올바르게 대답하지 못했다.

    • 우리에게 정보를 구하지 않더라도,

      우리가 적극적으로 정보를 제공해야 마땅하다.
    • 좋은 코드를 사수하는 일은 우리 프로그래머의 책임이다. 나쁜 코드의 위험을 이해하지 못하는 관리자의 말을 따르는 것은 전문가 답지 못하다.


원초적 난제

  • 빨리 가려고 시간을 들이지 않지만, 나쁜 코드를 양산하면 기한을 맞추지 못한다.

  • 기한을 맞추고 빨리 가는 유일한 방법은,

    언제나 코드를 최대한 깨끗하게 유지하는 습관이다.


깨끗한 코드란?


우아하고 효율적인 코드


가독성이 좋은 코드


다른 사람이 고치기 쉬운 코드


주의 깊게 작성한 코드 (시간을 들여 깔끔하고 단정하게 정리한 코드)


중복 줄이기, 표현력 높이기, 초반부터 간단한 추상화 고려하기.


읽으면서 짐작했던 기능을 그대로 수행하기.

  • 언어를 단순하게 보이게 만드는 열쇠는 프로그래머다.


우리들은?


  • 우리들은 저자다. 저자에게는 독자가 있고, 독자와 잘 소통할 책임이 있다. 독자가 있다는 사실을 기억하라.

    • 코드를 읽는 시간 대 짜는 시간 비율이 10:1을 훌쩍 넘는다.
      즉, 새 코드를 짜면서 끊임없이 기존 코드를 읽는다.

  • 적극적으로 코드의 퇴보를 막아야 한다.

    • 체크아웃 할 때보다 좀 더 깨끗한 코드를 체크인 한다면 코드는 절대 나빠지지 않는다.



2장 - 의미있는 이름


javascript
1좋은 이름을 선택하려면 설명 능력이 뛰어나야 하고, 문화적 배경이 같아야 한다.
2좋은 이름을 선택하는 능력은 기술, 비즈니스, 관리 문제가 아니라 교육 문제이다.
3사람들이 이름을 바꾸지 않으려고 하는 이유 중 하나는 다른 개발자가 반대할까 두려워서이지만,
4좋은 이름으로 바꿔주면 오히려 고맙다.
5나름대로 바꿨다가 누군가 나중에 질책할 수도 있지만, 코드를 개선하려는 노력을 중단해서는 안 된다.

  • 우리는 변수에도 이름을 붙이고, 함수에도 이름을 붙이고, 인수와 클래스와 패키지에도 이름을 붙인다.

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

  • 십중팔구 개발자는 주석이나 목록을 살펴보지 않은 채, 이름만 보고 객체를 선택한다.


의도를 분명히 밝혀라.

  • 존재 이유, 수행 기능, 사용 방법에 대해 따로 주석이 필요하다면 의도를 분명히 드러내지 못한 것이다.

  • 코드 맥락이 코드 자체에 명시적으로 드러나야 한다.


그릇된 정보를 피하라.

  • 실제 List가 아니라면, List라 명명하지 않는다.

  • 일관성이 떨어지는 표기법은 그릇된 정보다.

  • 소문자 l과 숫자 1, 대문자 O와 숫자 0과 같은 문자를 조심해야 한다.
    폰트를 바꿔 해결해야 하는 것들은 이름을 바꾸자.


의미 있게 구분하라.

  • 컴파일러나 인터프리터만 통과하려는 생각으로 구현한 코드는 문제를 일으킨다.

  • 연속적인 숫자나, 불용어를 추가하는 방식은 부적절하다.

    • name1, name2, name3 ... 처럼 이름이 달라야 한다면 의미도 달라져야 한다.

    • 명확한 관례가 없다면 아래와 같은 이름은 구분이 안된다.
      moneyAmount - money
      customerInfo - customer
      accountData- account



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

  • 사람들은 단어에 능숙하고, 상당 부분 단어라는 개념만 처리한다.

  • 타인과의 소통 과정에서도 이름은 중요하다.

javascript
1// generate date, year, month, day, hour, minute, second.
2const genymdhms = new Date(); // 이 변수를 어떻게 읽을 것인가?
3const generationTimestamp = new Date();

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

  • 문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 쉽게 눈에 띄지 않는다.

    • max 와 MAX_CLASSES_PER_STUDENT 중 무엇이 명확히 검색될 지는 뻔하다.

  • 이런 관점에서는 긴 이름이 짧은 이름보다 좋다. 검색하기 쉽기 때문이다.

  • 검색하기 쉬운 이름이 상수보다 좋다.


인코딩을 피하라.

  • 인코딩은 불필요한 정신적 부담이 되며, 발음하기 어렵고, 오타가 생기기 쉽다.

  • 컴파일러가 변수에 타입을 강제하고, 클래스와 함수는 작아지는 추세에서 헝가리안 표기법이나 멤버 변수 접두어와 같은 인코딩 방식들은 오히려 방해가 될 뿐이다.


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

  • 독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못하다.

    • r 이라는 변수가 소문자 URL 이라는 사실을 언제나 기억한다면 똑똑한 사람이지만, 남들이 이해해야 하는 코드를 내놓아야 한다는 걸 명심하라.


클래스 이름

  • 클래스 이름과 객체 이름은 명사나 명사구가 적합하다.

  • Manager, Processor, Data, Info 등과 같은 단어는 피한다.

  • 동사는 사용하지 않는다.


메서드 이름

  • 동사나 동사구가 적합하다.

  • 접근자, 변경자, 조건자 같은 경우는 표준에 따라 get, set, is 와 같은 접두어를 붙인다.

  • Constructor Overload 보다는 static method를 사용한다.


기발한 이름은 피하라

  • 이름이 너무 기발하면 그 농담을 아는 동안만 알 수 있다.

  • 재미난 이름보다 명료한 이름을 선택하라.

  • 의도를 분명하고 솔직하게 표현하라.


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

  • 추상적인 개념 하나에 한 단어를 선택해 이를 고수하라.

    • 동일 코드 기반에서 [fetch, retrieve, get] 또는 [controller, manager, driver] 와 같이 혼용되어있다면 혼란스러울 것이다.

  • 메소드 이름은 독자적이고 일관적이어야 주석을 보지 않고서도 올바른 메소드를 선택할 수 있다.


말장난을 하지 마라.

  • 한 단어를 두 가지 목적으로 사용하지 마라.

    • 값을 더하는 것은 add 이고, 집합에 값을 추가하는 것은 insert 또는 append 이다.



해법 영역에서 가져온 이름을 사용하라.

  • 기술 개념의 영역에는 기술 이름이 가장 적합한 선택이다.

    • 코드를 읽을 사람도 프로그래머이기 때문이다.


문제 영역에서 가져온 이름을 사용하라.

  • 적절한 프로그래머 용어가 없다면 문제 영역에서 이름을 가져온다.

    • 해당 분야의 전문가에게 의미를 물어 파악할 수 있기 때문이다.



의미 있는 맥락을 추가하라.

  • 클래스, 함수 등의 namespace를 통해 맥락을 부여한다.

    • 여의치 않을 경우 접두어를 붙여 맥락을 부여한다.

  • 접두어 addr을 붙이거나, Address라는 클래스를 만들어 변수를 사용하면 city, state 와 같은 변수명이 주소의 일부라는 것을 알 수 있다.


불필요한 맥락을 없애라.

  • 의미가 분명한 경우에 한해 짦은 이름이 긴 이름보다 좋다.

  • Calculator 어플리케이션을 만든다고 가정 했을 때, 클래스 이름마다 Calculator나 Cal 같은 접두어를 붙일 이유가 없다.



3장 -함수

  • 어떤 프로그램이든 가장 기본적인 단위가 함수이다.


작게 만들어라.

  • 각 함수는 명백히 하나의 이야기를 표현한다.

  • 즉, 중첩 구조가 생길만큼 함수가 커져서는 안 된다. 그래야 읽고 이해하기 쉬워진다.

    • 함수에서 들여쓰기 수준은 2단을 넘어서지 말자.

    • 적절한 네이밍과 함께면 훨씬 코드를 이해하기 쉬워진다.


한 가지만 해라.

  • 지정한 함수 이름 아래 추상화 수준이 하나인 단계만 수행한다면, 한 가지 작업만 하는 함수라고 할 수 있다.

  • 의미 있는 이름으로 다른 함수를 추출할 수 있따면, 그 함수는 여러 작업을 하는 셈이다.


함수 당 추상화 수준은 하나로.

  • 함수가 확실히 '한 가지' 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다.

    • 추상화 수준이 섞이면 읽는 사람이 헷갈려진다. 특정 표현이 근본 개념인지, 세부사항인지 구분이 어려워지기 때문이다.

      • 이 구분이 모호해지면, 사람들은 함수에 세부사항을 추가하기 시작한다. (like 깨진 유리창)

  • 코드는 위에서 아래로 이야기처럼 읽혀야 좋다.

    • 읽어 내려갈수록 추상화 수준이 한 번에 한 단계씩 낮아지는 것이다.

  • 추상화 수준이 하나인 함수

    를 구현하기란 쉽지 않지만, 이는 매우 중요한 규칙이다.


Switch 문법

  • 본질적으로 N가지를 처리하기 때문에 작게 만들기 어렵다.

  • 저차원 클래스에서 숨기고 중복을 피하여 사용한다.

  • 하지만 불가피하게 사용해야 하는 상황들이 존재하기 때문에 완전히 피할 수 없다.


서술적인 이름을 사용하라.

  • 함수가 하는 일을 더 잘 표현할 수 있는 좋은 이름이다.

  • 함수가 작고 단순할수록 서술적인 이름을 고르기도 쉬워진다.

  • 길고 서술적인 이름이 짧고 어려운 이름 또는 길고 서술적인 주석보다 좋다.

  • 여러 단어가 쉽게 읽히는 명명법을 사용한다.

  • 일관성 있는 이름을 붙여야 한다.

    • 같은 문구, 명사, 동사를 사용한다.


함수 인수

  • 인수는 개념을 이해하기 어렵게 만들므로 적을수록 좋다.

  • 인수가 많을수록 테스트케이스를 작성하는 것도 부담스러워 진다.

  • 플래그 인수는 추하다. 대놓고 함수가 여러가지 기능을 한다고 공표하는 것이기 때문이다.

  • 객체 인수는 변수를 묶어 넘길 때 이름을 넘기게 되므로 개념을 표현하게 된다.

  • 함수와 인수가 동사/명사 쌍을 이루면 기능을 분명하게 드러낼 수 있다.

  • 함수명에 인수명을 명시하면 인수의 순서를 기억할 필요가 없어진다.


부수 효과를 일으키지 마라

  • 함수로 넘어온 인수 또는 시스템 전역 변수를 수정하는 코드는 교활하고 해로운 거짓말이다.

  • 시간적인 결합(temporal coupling) 또는 순서 종속성(order dependency)를 초래한다.

  • 부수 효과가 발생하면 안되는 상황에서는 해당 함수를 사용할 수 없게 되고 이는 혼란을 야기한다.

  • 일반적으로 출력 인수는 지양한다.


명령과 조회를 분리하라.

  • 함수는 뭔가를 수행하거나, 답하거나 둘 중 하나만 해야 하며 둘 다 하면 혼란을 초래한다.

  • 명령과 조회를 분리하면 혼란을 뿌리 뽑을 수 있다.


오류 코드보다 예외를 사용하라.

  • 예외를 사용하면 오류 처리 코드가 원래 코드에서 분리되어 코드가 깔끔해진다.

    • 오류 코드를 반환한다는 것은 어디선가 오류 코드를 정의하고 있다는 것이다.

  • try/catch 블록은 정상 동작과 오류 처리 동작을 뒤섞기 때문에 블록 별 별도의 함수로 뽑아내는 편이 좋다.

    • try 동작을 하는 함수와 catch 동작을 하는 함수로.

  • 오류 처리도 한 가지 작업이므로 오류를 처리하는 함수 또한 오류만 처리해야 한다.


반복하지 마라.

  • 중복은 코드 길이를 늘리고, 알고리즘 변경 시 수정해야 하는 포인트가 늘어나 오류가 발생할 확률을 높인다.

  • 중복은 모든 악의 근원이다.!!!!
    • S/W 개발 혁신의 대부분은 중복을 제거하려는 지속적인 노력이다.


함수를 짜는 방법

  • 코딩은 작문과 비슷하다.

    • 초안은 어수선하고, 원하는 대로 읽힐 때까지 말을 다듬고 문장을 고치고 문단을 정리한다.

  • 처음 함수를 짤 때는 길고 복잡하고 즉흥적이다.

  • 작성한 후 코드를 다듬고, 함수를 만들고, 이름을 바꾸고, 중복을 제거하고, 메소드를 줄이고, 순서를 바꾸고, 때론 전체 클래스를 쪼갠다.

    • 최종적으로 모든 단위 테스트를 통과하는 클린한 코드가 만들어진다.




Contact Me

All Icons byiconiFy