본문 바로가기

책과 강연/클린 코드

클린 코드 3장 : 함수

클린 코드 3장 함수에 대한 인용과 부가 설명 요약 그리고 내가 한 잘못들에 대해서 서술해보았다.

-는 저자의 생각을 요약한 것.

*는 내 경험에 의한 부가설명 및 반성이다.

 

 

본문

 

작게 만들어라

- 저자의 경험 상, 함수는 작을수록 좋다. 어느정도 작냐면 20줄보다도 작은 게 좋다한다.

 

들여쓰기는 1단,2단까지만 : 더 들어가면 가독성이 나빠진다.

 

* if문 두 개 겹쳐있으면, 진짜 읽고싶지 않다. 매우 동의한다.

 

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

- 함수 내에 또 다른 함수를 뽑아서 이름을 붙일 수 있다면, 한 가지만 하는 것이 아니다

- 함수 내 추상화 수준이 동일해야한다 (아래 부가 설명)

 

함수 내 추상화 수준이 동일해야한다.

- 추상화 수준이 다른 함수가 섞여있으면 문맥이 헷갈린다.

- 이야기 읽듯이 내려가면서 읽을 수 있게 만드는 것이 가장 좋다.

* 가끔 큰 개념과 작은 개념이 섞이면 코드 읽으면서 흐름이 꼬일 때가 있긴하다.

 

서술적인 이름을 사용해라

- 길고 확실한 이름을 사용해라 (불명확한 이름, 긴 주석보다 이게 더 낫다.)

- 일관성 있는 이름을 사용해라 : 모듈 내 같은 문구, 명사, 동사를 사용해라

 

* 솔직히 아직 긴 이름이 꼴보기 싫어서 고민중이다. 다만, 예전에 내 코드 유지보수를 할 때, 함수명이 getInfo()였던 적이 있는데 꽤 불편했던 게 생각나서 반성된다. 

 

함수 인수는 최대한 적게 써라 

- 0개가 이상적이다. 3개 이상은 피해라

- 테스트할 때, 인수의 개수에 비례하여 테스트가 복잡해진다. 적을수록 좋다.

- 출력 인수 사용은 지양하자 (아래 상세 내용)

- 플래그 인수 사용은 지양하자 : 쓸데없이 인수를 많아지게 하는 요소다. 또한, 플래그 인수가 있다는 것은 그 함수가 여러가지를 처리하는 함수로 하나가 아닌 여러가지를 하는 함수가 된다. (true/false에 따라서 다른 동작을 하는 함수니까)

- 인수 객체 사용 시, 인수 개수를 주의하자 : 인수를 줄이는 척할 뿐 결국 전체 인수 양은 똑같다. 총 몇 가지 인수를 사용하는 지 주의하자.

- 동사와 키워드를 함께 표현하자.

assertEquals(expected : number, actual: number) : bad
assertExpectedEqualsActual(expected : number, actual: number) : good

 

* 동사와 키워드 함께 표현하는 부분 너무 좋은 거 같다. 예전에 expected와 actual 바꿔 써서 에러난 적이 있는데, 함수명에서 확인 가능하니 실수가 없을 거 같다.

 

출력 인수 사용은 지양하자

- 출력 인수 : 입력 인수를 받아서 내부 값을 수정한 뒤 그 인수를 반환하는 것

- 객체 지향 전에서는 이 부분이 필요했지만, 지금은 필요없다. 이를 위해서 this가 존재하기 때문이다. 필요하다면, 함수가 속한 객체의 상태를 변경해라

 

* 출력 인수라는 것도 사실 여기서 처음봤고, 인터넷 검색결과이다. 문맥상 맞는 표현이여서 가져왔다.

* 아직 써본 적이 없고, 앞으로도 안 쓸 거 같다.

 

부수 효과를 일으키지 마라. (함수에서 한 가지만 해라!!)
public class UserValidator {    
	private Cryptographer cryptographer;     
    
