본문 바로가기
Book/Clean Code

제 3장 함수

by 라바킴 2021. 5. 16.

#작게_만들어라

- 80년대에는 한 함수가 한 화면을 넘어가면 안된다고 했다

  - 당시 VT100 화면은 가로 80 세로 24줄이었는데 편집기가 4줄을 관리용으로 사용했기 때문

- 얼마나 짧아야하는가?

  - 20줄도 길다

  - if/else/while 블록은 한줄 -> 대게 여기서 함수 호출

  - 즉 중첩이 생길만큼 함수가 커선 안된다는 의미 (들여쓰기는 1,2에서 그치도록)

 


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


 

#한가지만_해라

- 한가지의 기준은?

  - 추상화 수준 : 지정된 함수 이름 아래 추상화 수준이 하나인 단계만 수행하면 작업 갯수는 하나인 것

  - 의미 있는 이름으로 다른 함수를 추출할 수 있다면 여러 작업

  - 여러 섹션으로 나눈다는건 여러 작업을 한다는 증거

 

#코드는_위에서_아래로_이야기처럼

- 추상화 수준이 한 단계씩 낮아지는 모양

 

#Switch문

- 본질적로 if/else를 포함한 swiitch문은 N가지 작업을 처리하므로 작게 만들기 어려움

- 각 분기문을 저차원 클래스에 숨기고 반복하지 않는 방법 존재

  - 다형성을 이용

  - 상속 관계로 숨겨 다른 코드에 노출하지 않는다

 

#서술적인_이름_사용

- 코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행한다면 깨끗한 코드!

   - 작은 함수에 좋은 이름이 붙는다면 절반은 성공하겠지

  - 길어지는것에 겁먹지 말것. 주석으로 쓰느니 이름으로 써라.

- 명명법

  - 여러 단어가 쉽게 읽히게

  - 여러 단어를 사용해 함수 기능을 잘 표현하게

  - 모듈 내 함수 이름의 문구, 명사, 동사 통일

    - ex) includeSetupAndTeardownPages, includeSetupPages ... (접미사처럼)

 

#함수_인수는_적을수록_좋다

- 무항, 다음이 단항, 다음은 이항 순으로 이상적 -> 3개 이상은 피하는게 좋다 (복-잡)

 

#이상적인_단항_함수

  - 인수에 질문을 던지는 경우 

    - ex) boolean fileExists("MyFile") : 있니 없니~

  - 인수를 변환해 결과를 반환하는 경우

    - ex) InputStream fileOpen("MyFile") : string을 InputStream으로

    - 변환 함수라면 결과를 반환 값으로 돌려줘야 (그대로 돌려주더라도 반환 형태를 명시할 것)

  - 이벤트 함수

    - 입력 인수로 시스템 상태 변경 (입력만 있고 출력이 없는 형태)

    - 명확히 드러내서 조심히 사용

 

#비추천_함수

- 플래그 인수 (terrible)

  - bool을 인수로 넘기는건 정말 끔찍. 함수가 여러 가지를 처리한다고 대놓고 공표하는 셈

- 이항 함수 (soso)

  - 단항보다 이해하기 어렵다

  - 꼭 필요한 경우도 있지만 위험이 수반된다는 걸 기억하고 단항으로 바꾸도록 노력할 것

- 삼항 함수 (bad)

  - 이항보다 이해하기 어렵다

 

#인수_객체

- 이항, 삼항 이상의 인수가 필요하다면 일부를 독자적 클래스 변수로 선언

  - 두개 묶어서 포인터로 넘기는 식

 

#인수_목록

- 인수 개수가 가변적인 경우 List 활용

  - 논리적으론 단항/이항/삼항 규칙에 벗어나지 않음. 이상 넘지 않도록 유의

 

#동사와_키워드

- 단항 함수 네이밍 : 동사/명사의 쌍

- 함수 이름에 키워드 추가 : 함수 이름에 인수 이름 포함

 

#남몰래_부수_효과_금지

