Clean Code 14장 - 15장
14장, 15장 둘 다 어려운 내용은 아니었으나 내가 만약 큰 코드를 고칠 때, 절충안을 찾으면서 깔끔하게 잘 할 수 있을지 모르겠다.
14장 점진적 개선
p. 286
…갑자기 ClassCastException을 왜 사용했느냐고? 이유는 내가 인수 테스트 케이스를 FitNess에서 구현했기 때문이다.
이게 무슨말이지 싶었는데, 테스트 프레임워크 때문에 로직을 변경했다는 뜻이다. 이런식으로 로직이 바뀌는 것은 썩 바람직하지 않다.
‘FitNess에 있는 테스트는 boolean이 아닌 인수로 getBoolean()을 호출하면 무조건 false를 반환을 한다’ 고 책에 적혀져 있다. 그렇기 때문에 ClassCastException이 발생한 상황에서 false를 리턴하도록 b = false
를 추가 한 것.
Marshaler?
책 예제 코드에 ArgumentMarshaler
라는 클래스가 있다. marshaler가 뭐지? 하며 marshal이 뭔지 찾아봤다. 사전적 의미로는 도통 이 클래스에 왜 이런 이름이 붙은건지 잘 와닿지 않는데, Marshalling(마샬링)
이라는 용어가 있다.
흔히 아는 Serialization(직렬화)와 비슷한 개념인듯 했는데, 조금 다르다. 마샬링이 직렬화보다 좀 더 큰 개념 같다.
Python에서는 marshalling, serialization, pickle, flatterning 을 똑같은 개념으로 취급하고 섞어쓰는 듯한데, Java에서는 왜 이 둘을 구분하는지 궁금했다. 이건 다음 글에 따로 포스팅을 하는게 좋을 듯해서 여기는 이 정도로만 적어둠.
getBoolean(), getString(), getInt(), getDouble()… 왜 이렇게 하는게 좋은거죠? Object나 제네릭쓰면 안돼요?
스터디하면서 나온 질문 중 하나였다. 위와 같은 질문처럼 짜게 되면 어떤일이 생길지 생각을 해 보자.
- 내부에 if-else 떡칠로 SRP 위반
- SRP 이전에 더 근본적인 문제는, 새로운 타입을 추가할때 개발자가 실수로 새 타입에 관련된 로직을 빼 먹어도 오류없이 정상동작하는 것 처럼 보인다는 것이다. (이전에 나온 switch-case의 단점과 동일한 상황) 이 때문에 뒤에 디버깅할때 큰 고생을 하게 된다.
- 반면, ArgumentMarshaler아래에 새 타입을 위한 클래스가 없으면 프로그램 자체가 뻗어버리게 된다.
15장 JUnit 들여다보기
여기에 나와있는 ComparisonCompactor는 JUnit4에 있는 것이다. github에 찾아보면 ComparisonCompactor 코드를 볼 수 있다. (JUnit5에는 안보임. 비슷한 구현체가 어딘가에 있겠거니 싶은데, …)
저 코드를 보면 알겠지만 그 안좋다고 평가받은 상태로 남아있다. 이 책에서 말하는 개선방향을 쭉 읽으면 설득이 충분히 되는데, 왜 JUnit4에 반영되지 않은 것일까?
를 생각해보았다.
어찌되었건 ComparisonCompactor는 잘 동작하고있고, 굳이 고칠필요가 없어서 냅둔걸까? 역시 현실은 이상과 다른가?
그래서 junit4에 있는 issue를 찾아봤다. #846, #848, #851 등 관련 PR을 보면 알겠지만 관련시도가 없진않았다.
전후 맥락을 완전히 파악하진 못했는데, 어찌되었건 시도는 있었으나 머지가 되지 않았다..정도로만 이해했다.