Clean Code 14장 - 15장

2019-05-09

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나 제네릭쓰면 안돼요?

스터디하면서 나온 질문 중 하나였다. 위와 같은 질문처럼 짜게 되면 어떤일이 생길지 생각을 해 보자.

  1. 내부에 if-else 떡칠로 SRP 위반
  2. SRP 이전에 더 근본적인 문제는, 새로운 타입을 추가할때 개발자가 실수로 새 타입에 관련된 로직을 빼 먹어도 오류없이 정상동작하는 것 처럼 보인다는 것이다. (이전에 나온 switch-case의 단점과 동일한 상황) 이 때문에 뒤에 디버깅할때 큰 고생을 하게 된다.
  3. 반면, ArgumentMarshaler아래에 새 타입을 위한 클래스가 없으면 프로그램 자체가 뻗어버리게 된다.

15장 JUnit 들여다보기

여기에 나와있는 ComparisonCompactor는 JUnit4에 있는 것이다. github에 찾아보면 ComparisonCompactor 코드를 볼 수 있다. (JUnit5에는 안보임. 비슷한 구현체가 어딘가에 있겠거니 싶은데, …)

저 코드를 보면 알겠지만 그 안좋다고 평가받은 상태로 남아있다. 이 책에서 말하는 개선방향을 쭉 읽으면 설득이 충분히 되는데, 왜 JUnit4에 반영되지 않은 것일까? 를 생각해보았다.

어찌되었건 ComparisonCompactor는 잘 동작하고있고, 굳이 고칠필요가 없어서 냅둔걸까? 역시 현실은 이상과 다른가?

그래서 junit4에 있는 issue를 찾아봤다. #846, #848, #851 등 관련 PR을 보면 알겠지만 관련시도가 없진않았다.

전후 맥락을 완전히 파악하진 못했는데, 어찌되었건 시도는 있었으나 머지가 되지 않았다..정도로만 이해했다.