Book | 읽기 좋은 코드가 좋은 코드다

sik2·2021년 5월 2일
4

리뷰

목록 보기
3/12

첫번째 테마 클린코드에 관련한 도서입니다.

책 이름은 '클린 코드의 경우 읽기 좋은 코드가 좋은 코드다' 이며 전반적인 좋은 코드에 대해 저자의 생각을 심플하게 풀어냈습니다.

개발 관련 칼럼니스트로 유명하신 임백준님께서 번역하신 책입니다.

(무엇보다 분량이 작아서 너무 좋았습니다)

책 내용에서 인상 깊은 구절 정리를 할까 하다 쿡북(how to)느낌의 강해

내용을 전체적으로 잘 정리한 블로그 글 몇개를 참고해 작성했습니다.

참고 블로그는 하단 레퍼런스 url로 남겨두었습니다.

더스틴 보즈웰, 트레버 파우커 공저 / 임백준 역 | 한빛미디어

좋은 코드는 무슨 일이 일어나고 있는지를 빠르게 전달해준다.사용하기에도 즐겁고,
자신에게도 더 좋은 코드를 만들어야 하겠다는 욕구를 불러일으키기도 한다. (서론)

표면적 수준에서의 개선

코드는 이해하기 쉬워야한다
  • 코드는 다른사람이 이해하는데 들이는 시간을 최소화하는 방식으로 작성해야한다
  • 적은 분량으로 코드를 작성하는 것이 목표지만 이해하는 시간을 최소화 시키는게 더 좋은 목표다
  • 좋은 이름 짓기, 좋은 설명 달기, 코드를 보이 좋게 정렬하는 행위

이름에 정보담기

  • 추상적인 이름 대신 특정할 수 있는 구체적인 단어 고르기, 보편적인 이름 피하기 get ⇒ fetch, download
  • 축약할때는 보편적인 이름으로 쓰기 string ⇒ str
  • 변수명에 접두사 혹은 접미사로 세부 정보 덧붙이기 start_ms(밀리세컨즈)
  • 이름 포맷팅(관습) 지켜서 작성하기 var $all_images = $("img"); 제이쿼리 $변수명 관습 지키기

오해할 수 없는 이름들

  • 본인이 지은 이름을 ‘다른 사람들이 다른 의미로 해석할 수 있을까?’ 라는 질문을 던져보며 철저하게 확인해야 한다. filter() 거르다? 제거? 모호 ⇒ select()나 exclude() 로 명확하게
  • 한계 설정시 min, max와 같은 명확한 이름쓰기
  • 경계 포함 first, last
  • 경계를 포함하고 배제 begin, end
  • 불리언 변수에 이름 붙이기 is, has, can, should
  • 사용자 기대에 부응하기 get(), size()

미학

  • 좋은 소스 코드는 ‘눈을 편하게’ 해야한다.
  • 일관성 있는 스타일은 ‘올바른' 스타일보다 더 중요하다(들여쓰기, psr, Java Code Conventions)
  • 빈 줄을 이용하여 커다란 블록을 논리적인 ‘문단'으로 나누어라

주석에 담아야 하는 대상

  • 코드를 읽는 사람의 입장이 되어라 (코드를 처음으로 읽는 외부인의 입장에 자기 자신을 놓는 기법)
  • 나쁜 이름에 주석을 달지 마라 — 대신 이름을 고쳐라 (좋은 코드 > 나쁜코드 + 좋은 주석)
  • 코드가 특정한 방식으로 작성된 이유를 설명해주는 내용 (감독의 설명)
    - 상대방 입장에서 요점 파악을 쉽게 해줄 주석
    - 코드에 담긴 결함
    - 어떤 상수가 특정한 값을 갖게 된 ‘사연'
  • javadoc, jsdoc, phpdoc에 필요 정보 담아주기

루프와 논리를 단순화하기

읽기 쉽게 흐름제어 만들기

  • A > B (변수 > 10)
    - 왼쪽 : 값이 더 유동적인 질문을 받는 표현(변수)
    - 오른쪽 : 더 고정적인 값, 비교대상으로 사용되는 표현
    - cf_ 요다표기법 (옛날에 쓰던.. NULL == obj ) 피하기

