[Clean Code] 3장 함수

Bam·2023년 1월 25일
0

책꽃이

목록 보기
3/8
post-thumbnail

프로그래밍에서 가장 작은 단위로 함수가 있다. 함수를 기반으로 어떤 것이 작동을 하고, 이 함수들이 모여서 하나의 프로그램을 만들게 된다. 함수형 프로그래밍이 대세를 이루듯이 점점 함수를 잘 작성하는 것이 중요한 점으로 꼽히고있는데, 이번 장에서는 어떻게 하면 함수를 깨끗하게 작성할 수 있는 지에 대해서 알아보도록 하겠습니다.


작게 만들어라

코드 길이가 짧을수록 함수를 이해하기가 쉽다.

함수를 작게 만들라고하지만 이 책에서 그에 대한 명확한 근거를 대지는 못한다. 이른바 "저자의 감"? 하지만 내 경험상(로버트 C.마틴도 또한) 확실히 짧은 함수가 코드를 읽어낼 때 이해하기 편했던 것들을 생각한다면 수치적인 근거가 없어도 이해가 되는 부분이었다.

이에 대해 함수가 커지는 원인인 블록들여쓰기를 자제할 것을 권고하고있다. 이들이 발생하는 원인은 중첩 구조때문인데, 다시말하자면 중첩 구조를 함수 내에서 최대한 적게 만드는 것이 이해하기 쉬운 함수를 작성하는데 도움을 준다.


한 가지만 해라

함수는 한 가지를 해야한다. 그 한 가지를 잘 해야한다. 그 한 가지만을 해야 한다.

한 가지 일이라는 표현이 조금 애매하다. 그래서 이 책에서는 다음과 같은 기준을 제시하고 있다.

주어진 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 일만 한다.

함수의 이름의 의미를 유지하면서 함수를 줄일 수 없다면, 그 함수는 한 가지 일을 한다고 판단한다. 또, 함수의 내용 중에서 어떤 부분을 의미있는 이름을 가진 부분으로 추출할 수 있다면 그 함수는 여러 일을 하고 있다고도 판단할 수 있다.


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

함수 내 모든 문장의 추상화 수준은 동일해야한다.

방금 언급한 한 가지 일만을 하기 위해선 함수 내의 코드들의 추상화 수준이 모두 동일해야한다. 만약 한 함수 내에서 추상화 수준이 다양하게 섞인다면 읽는 사람에게 혼란을 주게된다. 이를 위해서 코드를 작성할 때 위에서 아래로 읽히는(내려가기 규칙) 코드를 작성하는 것이 좋다.


Switch 문

Switch 문의 사용을 자제하거나, 사용하더라도 숨긴다.

Switch 문은 그 특성상 작게 만드는 것이 아주 어렵다. 또한 한 가지 일만 하는 Switch 문을 만드는 것도 어렵다. 그래서 함수를 작성할 때는 Switch 문을 가급적이면 사용하지 않는게 좋다. 혹은 사용하더라도 저차원 클래스에 숨기는 것이 좋다.


서술적인 이름을 사용하라

함수가 하는 일을 알기 쉬운 서술적인 이름을 사용하라

변수편에서 언급했듯이 이름은 그 함수(변수)가 무슨 일을 하는지 알기 쉽도록 적는 것이 좋다. 함수 이름을 읽었을 때 그 이름을 보고 상상했던 동작을 함수가 그대로 동작시킨다면 그 코드는 깨끗하다고 할 수 있다. 앞서 소개한 원칙들을 지키다보면 자연스럽게 서술적인 함수 이름이 나오게 될 것이다. 함수가 작고 단순할수록 서술적인 이름을 고르기가 쉽다.

이름 선택법

  • 길고 서술적인 이름이 짧고 어려운 이름보다 좋다.
  • 길고 서술적인 이름이 길고 서술적인 주석보다 좋다.
  • 여러 단어들이 쉽게 읽히는 명명법을 이용한다.
  • 여러 단어들을 조합해 기능을 잘 표현하는 이름을 사용한다.
  • 같은 모듈 단위 내에서 이름은 일관성 있게 짓는다.

함수 인수

3항 이상의 인수는 피하는 것이 좋다.

가장 이상적인 인수는 0항이고 그 다음이 1항 2항이다. 3항까지는 피할 수 있다면 피하고, 4항 부터는 이유가 없다면 사용하지 말아야한다. (또는 이유가 있어도 쓰지 않는 것이 좋다.) 인수가 많아지면 읽는 사람이 인수의 의미를 파악해야하고, 테스트할 때도 과정이 추가되어 복잡해지는 결과를 초래하게 된다.

단항

단항 함수는 인수에 질문을 던질 때, 인수를 무언가로 변환해 결과를 얻을 때, 이벤트 함수인 경우에만 사용하도록 한다.

플래그

플래그(bool 값)은 사용하지 않도록 한다. 플래그 값을 넘기는 것은 함수 내에서 여러가지 처리를 하겠다는 의미와도 같다.

이항

인수가 하나인 경우보다 이해하기가 어려워지기에 사용을 자제한다. 단, 좌표 정보 등을 나타내는 경우엔 이항이 적합할 수도 있다. 이 경우는 두 값이 모여서 하나의 정보를 의미하기에 단항처럼 이해할 수 있다.

삼항

삼항 함수는 이항에서 일어날 수 있는 문제들이 배로 발생한다. 따라서 사용을 하지 않는 것을 추천하고, 사용을 신중히 고려할 것을 권고한다.

인수 객체