	public boolean checkPassword(String userName, String password) {        
		User user = UserGateway.findByName(userName);        
		if (user != User.NULL) {
            		String codedPhrase = user.getPhraseEncodedByPassword();            
			String phrase = cryptographer.decrypt(codedPhrase, password);            
			if ("Valid Password".equals(phrase)) {
            			Session.initialize();                
				return true;           
			}        
		}        
		return false;    
	}
}

- 부수 효과는 거짓말이다. 다 하나의 함수에서 여러가지를 해서 생기는 일이다.

- 위 코드는, password를 check한다하지만, Session.initialize()를 한다. 여기서, 문제가 생길 것이다. checkPassword는 세션을 초기화해도 괜찮은 상황에서만 사용가능한 함수가 된다. 그렇지 않을 때 사용하면, 부수 효과를 만들어낸다.

- 만약, 이렇게 써야할 경우 checkPasswordAndIntializeSession()으로 작성해야한다. (물론 이 경우 두 가지를 하긴 하지만)

 

* 굉장히 찔린다. 매 번 이렇게 짰는데 굉장히 무섭다. 반성하는 중이다.

 

명령과 조회를 분리해라

- 뭔가를 수행하거나, 뭔가를 답하거나 둘 중 하나만 해야한다. 둘 다 하면 혼란을 야기한다. (객체를 바꾸거나, 조회하거나 둘 중 하나만 해라)

 

* 이 부분도 어쩌다보니 get/set을 나누어서 사용중인데 주의하도록 해야겠다.

 

오류코드보다 예외를 사용해라

- 오류 코드를 사용하면, 오류 코드에 대한 대응을 해야한다. 하지만, 예외를 사용하면 오류 코드를 본래 코드에서 구분할 수 있어서 깔끔해진다.  

 

try/catch 블록 뽑아내기

- try/catch도 마찬가지다. 별도의 함수로 뽑아내는 편이 좋다.

- 오류 처리도 한 가지 작업이다. 오류를 처리하는 함수는 오류만 처리해야한다.

 

* 이거는 좀 고민된다. 너무 함수가 길어지고 많아지지 않나 싶다. 좀 더 경험이 필요할 수도 있다.

 

반복하지 마라

- 중복을 제거하는 것이 중요하다. 중복이 4곳 있다면 4배의 수정이 필요하다. 중복은 모든 악의 근원이다.

 

* 이 또한 찔리는 부분이다. 뭔가 애매하게 달라서 다른 함수를 만들고 그 코드가 변해서 4군데씩 수정하는 건 지금 일상이다... 고쳐야겠다.

 

구조적 프로그래밍

- 데이스크트라는 입구(input)와 출구(return문)이 각각 하나여야한다 주장한다.

 

* 구조적 프로그래밍 => 절차적 프로그래밍(=== 명령형 프로그래밍) => 함수형 프로그래밍 / 객체지향 프로그래밍 식으로 영향을 주었다 한다.

 

결론

함수는 글과 비슷하다. 처음에는 즉흥적으로 짜면서 단위테스트를 같이 만든다. 그 후, 코드를 다듬고 함수를 쪼개고 중복을 제거하고 이름을 바꾼다. 그 과정에서 단위테스트를 모두 통과해야한다. 그리고 위에서 말한 것처럼 깔끔한 함수가 얻어질 것이다.

 

master programmer는 시스템을 구현할 프로그램이 아니라 풀어갈 이야기로 여긴다. 

 

이 방식대로 만든다면 짧고 체계가 잡힌 함수가 나올 것이다. 하지만 진짜 목표는 시스템이라는 이야기를 풀어가는 데 있다는 사실을 잊지마라

 

* 클린 코드는 결국 시스템을 풀어나가는 이야기다. 그걸 항상 명심하자

'책과 강연 > 클린 코드' 카테고리의 다른 글

클린 코드 8장 : 경계  (1) 2023.12.29
클린코드 7장 : 오류 처리  (0) 2023.12.28
클린코드 6장 : 객체와 자료구조  (0) 2023.12.24
클린 코드 5장: 형식 맞추기  (0) 2023.12.24
클린코드 4장 : 주석  (0) 2023.12.24