- 한가지 동작 한대놓고 다른 짓하면 시간적인 결합이나 순서 종속성을 초래

  - 시간적인 결합(Temporal Coupling) : 특정 상황에서만 호출 가능하게 됨

  - 순서 종속성(Order Depandency) : 정해진 순서에 의해서만 호출 가능하게 됨

 

#시키거나_하거나_둘중_하나만

- 명령과 조회 분리 : 객체 상태를 변경or 객체 정보를 반환 (쉽게 말해 get/set 따로 두라는 말)

 

#오류코드_말고_예외처리

- 명령 함수에서 오류 코드 반환하면 분리 규칙을 미묘하게 위반하게 됨

  - if (deletePage(page) == E_OK) 같이 명령을 표현식으로 많이 사용하게 되기 때문

- 오류 코드로 인해 분기처리 하지 말고 예외로써 try/catch를 활용해준다

 

#Try/Catch_별도_함수로

- 원래 try/catch가 코드 구조에 혼란을 일으키며 정상 동작과 오류 처리를 뒤섞는 나쁜 구조이므로 try/catch 블록은 별도 함수로 뽑아낸다

  - 즉 정상 동작과 오류 처리 동작을 따로 함수로 뽑는다

- 물론 오류처리도 한번에 한 가지 작업만 해야함

  - try로 시작하면 catch, finally로 끝나야 하지 다른거 섞이면 ㄴㄴ

 

#오류_코드_정의

- 오류 코드를 반환하게 된다면 어디선가 오류 코드를 enum 처럼 정의하고 있을 것

  - 이런 클래스를 의존성 자석(magnet)이라 함

  - 이거 고치면 얘 사용하는 클래스 모두 재컴파일

  - 따라서 새 오류 코드를 추가하는게 아닌 기존 오류 코드를 재사용하는 방식 선호

- 물론 오류 코드 대신 예외 사용하면 편함

 

#반복_금지

- 중복은 소프트웨어에서 모든 악의 근원

  - 많은 원칙과 기법이 중복을 없애거나 제어할 목적으로 나오게된 것

    - ex) 자료에서 중복을 제거할 목적으로 관계형 데이터베이스에 정규 형식을 만듦

    - ex) OOP에서는 코드를 부모 클래스로 몰아 중복을 없앰

    - ex) 그 외 AOP(Aspect Oritented Programming), COP(Component Oriented Programming) 등

 

#구조적_프로그래밍

- 모든 함수와 함수 내 모든 블록에 입구와 출구가 하나만 존재하는 것

  - 즉 함수는 return 문이 하나여야함

  - loop내 break/continue 사용 지양

  - goto는 절대절대 금지

- 물론 함수를 애초에 작게 설계했으면 문제되지 않음

  - 오히려 break,continue,return 여러번 해도 의도 표현이 명확해짐

  - 함수가 클 땐 저 원칙을 지키면 꽤나 이득일지도?

  - 그치만 작은 함수에서도 goto는 피해라

 

#개발은_글짓기다

- 초안에서 고치고 정리하다보면 좋아지는 것

  - 코드를 빠짐없이 테스트할 수 있는 단위 테스트 케이스도 잘 만들어야함

 

#끝으로

- 모든 시스템은 DSL(Domain Specific Language, 도메인 특화 언어)로 만들어짐

  - 특정 응용 분야 시스템을 기술할 목적

    - 함수는 그 언어에서 동사, 클래스는 명사

  - 프로그래밍은 언어 설계의 기술

 - 즉 시스템은 (구현할) 프로그램이 아닌 (풀어갈) 이야기

  - 언어라는 수단을 사용해 좀 더 풍부하고 좀 더 표현력이 강한 언어를 만들어 이야기를 풀어가는 것

    - 앞선 규칙을 잘 따르면 짧고, 좋은 이름의 체계가 잡힌 함수가 나오겠지만

    - 단지 함수가 분명하고 정확한 언어로 깔끔하게 맞아 떨어져야 이야기를 풀어가기 쉬워지는 것

- 진짜 목표는 시스템이라는 이야기를 풀어가는 데 있다

 

'Book > Clean Code' 카테고리의 다른 글

제 2장 의미 있는 이름  (0) 2021.04.11
제 1장 깨끗한 코드  (0) 2021.04.03

댓글