서술적인 이름을 사용하라

함수가 하는 일을 좀 더 잘 표현하기

코드를 읽으면 짐작했던 기능을 수행한다면 좋은 이름이다.

이름이 길어도 두려워하지 말라, 길고 서술적인 이름이 짧고 어려운 이름보다 좋다.

특히, 길고 서술적인 이름이 길고 서술적인 "주석"보다 좋다.

요즘은 IDE 기능을 이용하면 이름 변경이 쉬우므로 자주 변경하는 것에 두려워할 필요 없다.

 

 

 

함수 인수

함수에서 가장 이상적인 인수 개수는 0 개다.

다음은 단항, 다음은 이항이다.

 

인수는 함수 개념을 이해하기 어렵게 한다.

인수가 있다면 내부구조를 봐서 무슨 일을 하는지 세부사항을 확인해야 한다.

 

또한 테스트 관점에서 함수 인수는 테스트를 더욱 어렵게 한다.

인수가 3개 이상이라면 모든 경우의 수를 테스트하기 힘들어진다.

인수가 없다면 쉬울 것이다.

 

인수가 두 개 이상부턴 인수의 순서도 생각해야 한다.

 

결과적으로 최선은 인수가 없는 것이고, 차선은 인수가 1개인 것이다.

 

 

많이 쓰는 단항 형식

  • 인수에 질문을 던지는 경우
    boolean fileExists("file")
  • 인수를 뭔가로 변환해 결과를 반환하는 경우
    InputStream fileOpen("file")

위와 같은 경우가 아니라면 단항 함수도 가급적 피하는 것이 좋다

인수를 무언가로 변환하는 함수의 경우 이름을 명확히 해야 한다.

좋은 예시

Integer parseInt()  

딱 봐도 반환 결과가 Integer 형일 것을 알 수가 있다.

 

 

 

플래그 인수

플래그 인수는 추하다. 함수로 boolean 값을 넘기는 것은 끔찍하다.

함수는 한 가지만 잘해야 하는데, 플래그 인수가 true/false에 따라 동작을 달리한다는 것은 SRP를 위배한다. 

또한, 외부에서 값을 받아 객체가 조작된다는 것은 의존성이 높다는 것과 같다.

차라리 함수를 두 개로 쪼개는 것이 올바르다.

 

 

이항 함수

이항 함수부터는 인수 순서에도 주의가 필요하다.

가급적 안 쓰는 것이 좋지만, 문맥상 자연스러운 이항 함수도 분명 존재한다.

compare(a, b) ,  Objects.equeals(a, b)...

 

 

삼항 함수

당연히 이항 함수보다 훨씬 이해하기 어렵다.

순서, 주춤, 무시로 야기되는 문제가 이상 늘어난다.

 

인수 객체

인수가 많아 일부를 독자적인 인수 객체로 선언한 경우

인수 객체가 단순히 인수 개수를 줄이겠다는 눈속임으로 생각할 수 있다.

꼭 그렇지만은 않다. 인수 사용 시 객체의 이름을 꼭 붙여야 하므로 결국 개념을 표현하게 된다.

 

 

동사와 키워드

함수 인자 이름과 함수 이름은 명사/동사 쌍을 이루면 좋다.

find(item)  누가 봐도 아이템을 찾는 것이라는 것을 알 수 있다.

더 좋은 방향은 인수 순서까지 표시하는 것이다.

inputPasswordEqualsDbPassword(intputPassword, DbPassword)

 

 

부수 효과를 일으키지 마라

부수효과는 거짓말이다. 함수는 한 가지만 하겠다고 약속하고선 남몰래 다른 짓도 하니까.

클래스 변수나, 참조 변수를 수정하면, 많은 경우 시간적인 결합이나 순서 종속성을 초래한다.

특히, 부수효과를 파악하려면 함수 내부를 들여봐야지만 알 수가 있다.

따라서 어쩔 수 없는 경우는 함수 이름으로 부수효과를 알 수 있게 해야 한다.

 

 

출력 인수

appendFooter(String str)

이 함수를 호출하는 쪽 관점에서 보자.

이 함수를 호출하면 str을 바닥글로 첨부하는 것일까? 아니면, str에 바닥글을 첨부할까?

알 수가 없어 이 함수를 호출한 선언부를 찾아본다.

이는 코드를 보다가 주춤하는 행위와 동급이다. 인지적으로 거슬리므로 피해야 한다.

 

객체지향 언어에서는 출력 인수를 사용할 필요가 거의 없다. 출력 인수를 사용하라고 설계한 변수가 this이기 때문이다.

 

 

