함수에서 이상적인 인수 개수는 0개(무항)다.
다음은 1개(단항)고, 다음은 2개(이항)다. 3개(삼항)는 가능한 피하는 편이 좋다.
4개 이상(다항)은 특별한 이유가 필요하다. 특별한 이유가 있어도 사용하면 안 된다.
인수는 어렵다.
인수는 개념을 이해하기 어렵게 만든다.
인수에 질문을 던지는 경우
→ boolean fileExists(”MyFile”)
인수를 뭔가로 변환해 결과를 반환하는 경우
→ InputStream fileOpen(”MyFile”)
이들 두 경우는 독자가 당연하게 받아들인다. 함수 이름을 지을 때는 두 경우를 분명히 구분한다. 또한 언제나 일관적인 방식으로 두 형식을 사용한다.
이벤트 (입력 인수로 시스템 상태를 바꾸는 함수, 앞선 두 경우보다는 다소 드물게 사용한다)
→ passwordAttemptFailedNTimes(int attempts)
이외의 케이스에서는 단항 함수는 가급적 피하도록 한다.
다음 세 함수는 모두 같은 역할을 하는 함수입니다.
StringBuffer transform(StringBuffer in)
→ in을 입력 인수로 받아 StringBuffer out을 반환합니다.
void transform(StringBuffer out)
→ out을 변환하여 반환하는 함수입니다. 즉, out은 출력 인수입니다.
StringBuffer transform(StringBuffer in)
→ in을 변환하여 반환하는 함수입니다. 즉, 입력 인수를 그대로 돌려주는 함수입니다.
1번은 위에서 언급한 많이 쓰이는 단항 형식에 정확히 부합합니다.
그렇다면, 2번과 3번 중에서는 어떤 형식을 취해야 할까요? 클린 코드에서는 이렇게 말합니다.
입력 인수를 그대로 돌려주는 함수라 할지라도 변환 함수 형식을 따르는 편이 좋다.
적어도 변환 형태는 유지하기 때문이다.
→ 3번이 차라리 낫다고 하네요!
플래그 인수는 추하다. 함수로 부울 값을 넘기는 관례는 정말로 끔찍하다. 왜냐고? 함수가 한꺼번에 여러 가지를 처리한다고 대놓고 공표하는 셈이니까!
이항 함수가 무조건 나쁘다는 소리는 아니다. 프로그램을 짜다보면 불가피한 경우도 생긴다. 하지만 그만큼 위험이 따른다는 사실을 이해하고 가능하면 단항 함수로 바꾸도록 애써야 한다.
assertEquals(1.0, amount, .001)은 그리 음험하지 않음 삼항 함수다. 여전히 주춤하게 되지만 그만한 가치가 충분하다. 부동소수점 비교가 상대적이라는 사실은 언제든 주지할 중요한 사항이다.
assertEquals(float expected,float actual)
→ deprecated
assertEquals(double expected,double actual,double delta)
→ replaced
그만큼 주지할 만 한 중요 사항이었다는 뜻이겠죠? 이렇듯 인수는 적을 수록 좋다는 말이 무조건적으로 옳은 것은 아닙니다. 상황에 맞게 유연한 적용을 할 필요가 있겠습니다. 물론, 신.중.히. 고려해야겠지만요.
객체를 생성해 인수를 줄이는 방법이 눈속임이라 여겨질지 모르지만 그렇지 않다.
...(중략)
변수를 묶어 넘기려면 이름을 붙여야 하므로 결국은 개념을 표현하게 된다.
부수 효과는 거짓말이다. 함수에서 한 가지를 하겠다고 약속하고선 남몰래 다른 짓도 하니까.
객체 지향 언어에서는 출력 인수를 사용할 필요가 거의 없다. 출력 인수로 사용하라고 설계한 변수가 바로 this이기 때문이다.