Clean Code 3장

함수

Untitled

3장 함수


함수를 잘 만드는 방법을 알려주는 챕터

읽기 쉽고 이해하기 쉬운 함수가 왜 읽기 쉽고 이해하기 쉬운지

의도를 분명히 표현하는 함수를 구현하는 방법

읽는 사람이 프로그램 내부를 직관적으로 파악하게 하는 방법

목차


  • 작게 만들어라!
    • 블록과 들여쓰기
  • 한 가지만 해라!
    • 함수 내 섹션
  • 함수 당 추상화 수준은 하나로!
    • 위에서 아래로 코드 읽기: 내려가기 규칙
  • Switch 문
  • 서술적인 이름을 사용하라!
  • 함수 인수
    • 많이 쓰는 단항 형식
    • 플래그 인수
    • 이항 함수
    • 삼항 함수
    • 인수 객체
    • 인수 목록
    • 동사와 키워드
  • 부수 효과를 일으키지 마라!
    • 출력 인수
  • 명령과 조회를 분리하라!
  • 오류 코드보다 예외를 사용하라!
    • Try/Catch 블록 뽑아내기
    • 오류 처리도 한 가지 작업이다
    • Error.java 의존성 자석
  • 반복하지 마라!
  • 구조적 프로그래밍
  • 함수를 어떻게 짜죠?

3-1 작게 만들어라!


함수를 만드는 첫 번째 규칙은 ‘작게!’다. 함수를 만드는 두 번째 규칙은 ‘더 작게!’다.

조건문에 들어가는 블록은 한 줄이어야 한다.

3-2 한 가지만 해라!


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

저장된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행해야 한다.

의미 있는 다른 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하고 있는 것이다.

3-3 함수 당 추상화 수준은 하나로!


추상화 수준을 섞으면 표현이 근본적인 개념인지 세부사항인지

구분하기 어려워 읽는 사람으로 하여금 헷갈리게 한다.

추상화 단계를 나눠서 메인 함수 - 서브 함수로 들어갈 때 추상화 수준이 낮아진다.

추상화하라.

 함수를 쪼개서 작게 만들어라.

높은 추상화란 간략한 함수

낮은 추상화란 높은 추상화에 비해 좀 더 자세한 세세하게 표현한 것을 이야기한다.

추상화 수준을 맞춘다 라는 것은 무엇일까?

추상화를 낮추어 풀어서 사용하는 것과 추상화를 높여 함수화 하는것으로 말할 수 있다.

3-3-1 내려가기 규칙


위에서 아래로 이야기처럼 읽혀야 좋은 함수다.

함수 추상화 수준이 한 번에 한 단계씩 낮아진다.

자바스크립트의 호이스팅이 내려가기 규칙을 적용한 것.

3-4 Switch 문


기다란 switch문의 반복은 추상 팩토리 & 다형성 객체 생성 코드로 개선할 수 있다.

3-5 서술적인 이름을 사용하라


코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행한다면 깨끗한 코드라 불러도 되겠다.

함수가 작고 단순해야 하고, 하는 일을 이름에 잘 표현해야 한다.

3-6 함수 인수


이상적인 인수 개수는 0개( 무항 )이다. 다음은 1개( 단항 )이고, 다음은 2개( 이항 )다.

인수는 개념을 이해하기 어렵게 만든다.

별로 중요하지 않은 세부사항임에도 불구하고, 발견할 때마다 의미를 해석해야 하기 때문이다.

인수가 생기면 모든 경우의 수를 검증하는 테스트 케이스를 작성하기 복잡해진다.

3-6-1 많이 쓰는 단항 형식


이름과 문맥을 주의해 단항 형식을 사용한다.

void transform(StringBuffer pageText)

위와 같은 변환 함수에서 출력 인수를 사용하면 혼란을 일으킨다.

입력 인수를 변환하는 함수라면 반환 결과는 반환값으로 돌려준다.

StringBuffer transform(StringBuffer pageText)

입력 인수를 그대로 돌려주는 함수라 할지라도 변환 함수 형식을 따르는 편이 좋다.

3-6-2 플래그 함수


플래그 함수는 추하다.

함수로 진리 값을 넘기는 관례는 정말 끔찍하다.

함수로 진리 값을 넘긴다는 것은 함수가 한꺼번에 여러 가지를 처리한다고 대놓고 공표하는 셈이다

플래그는 참이면 참에 대한 로직, 거짓이라면 거짓에 대한 로직 즉 하나의 함수가 이것 저것한다.

플래그 함수를 꼭 써야한다면 함수명을 AandB와 같은 형식으로 작명해야한다.

3-6-3 이항 함수


인수가 2개인 함수는 단항 함수보다 이해하기 어렵다.

이항 함수가 무조건 나쁘다는 말은 아니다.

하지만 가능하면 단항 함수로 바꾸도록 애써야 한다.

3-6-4 삼항 함수


인수가 3개인 함수는 이항 함수보다 문제가 두 배 이상 늘어난다.

따라서 삼항 함수를 만들 때는 신중히 고려해야 한다.

3-6-5 인수 객체


인수가 2개, 3개 필요하다면 일부를 클래스 변수로 선언하는 방법을 가져본다.

Circle makeCircle(double x, double y, double radius)
Circle makeCircle(Point center, double radius)

이는 객체를 이용한 눈속임이 아니다.

