프로그래밍 원칙

반면교사를 통해 배운 프로그래밍 원칙


전제

  • 불확실성(개발자가 고려하지 못한 상황)은 버그의 원인이 된다
  • 시스템이 아닌 개인의 능력에 의존하는 소프트웨어의 경쟁력은 오래가지 못한다

encapsulation

  • 특정 기능을 제공하는 API를 구현할 때에는 구체적인 자료구조는 숨겨 오직 함수로만 내부 데이터를 조작하도록 유도하자
    • 사용자가 직접 내부 데이터(구조체 필드)에 접근하면 개발자의 의도와 다르게 사용할 가능성이 높기 때문에 버그의 원인이 된다
    • 함수를 통해서만 내부 데이터를 조작하면 불확실성을 최소화할 수 있다
  • 함수(메뉴얼 포함)와 구조체 이름만 제공하자
    • API 사용자는 그 이상(함수의 구현)은 알 필요도 없고 분석하는 것은 시간낭비다

계층화

  • 프로젝트 전체를 계층화 하여 모든 계층은 한 단계 아래 계층의 API만 사용하도록 추상화하자
    • 깔끔하게 모듈화가 가능하다 --> 테스트 작성이 편하다
    • 자주 사용될 모듈(list, hashmap과 같은 자료구조)을 하위 계층으로 분리하면 재활용성이 올라간다
  • 시스템(하드웨어 또는 운영체제) 의존적인 매크로는 하나의 계층에서만 사용하자
    • 매크로 분기는 코드 분석을 어렵게 만든다
    • 시스템 의존적인 코드를 한 번 감싸면 코드의 수정량을 최소화할 수 있다
  • 외부 라이브러리는 한 번 감싸서 제공하자
    • 외부 라이브러리의 구현이 바뀌었을때 코드의 수정량을 최소화할 수 있다

테스트

  • 단위 테스트를 작성하자
    • 기능이 추가되거나 구현이 변경될 경우 테스트 코드가 있으면 테스트 실행만으로 문제가 없음을 보장받을 수 있다
    • 코드를 수정할때마다 side effect를 분석하는 것은 불가능하다
  • 테스트 코드를 보면 각 함수가 어떤 일을 하는지 쉽게 파악 가능하다

함수

  • 함수가 하는 일은 접속사 없이 한 문장으로 설명이 가능할때까지 분리
    • 함수의 재활용성이 높으면 버그 수정에 용이하다
    • 줄 수가 크고 하는 일이 많은 함수는 분석하는데 시간이 오래 걸린다 --> 새로운 사람이 올때마다 설명해주는 시간이 아깝다
  • 반환값으로 성공/실패 여부를 표현하고 결과값은 [out] parameter로 전달하자
    • 무책임하게 난사한 Throw는 코드의 흐름을 예상하기 힘들게 만들고 이런 불확실성이 버그를 유발한다
    • 예를 들면 어떤 변수가 해제되었는지 알 수 없기 때문에 SIGSEGV의 발생 위험성을 높인다
    • 성공하면 0을 반환하고 실패하면 1을 반환하는 형태는 C/C++ 라이브러리에서는 일반적인 관습이다(e.g. pthread, unix system call 등)
  • 이름에 줄임말을 쓰지 말고 문장처럼 풀어서 쓰자
    • 동사가 없이 명사만 있는 함수 이름은 이름만으로 기능을 유추하기 힘들다
    • 줄임말은 원래 단어를 유추하기 힘들다. 그리고 자동완성 기능이 있는데 귀찮다고 줄임말을 쓰는건 말이 안된다