함수
작게만들어라
함수를 만드는 첫째 규칙은 작게 둘째도 작게
if, else, while문 등에 들어가는 블록은 한줄이여야 한다. 블록 안에서 호출하는 함수 이름을 적절히 짓는다면, 코드를 이해하기도 쉬워진다. 중첩 구조가 생길만큼 함수가 커서는 안된다. 함수에서 들여쓰기 수준은 1단이나 2단을 넘어서는 안된다.
한가지만 해라
함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다.
지정된 함수 이름 아래에서 추상화 수준이 하나인 단계만 수행한다면 그 함수는 한 가지 작업만 한다.
우리가 함수를 만드는 이유는 큰 개념을 다음 추상화 수준에서 여러 단계로 나눠 수행하기 위해서 이다.
함수 당 추상화 수준은 하나로
함수가 확실히 한 가지 작업만 하려면 함수 내 모든 문장의 추상화 수준이 동일해야 한다.
한 함수 내에 추상화 수준을 섞으면 코드를 읽는 사람이 헷갈린다.
-
내려가기 규칙 :
코드는 위에서 아래로 이야기처럼 읽혀야 좋다.
위에서 아래로 프로그램을 읽으면 함수 추상화 수준이 한 번에 한 단계씩 낮아진다.
서술적인 이름을 사용하라
좋은 이름이 주는 가치는 아무리 강조해도 지나치치 않다.
코드를 읽으면서 짐작했던 기능을 각 루틴이 그대로 수행한다면 깨끗한 코드라 불러도 되겠다(1장 워드커닝햄)
이름은 길어도 괜찮다. 겁먹을필요 없다. 길고 서술적인 이름이 짧고 어려운 이름보다 좋다.
서술적인 이름을 사용하면 개발자 머릿속에서도 설계가 뚜렷해지므로 코드를 개선하기 쉬워진다.
이름을 붙일 때는 일관성이 있어야 한다. 모듈 내에서 함수 이름은 같은 문구, 명사, 동사를 사용한다.
함수인수
함수에서 이상적인 인수 개수는 0개(무항)다. 다음은 1개(단항)고, 다음은 2개(이항)다. 3개(삼항)는 가능한 피하는 편이 좋고, 4개 이상은 특별한 이유가 필요하다. 특별한 이유가 있어도 사용하면 안된다.
-
많이쓰는 단항형식
인수에 질문을 던지는경우, 인수를 변환해 결과를 반환하는경우
-
플래그인수
플래그인수 함수는 추하다. 함수가 한꺼번에 여러 가지를 처리한다고 대놓고 말하는 셈이니.
-
이항함수
예)assertEquals(expected, actual) 두 인수에는 자연적인 순서는 없다.
이항 함수가 무조건 나쁘다는 소리는 아니며, 위험이 따른다는 사실을 이해하고 가능하면 단항함수로 바꾸려고 애써야 한다.
-
삼항함수
이항 함수보다 훨씬 더 이해하기 어렵다. 신중히 고려하라
-
인수 객체
인수가 2-3개 필요하다면 일부를 독자적인 클래스 변수로 선언할 가능성을 짚어보라
-
인수 목록
때로는 인수 개수가 가변적인 함수도 필요하다. String.format메서드 처럼
-
동사와 키워드
함수의 의도나 인수의 순서와 의도를 제대로 표현하려면 좋은 함수 이름이 필수다. 단항 함수는 함수와 인수가 동사/명사 쌍을 이뤄야 한다.
예)assertEquals보다 assertExpectedEqualsActual(expected, actual)이 더 좋다. 그러면 인수 순서를 기억할 필요가 없어진다.
부수 효과를 일으키지 마라
부수효과는 거짓말이다. 함수에선 한가지를 하겠다고 약속하고 남몰래 다른짓도 해선 안된다.
함수로 넘어온 인수나 시스템 전역변수를 수정하는경우도 있다.
-
출력인수
일반적으로 우리는 인수를 함수 입력으로 해석한다.
출력인수는 피하고, 함수에서 상태를 변경해야 한다면 함수가 속한 객체 상태를 변경하는 방식을 택한다.
명령과 조회를 분리하라
함수는 뭔가를 수행하거나 뭔가에 답하거나 둘 중 하나만 해야 한다.
객체 상태를 변경하거나 객체정보를 반환하거나 둘 중 하나다.
오류 코드보다 예외를 사용하라
명령 함수에서 오류 코드를 반환하는 방식은 명령/조회 분리 규칙을 미묘하게 위반한다. 자칫하면 if문에서 명령을 표현식으로 사용하기 쉬운 탓이다.
-
try/catch 블록 뽑아내기
코드 구조에 혼란을 일으키며, 정상 동작과 오류 처리 동작을 뒤섞는다. try/catch 블록을 별도 함수로 뽑아내는 편이 좋다.
-
오류 처리도 한 가지 작업이다.
함수와 마찬가지도 오류 처리도 한 가지 작업에 속한다. 오류를 처리하는 함수는 오류만 처리해야 마땅하다.
-
Error.java의존성 자석
오류 코드를 반환한다는 이야기는 어디선가 오류 코드를 정의한다는 뜻이다. 오류코드가 변할때마다 클래스전부를 다시 컴파일하고 배치해야하므로, 오류 코드 대신 예외를 사용하면 새 예외는 Exception 클래스에서 파생된다. 따라서 재 컴파일/재배치 없이도 새 예외 클래스를 추가 할 수 있다.
반복하지 마라
중복은 소프트웨어에서 모든 악의 근원이다. 원칙과 기법이 중복을 없애거나 제어할 목적으로 나왔다.
데이터베이스 정규형식 / AOP(Aspect Oriented Programming) / COP(Component Oriented Programming)
구조적 프로그래밍
함수는 return문이 하나여야 한다. 루프 안에서 break나 continue를 사용해선 안되며 goto는 절대로 안된다.
위 규칙은 함수가 클때만 이익을 제공한다. 함수를 작게 만든다면 간혹 return, break, continue를 여러차례 사용해도 괜찮다. 반면 goto는 큰 함수에서만 의미가 있으므로, 작은 함수에서는 피해야만 한다.
함수를 어떻게 짜죠?
소프트웨어를 짜는 행위는 여느 글짓기와 비슷하다.
길고 복잡하고 정리되지 않은 말들(코드)를 다듬고, 함수를 만들고,이름을 바꾸고, 중복을 제거, 메서드를 줄이고 순서를 바꾸고, 클래스를 쪼개는 등.
⌨️ 이 장에서도 이름의 중요성, 함수를 잘 만드는 방법에 대해 설명해주었는데 마지막 함수를 어떻게 짜죠? 소제목의 소프트웨어를 짜는 행위는 여느 글짓기와 비슷하다. 라는 말이 꽂혔다. 나는 말로도 모두 풀어내지 않고 다짜고짜 기능을 코드로 구현하려 했던것 같다.