2~3개의 인수가 올 경우 인수를 독자적인 클래스 변수로 선언해서 사용할 것을 고민해본다. 만약 2개 이상의 인수가 독자적인 클래스로 묶인다면, 클래스로 묶는 것이 인수도 줄이고 개념을 표현하는데 더욱 적절하다고 할 수 있다.

인수 목록

가변 인수를 사용하는 함수들을 사용할 때가 있는데, 가변 인수들을 하나로 묶어 이항, 삼항...으로 취급할 수 있다. 하지만 이 경우에도 인수가 늘어나느 것을 주의해야한다.

동사와 키워드

함수의 의도나 인수의 순서, 의도를 표현하기 위해선 좋은 함수 이름이 필요하다. 함수와 인수가 동사/명사 쌍을 이루도록 하는 것이 그 방법이다. 또는 함수 이름의 인수 이름(키워드)을 넣어 표현하는 것도 좋은 방법이다.


부수 효과를 일으키지마라

부수효과가 일어나면 함수가 여러가지 일을 하게된다. 게다가 부수효과는 알게모르게 일어나므로 코드에 큰 혼란을 초래한다.

추가적으로 출력 인수는 피하고, 함수 내에서 상태가 바뀔 경우에는 함수가 속한 객체의 상태를 변경하는 방식을 사용해야한다.


명령과 조회를 분리하라

함수는 무언가를 수행하거나, 답하거나 둘 중 하나만 해야한다.

함수가 어떤 상태를 변경하고 대답을 동시에 해낸다면 그 함수는 혼란을 초래한다.


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

명령 함수에서 오류 코드를 반환하는 방식은 명령/조회 분리 규칙을 위반한다.

오류 코드를 작성하면 if 문의 중첩을 불러일으키고 이는 복잡한 함수 내부 구조를 만들게 된다. 따라서 예외 처리 구문을 이용하는 것이 더욱 깨끗한 코드를 작성할 수 있게 도와준다.

try~catch 구문 분리

if문 만큼은 아니지만 try~catch 구문도 중첩 구조를 갖는다. 따라서 이 부분도 함수로 분리해주는 것이 좋다.

오류 처리도 한 가지 작업이다.

함수는 한 가지 일을 해야한다. 그리고 오류 처리도 한 가지 작업이다. 따라서 오류 처리 함수는 오류만 처리해야한다. 다시말해 try~로 시작하는 함수는 catch/finally로만 끝나야한다.


반복하지 마라

중복된 구조는 코드 길이를 늘어나게 하고, 특정 부분을 수정할 때 똑같이 네 군데를 고쳐야하는 문제를 발생시킨다. 따라서 중복은 나오지 않도록 하는 것이 좋다.

많은 프로그래밍 원칙들이 중복을 없애고 제어하기 위해서 등장했다. 객체지향에서는 코드를 부모 클래스에 넣어 중복을 방지한다. 구조적 프로그래밍, AOP, COP 같은 기법들도 어떻게 보면 중복 제거 전략이라고 할 수 있다. 서브 루틴 이후로 프로그래밍의 역사에서 일어난 혁신들은 중복을 제거하기 위한 지속적 노력이라고 볼 수 있다.


구조적 프로그래밍

에츠허르 데잌스트라의 구조적 프로그래밍은 다음과 같다.

  • 모든 함수와 함수 내 모든 블록의 입구와 출구는 하나여야한다.(= 함수는 return이 하나여야한다.)
  • 루프 내에서 break나 continue는 사용하지말고 goto는 절대로 사용하지 말라.

하지만 이 책에서 저자는 아주아주 작게 만든 함수에서 위 두 가지 규칙은 별다른 이익을 주지 못한다고 한다. 그래서 함수가 아주 작다면 return, break, continue를 여러번 사용해도 괜찮다고 한다. 하지만 goto문은 작은 함수에서 의미가 완전히 없으므로 사용하지 말 것을 권장하고 있다.


함수의 작성법

책에서 알려주는 함수 작성법입니다. 어떻게 해야 소개한대로 깨끗한 함수를 작성할 수 있는지에 대해서 소개하고 있습니다.

처음부터 완성된 깨끗한 함수를 작성하기 보단, 손가는대로 작성한 초안같은 코드를 작성한다. 테스트 코드도 포함해서.

그 후 코드를 다듬고, 함수를 만들어내고, 이름 바꾼다. 그리고 중복도 제거한다. 그 외에도 메소드를 줄이고 순서도 바꾸며 전체 클래스를 쪼개기도한다. 이 작업을 거치는 동안 만들었던 테스트 케이스는 항상 통과하도록 한다.

이 과정들을 하다보면 지금까지 소개했던 조건들을 만족하는 함수가 탄생하게 된다.


후기

이번 장에서는 깨끗한 함수를 작성하는 방법에 대해서 알아보았습니다. 읽으면서 보다보니 타입스크립트를 찍먹할 때 자주 언급된 함수형 프로그래밍의 방식과 상당히 비슷한 작성법들이 있음을 느꼈습니다. 함수형 프로그래밍도 가독성을 위해 발전한 방식이니만큼 이 책과 같은 방식을 선택하고 있다고 생각이 됩니다.

개인적으로 함수를 작게 짜야지 해놓고 가장 어려웠던 것이 함수가 한 가지 일만을 하는 것이 었습니다. 나름 쪼갠다고 쪼갰지만 내 함수는 항상 1인 다역의 달인이 되어있었습니다. 마지막에 작가가 직접 남긴 함수 작성법의 도움을 받아 좋은 함수를 작성하는 프로그래머가 될 수 있도록 노력해야지 하고 덮게되는 클린 코드 3장 함수였습니다.

0개의 댓글