
최근 테스트 코드를 작성하다 조금 애매한 상황을 만났다.
바로 내가 작성한 기능에 대해 테스트 코드를 작성할 수 없는 상황이었다.
분명 핵심 로직인데 특정 클래스 내부에서 private으로 선언이 되어 테스트를 하지 못하고 있었다.
핵심 로직을 private으로 선언한 이유는 아래와 같다.
1. 객체 속성을 직접 접근할 수 없게 만들며, 외부로부터 필요한 값을 해당 객체가 직접 값을 관리할 수 있는 상태로 관리
2. 외부에서 해당 객체의 값이 필요할 때 특정 Public Method(interface)를 통해서만 제공
3. 외부에서 해당 객체의 값을 직접 접근하는 기능은 private 메서드로 선언하고 선언된 private method를 public method 내부에서 사용
그렇다 보니 실질적인 로직을 테스트해야 하는 상황에서 private으로 선언된 메서드에 대해 테스트 코드를 작성하지 못하는 상황이었다.
private method를 테스트 할 수 있는 방법은 몇 가지가 존재한다.
1. 테스트에 해당하는 method를 package private(default)나 protected로 변경해서 테스트를 시도
2. Java Reflection API를 사용해 강제적으로 private method 호출
그런데 private method를 테스트 하기 위해서 위와 같은 다양한 레퍼런스를 통해 찾아본 결과 트레이드오프가 존재했다.
그렇다면 나는 다시 돌아와서
라는 의문을 품게 되었다.
결론적으로 나는 위 질문들에 대해 답변을 하지 못했다.(두 번째의 이유는 존재하지만 이것 또한 나만의 기준이라 맞다고 하기도 애매한 부분이다)
그렇게 'private method의 목적은 무엇인가'에 대해 찾아 보았다.
꽤나 좋은 영어 레퍼런스가 있어 학습하고, 참고하는데 도움이 되었다.
private methods help reduce this size of an object's API
Complexity is the enemy.
코드는 간단하게 만들수록 이해하기 더 쉬워지고, 코드의 유지비용이 더 저렴해진다. 8개의 public method가 있다고 가정해 보자.
이는 "understandability cost” of 8 이해 비용이 8이라는 값이 든다.
다른 클래스에 2개의 public method가 있다고 가정해 보자.
이는 "understandability cost” of 2 이해 비용이 2이라는 값이 든다.
이해 비용의 측정 기준이 정확하지 않다는 것은 맞다. 하지만 비유를 통해 요점을 바라보자. 각 객체의 public method가 적을수록 더 쉽게 이해할 수 있다.
private method는 리팩토링을 해도 안전할 수 있다.
public method는 외부에서 호출될 수 있다. 외부에서 public method를 호출할 경우, 호출하고(사용하고)있는 모든 곳을 변경하지 않는 이상, 메서드를 변경하거나 시그니처를 변경할 수 없다.
할 수 있는것은 오직 구현부 수정 뿐.
private method 만큼은 외부에서 호출할 수 없으므로, 원하는대로 리팩토링이 가능함. 외부 코드를 손상시킬 걱정을 안해도 됨.
물론 same class 내부에서는 영향이 있겠지만 걱정하는 범위 역시 same class 범위 안에서만 걱정하면 된다.
두 가지의 경우가 private method의 목적이라고 레퍼런스 속 글쓰니님의 생각을 말씀해 주셨다. 댓글에 좋은 비판적인 피드백 또한 있으니 참고해도 좋을 것 같다. 각자만의 private method 기준을 설명한다.
좋은 규칙이라고 바라보며 참고해야겠다.