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

sik2·2021년 5월 2일
3

Book

목록 보기
3/6

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

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

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

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

책 내용에서 인상 깊은 구절 정리를 할까 하다 쿡북(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개의 댓글