예측 가능한 코드 #좋은코드나쁜코드 #6장
* 본 아티클은, '좋은 코드 나쁜 코드' 6장을 기반으로 작성된 글입니다.
매직값을 반환하지 않는다
-1을 반환하는 등, 매직값을 반환하는 것은 함수 호출하는 위치에서 예측이 불가능하다.
null, Optional을 반환하거나, 오류를 발생시키는 것으로 해결할 수 있다.
Null object pattern을 적절히 사용하라
컬렉션을 반환할 때, 비어 있음을 나타내려고 빈 컬렉션을 반환할 수 있다.
이 또한 Null object pattern의 예시이다.
하지만 빈 문자열은 의미를 갖고 있다고 볼 수 있어 지양해야 한다.
Null의 의미를 갖는 새로운 객체를 구현할 수 있다.
하지만 예상을 벗어나는 동작을 할 수 있어 조심해야 한다.
Null 안정성을 지원하는 언어를 사용하거나, Optional을 사용할 수 있게 되면서
Null object pattern의 사용을 지지하는 많은 주장이 힘을 잃고 있다.
예상치 못한 부수 효과를 피하라
부수 효과는 함수의 호출이 외부에 초래한 상태 변화를 의미한다.
- 사용자 출력
- 파일, DB 저장
- 다른 시스템 호출
- 캐시 업데이트 등
함수의 이름 등을 통해, 동작을 충분히 설명해서 부수 효과를 방지해야 한다.
그 전에 부수 효과를 일으키는 동작을 제거할 수 있다면 가장 좋다.
입력 매개변수를 수정하는 것에 주의하라
인자로 받은 객체를 수정하는 것은 버그를 초래할 수 있다.
해당 객체가 다른 곳에서 재사용될 수 있고, 변화가 있었다고 예측하기 어렵기 때문이다.
이는 새 자료구조에 복사해서 변경함으로써 해결할 수 있다.
오해를 일으키는 함수를 작성하지 마라
중요한 입력을 필수 항목으로 만들어(null일 수 없게),
값을 사용할 수 없는 경우 함수를 호출할 수 없도록 할 수 있다.
미래를 대비한 열거형 처리
열거형 추가를 고려하지 않고, 암묵적으로 처리하는 것은 문제가 될 수 있다.
예컨대, A, B에 대해서는 true를, 나머지에 대해서는 false를 반환하는 식이다.
이 경우, true를 반환해야 하는 값이 열거형에 추가되는 경우,
true를 반환하는 코드를 추가하지 않아도 개발자가 알 수 없다.
코드에 추가되지 않은 열거형에 대해서는 예외를 발생시킬 수 있다.
또한 스위치 문을 사용할 수도 있다. (이때, 기본 케이스 사용은 지양해야 한다.)
Boolean isOutcomeSafe(PredictedOutcome prediction) {
switch (prediction)
case COMPANY_WILL_GO_BUST:
case WORLD_WILL_END:
return false;
case COMPANY_WILL_MAKE_A_PROFIT:
return true;
}
throw new UncheckedException("Unhandled prediction: " + prediction);
}
테스트로 해결할 수는 없나?
테스트는 별개로 잘 작성되어야 하지만,
테스트만으로 예측 가능한 코드를 작성하고, 반대의 경우 발생하는 문제를 모두 해결할 수는 없다.
테스트 또한 완벽할 수 없기 때문이다. (놓칠 수 있고, 완벽한 테스트 작성이 불가능할 수 있고(멀티 스레딩 등), mocking 등을 잘못 작성할 수 있다.)