도입
프로그래밍 초창기 시스템은 루틴, 하위 루틴으로 나누어짐.
포트란, PL/1 시절에는 시스템을 프로그램, 하위 프로그램, 함수로 나눔.
지금은 함수만 남아있으며 어떤 프로그램이든 가장 기본적인 단위가 함수이다.
이 장에서는 함수를 잘 만드는법을 소개함.
방법 1) 작게 만들어라!
- 함수를 만드는 첫째 규칙은 “작게!”이다. 그리고 두번쨰 규칙 또한 “작게!”이다.
- 함수는 작은 것이 좋다고 근거를 댈 수는 없지만, 작가의 오랜경험을 바탕으로 나온 조언이다.
그렇다면 얼마나 짧아야 좋은걸까??
작가의 기준 = 블록과 들여쓰기
- if 문/else 문/while 문 등에 들어가는 블록은 한 줄이어야 한다.
- 대개 거기서 함수를 호출하기에 바깥을 감싸는 함수(enclosing function)가 작아지며, 블록 안에서 호출하는 함수 이름을 적절히 지으면(이전 장 참고) 코드를 이해하기 쉽다.
- 결론적으로, 중첩 구조가 생길만큼 함수가 커지면 안됨 = 들여쓰기는 1단, 2단을 넘어서는 안됨
방법 2) 한 가지만 해라!
- 함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야한다. 그 한 가지만을 해야 한다.
그렇다면 “한 가지”란??
- 지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행하는 것
- 추상화 수준에서 여러 단계로 나눠 수행하는 것 = 함수를 만드는 궁극적 이유
- 결론적으로, 하나의 함수가 의미 있는 이름으로 다른 함수를 추출할 수 있다면 그 함수는 여러 작업을 하는 것으로 판단.
방법 3) 함수 당 추상화 수준은 하나로!
- 함수가 확실히 “한 가지” 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일 해야함.
- 위에서 아래로 코드 읽기: 내려가기 규칙즉, 위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아진다.
- 코드는 위에서 아래로 이야기처럼 읽혀야 좋다.
방법 4) Switch 문
- switch 문은 작게 만들기 어렵다.
- “한 가지” 작업만 하는 switch 문도 만들기 어렵다.(본질적으로 N가지에 대해 처리하기 때문)
단순 Switch 문의 문제
- 함수가 길다.
- “한 가지” 작업만 수행하지 않는다.
- SRP(Single Responsibility Principle)을 위반한다.
- OCP(Open Closed Principle)을 위반한다.
- 해결법
- 다형성의 성질을 이용, 추상 팩토리(Abstract Factory) 사용 하여 switch문 외부 노출 방지
방법 5) 서술적인 이름을 사용하라!
- 함수가 하는 일을 좀 더 잘 표현하는 = 훨씬 좋은 이름
- isTestable, includesetupAndTeardownPages 등과 같은 서술적 이름 사용
- 이는 함수가 작고 단순할수록 서술적인 이름을 고르기도 쉬워진다.
- 서술적인 이름을 사용하면 개발자 머릿속에서도 설계가 뚜렷, 코드 구현 용이
TIP)
- 이름이 길어도 괜찮다. 길고 서술적인 이름 >>>> 짧고 어려운 이름, 서술적인 주석
- 이름을 붙일 때는 일관성이 있어야함
방법 6) 함수 인수
- 이상적인 인수 개수 = 0개(무항) > 1개(단항 > 2개(이항) >> 권고X = 3개(삼항) >>>>>>> 기피대상 4개 이상(다항)
- 인수는 개념을 이해하기 어렵게 하며 테스트 관점에서 봤을땐 더더욱 어렵다.
- 출력 인수는 입력 인수보다도 코드를 이해하기 어렵게 만든다.
TIP)
- 많이 쓰는 단항 형식
- 인수에 질문을 던지는 것(ex. boolean fileExists(”File”))
- 인수로 뭔가를 변환해 결과를 반환하는 경우(ex. intToString())
- 이벤트(입력 인수O, 출력 인수X)
- 단항인자 쓰는 이유
- 플래그 인수⇒ 사용하지 말자
- T/F를 판별하는 부울 함수는 애초에 그 안에서 “한 가지”일을 하지 않는다.
- 이항 함수
단연 위에가 이해하기 쉽다.1. writeField(name) 2. writeField(outputStream, name)
- 직교 좌표계 점 표시(x,y)와 같이 인자들의 순서가 정해져 있는 경우
- assertEquals(expected, actual)은 그렇지 못하다.
- 이항 함수 적절하게 사용하는 방법
- 인수가 2개인 함수는 1개인 함수보다 이해하기 어렵다. 아래 예시를 이해해봐라
- 삼항 함수따라서, 신.중.하.게. 사용해야 한다.
- 인수가 3개인 함수는 인수가 2개인 함수보다 이해하기 훨씬 어렵다.
- 인수 객체
1번 → 2번으로 수정함에 따라 삼항 → 이항으로 변경되었다.1. Circle makeCircle(double x, double y, double radius) 2. Circle makeCircle(Point center, double radius)
- 하나로 묶어 개념을 표현, 넘길 것
- 인수가 2-3개 필요하다면 일부를 독자적인 클래스 변수로 선언할 가능성을 생각해보자
- 인수 개수가 가변적인 함수도 필요하다.
- 일종의 List를 인수로 받는 것과 동일하다.
- 다만, 정해진 개수를 넘어서는 경우에 주의해야 할 것이다.
- 동사와 키워드
- 함수의 의도나 인수의 순서와 의도를 제대로 파악하기 위해 동사/명사를 잘 섞어 만든다.
- ex. write(name) [Good] → writeField(name) [Excellent]
- 함수의 이름에 키워드를 추가하는 방식
결론
- 함수를 만들 때 최대한 세분화 하여 만든다.
- 들여쓰기를 많이하는 것은 이해하기 어려울 뿐더러 구현에도 도움이 되지 않는다.
- 인수의 개수를 늘리는 것은 신중해라
- 가장 기본이 되는 이름짓기에 신경써라
클린코드 p.4~p.54
원본 노션 링크
[Clean Code] - 3장 함수(1)
도입
leapday.notion.site
다음 자료
[Clean Code] - 3장 함수(2)
이전자료 https://leapday.tistory.com/7 방법 7) 부수 효과를 일으키지 마라! 때때로 함수를 통해 클래스 변수를 수정한다. 떄로는 함수로 넘어온 인수나 시스템 전역 변수를 수정한다. 이러한 경우들은
leapday.tistory.com
'[Book] > Clean Code' 카테고리의 다른 글
[Clean Code] - 4장 주석(1) 좋은 주석이란? (1) | 2023.02.13 |
---|---|
[Clean Code] - 3장 함수(2) (0) | 2023.02.08 |
[Clean Code] - 2장 의미 있는 이름 (0) | 2023.01.26 |
[Clean Code] - 1장 깨끗한 코드 (2) | 2023.01.17 |