연재 완료/읽기 좋은 코드 (Book review)

7장 읽기 쉽게 흐름제어 만들기

라이피 (Lypi) 2018. 6. 13. 14:30
반응형

PART Ⅱ. 루프와 논리를 단순화하기


7장. 읽기 쉽게 흐름제어 만들기

  - 제어문은 사실 코드를 읽기 어렵게 만든다. 
  ★ 흐름을 제어하는 조건과 루프 그리고 여타 요소를 최대한 '자연스럽게' 만들도록 노력하라. 
      코드를 읽다가 다시 되돌아가서 코드를 읽지 않아도 되게끔 만들어야 한다.


__01. 조건문에서 인수의 순서

  - 왼쪽에 '질문을 받는' 유동적인 값을 쓰고, 오른쪽에 비교대상으로 사용되는 고정적인 값을 써라.


__02. if/else 블록의 순서

  - 조건은 부정문이 아닌 긍정문으로 쓰려고하라. 
  - 간단한 것을 먼저 처리하라. 이러면 한 화면으로 두개의 구문을 볼 수 있을 가능성이 높아진다.
  - 더 흥미롭고, 확실한 것을 먼저 다루어라.
  - 위의 세가지 규칙이 서로 충돌을 일으킬 수도 있다. 중요한 것은 자신이 작성한 if/else문이 이상한 순서로 작성되었는지 확인하라는 것이다.


__03. ?: 연산자를 이용하는 조건문 표현

  ★ 줄 수를 최소하는 일보다 다른 사람이 코드를 읽고 이해하는데 걸리는 시간을 최소화하는 일이 더 중요하다.
  ★ 기본적으로 if/else를 이용하라. ?:를 이용하는 삼항 연산은 매우 간단할 때만 사용해야 한다.


__04. do/while 루프를 피하라

  - do/while루프는 코드를 두번 읽도록 만든다. 반면에 while 루프는 반복 조건을 먼저 확인할 수 있으므로 읽기 좋다.
  - 하지만 do/while을 제거하려고 중복된 코드를 사용하진 말라. 그렇게 하지 않아도 대부분의 do/while루프를 while루프로 변경할 수 있다.
  - 특히 do/while루프 안에서 continue를 사용하면 혼란을 초래하므로 피하는 것이 좋다. 
  (다만 이 조언이 do/while루프를 절대 쓰지 말라는 뜻은 아니다.)
  ★  "내 경험으로 에러와 혼동의 원인은 do문에 있다. 그래서 나는 조건이 '눈에 띄는 곳에 미리' 나타나도록 만드는 것을 선호한다. 
       결과적으로 나는 do문을 피하는 경향이 있다." - C++의 창시자 "반얀 스토라우스트럽"


__05. 함수 중간에서 반환하기

  - 반환 포인트를 하나만 두려는건 함수의 끝부분에서 실행되는 클린업(cleanup)코드의 호출을 보장하려는 의도이다. 
    하지만 현대의 언어들은 클린업 코드를 실행시키는 더 정교한 방법을 제공하고 있다. 
    그러므로 이제는 함수 중간에서 반환하는 것은 완전히 허용되어야 한다.


__06. 악명 높은 goto

  - goto를 쓰면 코드가 쉽게 엉망진창이 될 가능성이 높으므로 피하는 것이 좋다. 
    하지만 클린업 코드를 실행시키기 위해서 함수의 맨 밑으로 단 하나의 exit 포인트만 두는 방식이라면 goto의 괜찮은 사용법이라 할 수 있다. 
  (어지럽게 중첩된 코드에서 한번에 빠져나오기 위한 용도로도 goto는 유용하다. 그런 코드 자체를 지양해야겠지만 말이다.)


__07. 중첩을 최소화하기

  - 코드가 중첩된다는 것은 읽는 사람에게는 정신적 스택에 추가적인 조건이 입력된다는 뜻이다. 
  - 중첩이 추가되는 상황은 주로 코드를 수정하는 과정에서 새로운 코드를 추가할 때이다.
  ★ 코드를 수정해야 하는 상황이 오면 코드를 새로운 관점에서 혹은 코드 전체를 보고 어떻게 수정하면 좋을지 생각해보라.


  - 함수 중간에서 반환하여 중첩을 제거하라 (if/return)


  - 밖으로 빠져나가지 않고 루프 중간에서 반환해야 한다면 continue를 사용하면 된다. (if/continue)
    일반적으로 continue문은 goto처럼 논리의 흐름을 건너뛰게 하므로 읽는 이를 혼란스럽게 만들 수 있다.
    하지만 루프에 대한 각각의 반복이 독립적이라면 continue문이 단지 이번 반복을 건너뛰어라라는 의미임을 쉽게 확인할 수 있다.


  - 우리는 자신의 프로그램에 존재하는 '흐름'을 상위수준에서 조망해볼 필요가 있다. 
    궁극적인 목표는 프로그램의 전체 실행 경로를 쉽게 따라갈 수 있게 만드는 것이기 때문이다.
   다음은 흐름을 따라가기 어렵게 만드는 구조들이다. 이러한 구조들은 가능하면 사용을 지양하는 것이 좋다.

 프로그래밍 구조

 상위 수준에서 프로그램 흐름이 혼란스러워지는 방식

 스레딩

 어느 코드가 언제 실행되는지 불분명하다.

 시그널/인터럽트 핸들러

 어떤 코드가 어떤 시점에서 실행될지 모른다.

 예외(exceptions)

 예외처리가 여러 함수 호출을 거치면서 실행될 수 있다.

 함수 포인터 & 익명 함수

 실행될 함수가 런타임에서 결정되기 때문에 컴파일 과정에서는 어떤 코드가 실행될지 알기 어렵다.

 가상 메소드

 object.virtualMethod()는 알려지지 않은 하위클래스의 코드를 호출할지도 모른다.

   (혹은 위의 단점을 생각하며 주석을 달아놓는 것도 방법이다. 물론 좋은코드>나쁜코드+좋은주석 임을 잊지 말자)



반응형