1. 함수는 작게 만들어라
1.1 작은 함수의 정의
오직 하나의 일만 하는 함수
1.2 어떻게 작게 만들까?
A. 객체지향 생활체조 원칙 1번과 2번을 적용한다.
1) 한 메소드에 오직 한 개의 들여쓰기만 한다
2) else 키워드를 쓰지 않는다.
B. 함수당 추상화 수준은 하나로
- 비슷한 추상화 수준의 함수끼리 한 함수내에서 사용한다.
C. 내려가기 규칙: 위에서 아래로 코드 읽기
추상화 레벨이 다양할 경우,
(1) 추상화단계가 높은 함수가 먼저 정의되고
(2) 페이지의 아래로 내려갈 수록 추상화 단계가 낮은 함수가 나온다.
/* 추상화 3단계*/
String renderPage() {
renderMenu(); // 추상화 3단계 내부에서는 2단계 함수만 사용한다. 1단계는 사용하지 않는다.
renderEventBanner();
renderPosting();
renderFooter();
}
/*추상화 2단계*/
String renderMenu(){
renderLoginSectiong();
}
String renderEventBanner(){
/*생략*/
}
String renderPosting(){
/*생략*/
}
String renderFooter(){
/*생략*/
}
/*추상화 1단계*/
String renderLoginSectiong(){
/*생략*/
}
D. 스위치 문은 추상팩토리(Abstract Factory) 안에 숨기자(47~48p. 레퍼런스 2번)
2. 함수 이름: 서술적인 이름을 사용하자.
2.1 긴이름이 짧고 이해 어려운 이름보다 낫다.
예) getCpuStatus -> getCpuStatusForLast5mins // 최근 5분간 cpu 상태 출력하는 함수
2.2 단항함수일 경우 인수가 동사/명사 쌍을 이룬다.
에) write: 동사, name: 명사
write(name)
2.3 함수 이름에 인수를 넣는다.
인수 순서를 기억할 필요 없어짐!
assertEquals(actual,expected) // 인수 순서 바뀔 가능성 높다
assertExpectedEqualsActual(expected, actual) // 왼쪽에서 오른쪽으로 읽은대로 인수 넣으면 된다
3. 함수 인수
3.1 권장되는 인수갯수
가장 좋은 것은 0개의 인자. 2개까지는 OK. 3개는 가능한 피하자. 4개는 사용하지 말자.
인자수가 적어야하는 이유: 인자가 많을 수록 테스트가 어려워진다.
3.2 인수형식
A. 단항형식
- 인수에 질문을 던지는 경우
boolean fileExists("20210101_upload")
- 인수를 변환하여 값을 반환하는 경우
InputStream fileOpen("myFile")
B. 플래그 인수
- 가능한 피하자. 인수값에 따라 함수의 동작이 다르다는 이야기다.
C. 이항함수
좌표 값 (new Point(0,1))과 같이 자연스럽게 읽히는 경우 제외하고 쓰지 말자.
D. 인수객체
여러개의 인수가 필요하다면, 관련있는 인수끼리 묶어 클래스화 하는 것이 좋다.
/*bad*/
Calendar drawTodaysCalendar(String year, String month, String day);
/*good*/
// Date 클래스가 java에서 이미 존재하지만 여기서는 예제를 위해 사용했다.
Calendar drawTodaysCalendar(Date date);
4. 부수효과를 일으키지 말자.
예를 들어, checkPassword 호출시, 우리는 password 옳음/틀림만 판단하겠구나 생각한다.
그런덴 막상 코드를 열어보니 password 매칭 결과에 따라 session이 초기화 되는 상황이 발생한다면,
그리고 이로 인해 버그가 발생한다면, 추후 디버깅시 버그의 원인을 찾기 매우 어려워진다.
5. 출력 인수 사용하지 말자.
행위(함수)에 출력 인수가 필요하다면, 출력 인수의 클래스에 함수를 넣는것이 맞다.
객체에게 행위를 시키자!
/*bad*/
Report report;
appendFooter(report); // report에 footer를 넣는건지, footer에 report를 넣는건지 불분명
/*good*/
Report report;
report.appendFooter(); // 레포트에 footer를 넣는것으로 분명해짐.
6. 함수의 예외처리
1. 에러 코드 보다는 예외 처리를 활용하자.
Enum을 활용하여 예외코드를 작성할 경우, 예외코드가 추가될 때마다 enum 클래스를 건드려야하는 부담 + OCP에 위반이 생긴다.
Exception을 상속하는 예외 클래스를 만들면 기존 코드를 건드릴 필요 없이 예외 처리가 가능하다.
2. 예외처리는 한 곳에서!
정상 동작과 예외 동작을 분리하자
7. 어떻게 함수를 리팩토링할까
단위 테스트 기반 리팩토링. 초기 테스트 코드 짤 때는 시간이 걸리는 것처럼 보이지만 추후 유지보수시 안정감을 부여한다.
(이번 프로젝트 때 절실히 느꼈다... ㅠㅠ)
느낀점
1. 디자인 패턴 공부가 함께 필요하다.
Interface의 존재를 알지만, 잘 활용하지 못했는데, 잘 써봐야겠다.
2. 단위 테스트 꼭 하자!
큰 프로젝트일수록 테스트는 안정감을 부여한다
레퍼런스
[1]객제지향 생활체조 원칙: https://jamie95.tistory.com/99
[2] 추상 팩토리 패턴: https://johngrib.github.io/wiki/abstract-factory-pattern/
'개발 > 클린코드' 카테고리의 다른 글
[클린코드 10장] 클래스 (0) | 2022.01.13 |
---|---|
5. 형식 (0) | 2021.08.21 |
4장. 주석 (0) | 2021.08.21 |
[요약] 2.의미 있는 이름 (0) | 2021.08.14 |
[요약] 1장. 깨끗한 코드 (0) | 2021.08.14 |