if/else 블록의 순서

  • 부정이 아닌 긍정을 다루어라. 즉 if(!debug)가 아니라 if(debug)를 선호하자.

삼항 연산자

  • 줄 수를 최소화하는 일보다 다른 사람이 코드를 읽고 이해하는 데 걸리는 시간을 최소화하는 일이 더 중요하다.

  • 삼항 연산자는 두 값을 선택하는 문제에서만 쓰자

  • 좋은 예

time_str += (hour >= 12) ? "pm" : "am"
  • 나쁜 예
return exponent >= 0 ? matissa * (1 >> exponent) : matissa / (1 >> -exponent); (x)
// if 문으로 개선
if (exponent >= 0) {
 return mantissa * (1 << exponent);
} else {
 retrun matissa / (1 << -exponent);
}

거대한 표현 잘게 쪼개기

  • 코드의 표현이 커지면 커질수록 이해하기 더 어렵다.

설명 변수

  • 변수명 자체가 설명
if line.split(':')[0].strip() == "root": x

username = line.split(':')[0].strip() o
if username == "root":
  • 요약 변수

    	- 커다란 코드의 덩어리를 짧은 이름의 변수로 대체해 목적 파악을 빨리할 수 있도록 한다
  • 드모르간의 법칙 사용하기

if (!(file_exists && !is_protected)) x
if (!file_exists || is_protected) o
  • 쇼트 서킷 논리 오용 말기

    	- if ( a || b ) a가 참이면 b는 평가하지 않는다.
  • 복잡한 논리와 씨름하기

bool Range::OverlapsWith(Range other){
  // 'begin'dlsk 'end'가 'other'에 속하는지검사한다.
  return (begin >= other.begin && begin < other.end) ||
          (end > other.begin && end <= other.end) ||
          (begin <= other.begin && end >= other.end);
}
  • 더 우아하게 접근하기
bool Range:;OverlapsWith(Range other){
  if (other.end <= begin) return false; // 우리가 시작하기 전에 끝난다.
  if (other.begin >= begin) return false; // 우리가 끝난 후에 시작한다.
  
  return true; // 마지막 가능성만 남았다. 즉 겹친다.
}
  • 거대한 부분 나누기

  • 반복되는 부분을 ⇒ 요약변수로 추출
    - 타이핑 실수를 피할 수 있다.
    - 코드를 한눈에 훓어보는게 용이하도록 코드의 길이를 조이라도 더 줄여준다.
    - 클래스명을 변경해야 할 때 한 곳만 바꾸면 된다.

변수의 가독성

  • 변수를 엉터리로 사용하면 코드를 이해하기가 얼마나 어려워지는지 살펴본다.
    - 변수의 수가 많을수록 기억하고 다루기 더 어려워진다.
    - 변수의 범위가 넓어질수록 기억하고 다루는 시간이 더 길어진다.
    - 변수 값이 자주 바뀔수록 현재 값을 기억하고 다루기가 더 어려워진다.

변수제거하기

  • 불필요한 임시 변수들
now = datetime.datetime.now()
root_message.last_view_time = now
  • 이러한 변수가 구지 필요하지 않는 이유
    - 복잡한 표현을 잘게 나누지 않는다.
    - 명확성에 도움이 되지 않는다.
    - 한번만 사용되어 중복된 코드를 압축하지 않는다.
  • 중간 결과 삭제하기
var remove_ (array, value_to_remove) {
  var index_to_remove = null;
  for (var i = 0; i < array.length; i +=1 ){
    if (array[i] === value_to_remove) {
      index_to_remove = i;
      break;
    }
  }
  if (index_to_remove !== null) {
    array.splice(index_to_remove, 1);
  }
}

/** 위의 방법보다는 아래방법 **/

var remove_one = function (array, value_to_remove) {
  var index_to_remove = null;
  for (var i = 0; i < array.length; i +=1 ){
    if (array[i] === value_to_remove) {
      array.splice(i, 1);
      return;
    }
  }
}
  • 흐름 제어 변수 제거하기