개념을 표현하는 방법이다.

명령 인수 객체의 경우에는 순서 상관없다.

3-6-6 인수 목록


때로는 인수 개수가 가변적인 함수도 필요하다.

하지만 가변 인수를 취하는 함수는 단항, 이항, 삼항 함수로 취급될 수 있는 사실을 명시하자.

3-6-7 동사와 키워드


단항 함수는 함수와 인수가 동사, 명사 쌍을 이루어야 한다.

write(name)

함수 이름에 인수에 관한 키워드를 추가해라.

write(name)
writeField(name)

assertEquals(expected, actual)
assertExpectedEqualsActual(expected, actual)

3-7 부수 효과를 일으키지 마라


부수 효과는 사이드 이펙트를 말한다.

프로그래머의 원수

예상치 못한 부수 효과는 시간적인 결합, 순서 종속성을 초래하게 된다.

함수는 한 가지 기능만 하도록 작성하라.

출력 인수란

반환값이 없지만 void, 인수가 변경되는 경우를 말한다. ⇒ 사이드 이팩트

값을 변경하는 코드가없는데 코드 내용이 변경되는 경우를 무조건 피해라.

피치못해 사이드 이펙트를 발생하는 함수는 무조건 주석을 작성해서 어떻게 변하는지를 설명해야한다.

애노테이션을 작성할 정도로 엄격하게 작성해야한다.

3-8 명령과 조회를 분리하라


함수는 무언가를 수행하거나, 무언가에 답하거나 두 가지 중 하나만 기능해야 한다.

나쁜 예

if(setName("userName", "juwon"))

좋은 예

if(nameExists("userName")){
	setName("userName", "juwon")
}

SRP를 지키면 지킬 수 있는 규칙이다.

C++에서는 변환 여부를 boolean값으로 반환.

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


오류 코드를 반환하는 방식은 여러 단계로 중첩되는 코드를 발생시킨다.

오류 코드를 반환하는 방식은 오류 코드를 곧바로 처리해야 한다는 문제가 발생한다.

오류 코드를 정의하는 의존성 자석( magnet )은 재컴파일, 재배치를 요구하기 때문에 번거로워진다.

3-9-1 Try/Catch 블록


Try/Catch 블록을 별도의 함수로 뽑아내고, try문 안에서 실제 작업할 메소드를 호출한다.

실제 작업을 하는 코드에서는 throws Exception하여 모든 예외 처리를 한 곳에서 처리한다.

3-10 반복하지 마라


어쩌면 중복은 소프트웨어에서 모든 악의 근원이다

DRY 원칙 ( Don’t Repeat Yourself )을 준수하자.
  • 강요된 중복
    • 개발자들은 다른 선택이 없다고 느낀다. 환경이 중복을 요구하는 것처럼 보인다.

  • 부주의한 중복
    • 개발자들은 자신들이 정보를 중복하고 있다는 것을 깨닫지 못한다.

  • 참을성 없는 중복
    • 중복이 쉬워 보이기 때문에 개발자들이 게을러져서 중복을 하게된다.

  • 개발자간의 중복
    • 한 팀에 있는 ( 혹은 다른 팀에 있는 ) 여러 사람들이 동일한 정보를 중복한다.

코드의 길이가 늘어난다.

알고리즘이 변하면 중복된 코드를 모두 수정해야 한다.

오류가 발생할 확률도 몇 배로 높아진다.

3-11 구조적 프로그래밍


모든 함수와 함수 내 모든 블록에 입구와 출구가 하나만 존재해야 한다.

함수가 아주 클 때 구조적 프로그래밍의 목표와 규율이 효과적이다.

함수의 크기가 불가피한 경우 크게짜고 되도록 한 화면을 넘어가지 않게 한다.

3-12 함수를 어떻게 짜죠?


처음부터 이번 장에서 소개한 방법으로 코드를 짜는 사람은 없다.

가능한 사람도 없다.

처음에는 이름은 즉흥적이고 코드는 중복된다.

하지만 이런 코드를 빠짐없이 테스트하는 단위 테스트 케이스를 만든다.

그 다음 코드를 수정하고 함수를 만들고 이름을 바꾸고 중복을 제거한다.

결과적으로 메소드를 줄이고 순서를 바꾼다.

때로는 전체 클래스를 쪼개기도 한다.

결론


함수는 동사이며 클래스는 명사다.

프로그래밍의 기술은 언제나 언어 설계의 기술이다.

프로그래밍 언어라는 수단을 사용해 풍부하고 표현력이 강한 언어로 만들어 간다.

시스템에서 발생하는 동작을 함수로 설명하는 것이며 재귀라는 기교로 해당 도메인에 특화된 자신만의 이야기를 풀어나간다.

이 3장에서는 함수를 잘 만드는 기교를 소개했다.

위에서 설명한 규칙을 따른다면 길이가 짧고 이름이 좋고 체계가 잡힌 함수가 나오리라.

하지만 프로그래머의 진짜 목적은 시스템이라는 이야기를 풀어가는데 있는 사실을 명심해야한다.

앞선 장에서 설명한 규칙과 이번 장에서 설명한 규칙들이 충돌나는 부분이 존재한다.

이 부분은 코드를 직접 작성하며 경험해 보면 적용법을 느낄 수 있게 된다.

4장 주석


Copyright © Juwon. Built with Gatsby