본문 바로가기
ETC/개발 지식

[CleanCode] 3장 함수 - 1

by heekng 2022. 6. 26.
반응형

함수 - 1

작게 만들어라

  • 함수를 만드는 첫째 규칙은 작게이다. 둘째 규칙은 더 작게이다.

블록과 들여쓰기

  • if문, else문, while문 등에 들어가는 블록은 한줄이어야 한다.
  • 한줄에서 대개 함수를 호출한다.
    • 블록 안에서 호출하는 함수 이름을 적절하게 짓는다면, 코드를 이해하기도 쉬워진다.
  • 즉, 중첩 구조가 생길만큼 함수가 커져서는 안된다.
  • 함수에서 들여쓰기 수준은 1단이나 2단을 넘어가면 안된다.

한 가지만 해라

  • 함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다.
  • 지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 하는 것이다.
    • 함수를 만드는 이유: 큰 개념을 다음 추상화 수준에서 여러 단계로 나눠 수행하기 위해서
  • 단순히 다른 표현이 아니라 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 셈이다.

함수 내 섹션

  • 한 가지 작업만 하는 함수는 자연스럽게 섹션으로 나누기 어렵다.

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

  • 함수가 한 가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다.
// 추상화 수준 높음
getHtml()
// 추상화 수준 중간
String pagePathName = PathParser.render(pagepath);
// 추상화 수준 아주낮음
.append("\n");
  • 한 함수 내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다.
  • 근본 개념과 세부사항을 뒤섞기 시작하면, 깨어진 창문처럼 사람들이 함수에 세부사항을 점점 더 추가한다.

위에서 아래로 코드 읽기: 내려가기 규칙

  • 코드는 위에서 아래로 이야기처럼 읽혀야 좋다.
  • 위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아진다.

Switch문

  • switch, if, else 문은 작게 만들기 어렵다.
  • switch문을 추상 팩토리에 숨기고, 다형성을 이용해 실제 파생 클래스의 함수를 실행시키자.
  • 상속 관계로 숨긴 후에는 절대로 다른 코드에 노출하지 않는다.

서술적인 이름을 사용하라

  • 함수가 작고 단순할수록 서술적인 이름을 고르기도 쉬워진다.
  • 길고 서술적인 이름이 짧고 어려운 이름보다 좋다.
  • 함수 이름을 정할 떄는 여러 단어가 쉽게 읽히는 명명법을 사용한다.
  • 서술적인 이름을 사용하면 개발자 머릿속에서도 설계가 뚜렷해지므로 코드를 개선하기 쉬워진다.
  • 이름을 붙일 때는 일관성이 있어야 한다. 모듈 내에서 함수 이름은 같은 문구, 명사, 동사를 사용한다.

함수 인수

  • 함수에서 이상적인 인수 개수는 0개, 1개, 2개 순서이다.
    • 3개 이상은 피하는 편이 좋다.

많이 쓰는 단항 형식

  • 인수에 질문을 던지는 경우
    • boolean fileExist("MyFile")
  • 인수를 뭔가로 변환해 결과를 반환하는 경우
    • inputStream fileOpen("MyFile")
  • StringBuffer transform(StringBuffer in)void transform(StringBuffer in)보다 좋다.
    • 입력 인수를 그대로 돌려주는 함수라 할지라도 변환 함수 형식을 따르기 때문에

플래그 인수

// 나쁜 예
render(boolean isSuite)
// 좋은 예
renderForSuite()
renderForSingleTest()

이항 함수

  • 인수가 2개인 함수는 인수가 1개인 함수보다 이해하기 어렵다
    • writeField(name)writeField(outputStream, name)보다 이해하기 쉽다.
  • 이항 함수가 적절한 경우도 있다.
    • Point p = new Point(0, 0)
  • writeField(outputStream, name)의 경우 outputStream을 현재 클래스 구성원 변수로 만들어 인수로 넘기지 않는 방향으로 개선할 수 있다.

삼항 함수

  • 인수가 3개인 함수는 인수가 2개인 함수보다 훨씬 더 이해하기 어렵다.

인수 객체

// 나쁜 예
Circle makeCircle(double x, double y, double radius);
// 좋은 예
Circle makeCircle(Point center, double radius);
  • 인수가 2~3개 필요하다면 일부를 클래스 변수로 선언할 가능성을 짚어본다.
  • 객체를 생성해 인수를 줄이는 방법이 눈속임이라 여겨지지만, 결국 개념을 표현하기 때문에 그렇지 않다.

인수 목록

  • String.format과 같이 가변 인수 전부를 동등하게 취업하면 List 형 인수 하나로 취급할 수 있다.
  • 이러한 논리로 String.format은 사실상 이항 함수이다.

동사와 키워드

  • 함수의 의도나 인수의 순서와 의도를 제대로 표현하려면 좋은 함수 이름이 필요하다.
  • 단항 함수는 함수와 인수가 동사/명사 쌍을 이뤄야 한다.
  • write(name)은 이름이 무엇이든 쓴다는 뜻이다.
  • 조금 더 나은 이름으로 writeField(name)을 사용할 수 있다. 그러면 이름이 필드라는 사실이 분명하게 드러난다.
  • 함수 이름에 키워드를 추가하는 형식도 좋다.
    • assertEquals보다 assertExpectedEqualsActual(expected, actual)이 더 좋다.
    • 그러면 인수 순서를 기억할 필요가 없어진다.
반응형

'ETC > 개발 지식' 카테고리의 다른 글

[CleanCode] 5장 형식 맞추기  (0) 2022.06.30
[CleanCode] 4장 주석  (0) 2022.06.28
[CleanCode] 3장 함수 - 2  (0) 2022.06.26
[CleanCode] 2장 의미있는 이름  (0) 2022.06.25
Cron 표현식  (0) 2022.06.24
[Object] 객체지향 프로그래밍 2  (0) 2022.05.16