boolean d

while(/*조건*/ && !done) {
 ...
 if(...){
  done = true;
   continue;
 }
}

while (/* 조건 */) {
 ...
 if (...) {
  break;
 }
}

변수의 범위를 좁혀라

  • ‘전역변수를 피하라’는 조언을 한번쯤 들었을 것이다.
    - 전역 변수는 어디에서 어떻게 사용되는지 일일이 확인하기 어려우므로 이는 합당한 조언이다.
    - 또한, 전역 변수의 이름과 지역 변수의 이름이 중복되어 이름공간이 더러워질 수도 있고, 어떤 코드가 지역 변수를 변경할 때 실수로 전역 변수를 변경하거나 혹은 그 반대의 경우가 일어날 수 있으므로 타당하다.
  • 사실 전역 변수 뿐만 아니라 모든 변수의 범위를 좁히는 일은 언제나 좋다.
  • 많은 프로그래밍 언어는 모듈, 클래스, 함수, 블록 범위 같은 다양한 범위/접근 수준을 제공한다.
  • 자바스크립트에서 프라이빗 변수 만들기
submitted = false;
var submit_form = function(form_name){
  if(submitted){
    return; // 폼을 두 번 제출하지 말라.
  }
  ...
  submitted = true;
}

submit_form() 만이 전역변수 submitted를 사용하는 유일한 함수처럼 보이지만,확실히 알 수 없다.

⇒ 다른 자바스크립트 파일에서 이와는 다른 목적으로 submitted라는 이름이 붙은 전역 변수를 사용할 지도 모르는 일이다!

⇒ submitted 변수를 클로저 내부에 집어 넣어서 이런 문제를 해결한다.

var submit_form = (function(){
 var submitted = false;
 return function(form_name){
  if(submitted){
   return; // 폼을 두 번 제출하지 말라.
  }
  ...
  submitted = true;
 }
}());

⇒ 프라이빗한 범위를 만드는 효과를 갖는다.

코드 재작성하기

엔지니어링은 커다란 문제를작은 문제들로 쪼갠 다음,각각의 문제에 대한 해결책을 구하고,다시 하나의 해결책으로 맞추는 일련의 작업을 한다.이러한 원리를 코드에 적용하면 코드가 더 튼튼해지며 가독성도 좋아진다.

  1. 주어진 함수나 코드 블록을 보고, 스스로에게 질문하라*“상위수준에서 본 이 코드의 목적은 무엇인가?”**
  2. 코드의 모든 줄에 질문을 던져라 이 코드는 직접적으로 목적을 위해서 존재하는가?혹은 목적을 위해서 필요하긴 하지만 목적 자체와 직접적으로 상관없는 하위문제를 해결하는가?
  3. 상당히 원래의 목적과 직접적으로 관련되지 않은 하위문제를 해결하는 코드 분량이 많으면,이를 추출해서 별도의 함수로 만든다.

한번에 하나씩 ⇒ 관심사 분리 방법

함수는 오직 한 가지 작업만 수행해야 한다.

  1. 코드가 수행하는 모든 ‘작업’을 나열한다.
  2. 이러한 작업을 분리하여 서로 다른 함수로 혹은 적어도 논리적으로 구분되는 영역에 놓을 수 잇는 코드로 만들면 된다.

생각을 코드로 만들기

  1. 코드가 할 일을 옆의 동료에게 말하듯이 평범한 영어로 묘사하라.
  2. 설명에 들어가는 핵심적인 단어와 문구를 포착하라.
  3. 설명과 부합하는 코드를 작성하라

코드 분량 줄이기

  1. 요구사항에 질문을 던지고 질문을 잘게 나누어 분석하라

ref)

https://www.slideshare.net/ddayinhwang9/ss-61286734
https://medium.com/inhyuck/읽기-좋은-코드가-좋은-코드다-리뷰-읽는중-e4002aa1378b
https://feel5ny.github.io/2018/08/01/Clean_code_1/

profile
기록

0개의 댓글