명령과 조회를 분리하라

함수는 무언가를 수행하거나 무언가에 답하거나 둘 중 하나만 해야 한다.

객체 상태를 변경하거나, 객체 정보를 반환하거나   

위 두 행위를 하나의 함수로 하는 경우를 보자

public boolean set(String attribute, String value)

이 함수는 이름이 attribute인 속성을 찾아 값을 value로 설정하고 결과를 boolean으로 리턴한다.

set("username", "kks") 

이 경우 username 속성을 찾아 kks로 설정에 성공한 결과를 반환하는 것인지

username 속성에 kks 값이 존재할 때 결과를 반환하는 것인지 모호하다.

 

함수 이름을 명확히 해 분별이 가능하게 할 수도 있지만, 애초에 명령과 조회를 분리해 혼란을 뿌리 뽑는 것이 좋다.

attributeExists("username")  조회

setAttribute("username", "kks")  명령

 

 

 

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

명령 함수에서 오류 코드를 반환하는 방식은 명령/조회 분리 규칙을 미묘하게 위반한다.

오류 코드 대신 예외를 사용하면 오류 처리 코드가 원래 코드에서 분리되므로 코드가 깔끔해진다.

 

 

 

Try/Catch 블록 뽑아내기

원래 try/catch 블록은 추하다. 코드 구조에 혼란을 일으키며, 정상 동작과 오류 처리 동작을 뒤섞는다.

그래서 try/catch 블록을 별도 함수로 뽑아내는 편이 좋다.

	void method1() {
		try {//정상 동작
			something1();
			something2();
			something3();
		}catch (Exception e){
			//오류 처리 동작
		}
		
	}
    
    /**********************************/
    //try/catch 블록 뽑아내기
	void tryCatch(){
		try {
		method1();
		}catch (Exception e) {
			//오류 처리만 한다.
		}
	}
	
	void method1() throws Exception{
		//정상 동작만 한다.
		something1();
		something2();
		something3();
		
	}

 

오류 처리도 가지 작업이다.

, 함수는 가지일만 한다는 원칙에 부합해야 한다.

따라서 오류처리를 하는 함수는 오류처리만 해야한다.

 

 

 

오류 코드 대신 예외를 사용하자

예를 들어, Error enum 클래스가 있다고 하자, 이 열거형 클래스가 변경되는 순간

열거형 클래스를 사용하는 곳 모두 컴파일을 다시 해야 한다.

그래서 Error enum 클래스를 변경하기 어려워진다.

반면에 오류 코드 대신 예외를 사용하면 재컴파일/재배치 없이도 새 예외 클래스를 추가할 수 있다.

 

반복하지 마라

중복은 문제이다. 코드 양이불필요하게 늘어나며 수정하고 싶다면 중복된 부분을 전부수정해야 한다. 또한 조금씩 상이한 부분이 생기면 유지보수가 더 힘들어진다.

중복은 가장 악이다

많은 원칙과 기법이 중복을 없애거나 제어할 목적으로 나왔다.

객체지향에서는 코드 중복을 부모 클래스로 몰아 없앤다.

구조적 프로그래밍, AOP, COP(Component Oriented Programming) 중복을 제거하기 위한 전략이다.

소프트웨어 개발에서 지금까지 일어난 혁신은 소크 코드에서 중복을 제거하려는 지속적인 노력으로 보인다.

 

함수를 어떻게 짜죠?

글짓기와 비슷하다. 먼저 생각을 기록한 읽기 좋게 다듬는다.

함수도 처음에는 길고 복잡하다. 들여 쓰기 단계도단계도 많고 중복된 루프도 많다. 인수 목록도 아주 길다. 이름은 즉흥적이고 코드는 중복된다. 이렇게 서투른 코드를 빠짐없이 테스트하는 단위 테스트 케이스를 만든다.

그런 다음 코드를 다듬고, 함수를 만들고, 이름을 바꾸고, 중복을 제거하고, 메서드를 줄이고 순서를 바꾼다. 때로는 전체 클래스를 쪼개기도 한다. 모든 과정에도 항상 단위 테스트를 통과한다.

누구도 처음부터 짜는 코드란 없다.

 

 

'IT책, 강의 > 클린코드(Clean Code)' 카테고리의 다른 글

4장 주석 - 나쁜 주석  (1) 2022.10.01
4장 주석 - 좋은 주석  (0) 2022.09.28
3장 함수 - 1  (0) 2022.07.05
2장 의미 있는 이름  (0) 2022.07.01
1장 깨끗한 코드  (0) 2022.06.27

+ Recent posts