TDD 강의가 끝난 지 1, 2주가 지난 시점이지만 늦게나마 마지막 회고를 작성해보려고 합니다. 4, 5주 차 회고에서 작성했다시피 그때 당시에 볼링이라는 마지막 미션을 남겨둔 상태였습니다. 그래서 좀 여유를 부리기도 하였고 미션의 난이도가 지난 3개의 미션보다 월등히 높아진 것을 체감하여 강의가 끝나는 날까지 꽉 채워서 미션을 진행하였습니다.
4월에 TDD 강의를 수강하면서 꼭 모든 미션은 완수하겠다는 목표를 세웠는데 그 목표를 이룬 거 같아서 참 다행이지만 강의가 끝난 지금 매일 진행하던 미션을 안 하니깐 뭔가 허전한 기분이 들기도 하네요. 모든 미션을 클리어하면 다음 기수의 리뷰어가 될 수 있는 기회를 주신다고 하셨었는데 조금이지만 기대를 해보면서 마지막 미션인 볼링이 난이도가 높은 만큼 리뷰어님께서 많은 피드백을 해주셨는데 몇 가지 내용을 정리해보도록 하겠습니다.
※ 마지막 미션인 볼링에서 많은 피드백을 해주셨는데 정말 갈길이 멀다는 것을 많이 느꼈습니다..!!
볼링의 첫 번째 미션은 실제 서비스 될 법한 코드를 유지 보수하기 좋은 코드로 리팩터링 하는 미션이었습니다. 많은 회사, 기업에서 서비스 레이어에 비즈니스 로직과 관련된 코드를 많이 작성합니다. 저 또한 이 강의를 듣기 전까지 그랬습니다. 그러나 이번 강의를 통해 도메인에 비즈니스 로직을 구현하고 서비스 레이어는 Thin Layer로 각 객체에게 메시지를 전달하는 계층임을 알게 되었습니다.
위처럼 도메인에 비즈니스 로직을 구현하면 좋은 점이 테스트 코드를 쉽게 작성할 수 있을 뿐 아니라 엔티티 자체가 능동적으로 행동을 취하는 객체 지향적으로 코드를 작성할 수 있습니다. 조영호님의 객체지향의 사실과 오해라는 책에서 "객체를 하나의 능동적인 존재로 바라보고 그것을 의인화라고 부른다"라는 구문을 적어주셨는데 가장 인상 깊은 구문이었고 이 내용을 재성님께서 강의 중에 언급해주셨고, 이 내용을 다시 한번 상기시킬 수 있었습니다. 결국 주문이라는 행위를 Order 라는 도메인이 스스로 하도록 우린 Order 도메인에 주문하겠다는 메시지를 보내면 됩니다.
볼링의 두 번째 미션은 총 10개의 프레임에서 사용자가 볼링의 점수를 입력할 때마다 볼링 규칙에 따라 점수판을 그리는(X, -, 9|/) 미션이었습니다. 두 번째 미션을 보자마자 바로 멘붕에 빠졌습니다. 이전에 했던 미션을 보면 어떻게 설계하고 로직을 짜야할지 느낌이 오긴 하지만 이 미션의 경우는 설계, 로직을 어떻게 가져가야 할 지 오랜 시간 고민해도 답이 나오지 않았습니다. 그래서 재성님께서 nextstep 홈페이지에 등록해주신 볼링 미션의 힌트를 봤고 그때 상태 패턴을 알게 되었습니다. 각각의 클래스가 가질 수 있는 상태를 State(저는 Status라고 했는데 State가 더 자연스러운 거 같습니다.)라는 인터페이스 혹은 추상 클래스로 추상화시킨 후에 State를 상속받는 특정 상태 클래스(FirstShoot, Strike, Spare etc..)를 구현하는 방식으로 미션을 해결해 나아가는 것을 요구하는 미션이었습니다. 그래서 상태 패턴을 도입해 미션을 해결하였고 그 과정에서 유지 보수하기 좋은 코드가 될 수 있도록 리뷰어님께서 많은 피드백을 주셨습니다.
피드백 내용을 몇 가지 적어보면 다음과 같습니다.
- 한 테스트에서 여러 개의 로직을 검증하고자 할 때 assertAll을 사용해보시면 좋을 거 같습니다.
- 특정 상태에서 호출 될 수 없는 메서드의 예외 처리는 UnsupportedOperationException을 사용해보시면 좋을 거 같습니다.
- 객체지향 생활 체조의 원칙에 따라 "한 메서드에 오직 한 단계의 들여 쓰기만 한다."의 규칙을 따라보시면 좋을 거 같습니다.
등등, 사소하다고 생각될 수 있지만 이런 세부적인 변화가 유지보수하기 좋은 코드로 가는 첫걸음이기에 수많은 피드백이 너무 감사했습니다.
세 번째 미션은 두 번째 미션에서 진행한 점수판에 누적 점수를 계산하여 보여주는 미션이었습니다. 세 번째 미션의 주요 목표는 각 객체(Frame)에 메시지를 던져 점수 계산에 대한 책임을 위임하는 것이었습니다. 그러나 이 미션의 의도와는 다르게 구현한 거 같아서 아직도 아쉬움이 남습니다. 미션이 원하는 설계, 로직에 대한 설명을 하면 향후에 수강하시는 분들이 이 글을 보고 직접 생각하실 수 있는 기회를 뺏는 것이기 때문에 별도로 적지 않지만, 제가 한 방법은 모든 프레임(Frame)을 생성하고 각 프레임이 획득한 점수도 다 따로 만들어서 구현을 하였습니다. 그래서 점수 계산을 프레임 외부에서 진행하였기 때문에 미션은 성공했지만, 아쉬움이 많이 남았습니다.
네 번째 미션은 다수의 사용자가 볼링을 같이 칠 수 있도록 구현하는 것이었습니다. 기존에 완수한 2, 3번째 미션을 잘 구현했다면 무리 없이 진행할 수 있는 미션이었습니다. 네 번째 미션의 코드 리뷰를 요청하고 피드백을 기다리고 있었는데 리뷰어님께서 라이브로 코드 리뷰를 하고 싶으시다고 하셔서 약 1시간 30분 동안 귀중한 시간을 보낼 수 있었습니다. 미션에 대한 전반적인 설명과 아쉬운 부분, 잘한 부분, 비즈니스 로직에 대한 리팩터링까지 해주셔서 너무 감사했습니다.
피드백 내용을 몇 가지 적어보면 다음과 같습니다.
- CustomException을 사용해보시면 좋을 거 같습니다.
=> 사용자에게 의미 있는 예외를 전달해주고자 할 때 CustomException을 사용하면 좋다고 피드백 해주셨습니다.
=> 한 메서드에 검증하는 코드가 2개 이상 존재할 때 둘 다 IllegalArgumentException으로 처리를 해주게 된다면 실패하는 테스트 코드를 작성할 때 2개의 검증 코드에 대한 Exception이 IllegalArgumentException으로 동일하기 때문에 어떤 이유로 실패했는지 다른 개발자분들이 보셨을 때 한눈에 확인하기 어렵다고 설명해주셨습니다.
- 테스트 코드 작성 시 자주 사용되는 assertThatIllegalArgumentException의 존재도 알려주셨습니다.
- IllegalArgumentException, IllegalStatementException에 대한 설명도 해주셨습니다. (이펙티브 자바)
- 상태 패턴에서 좀 더 공통으로 추상화할 수 있는 부분이 있음을 알려주셨습니다.
=> State : 인터페이스는 모든 상태의 공통
=> Running : 아직 프레임이 끝나지 않은 상태 (FirstShoot, Ready)
=> Finish : 한 프레임이 끝난 상태 (Strike, Shoot, Miss)
등등 화면 공유를 통해 라이브로 피드백을 진행하고 다양한 의견을 나눌 수 있어서 실제로 협업하는 기분이 들어서 너무 재밌고 소중한 시간을 보냈습니다. TDD 강의를 통해 개발이 단순 생산이라는 생각에서 미학적인 요소가 있음을 느껴서 더 흥미가 생겼고 재성님의 강의는 매우 유익했고, 리뷰어님들의 정성스런 코드 리뷰는 많은 것을 깨닫고 배우는 너무 재미있는 8주를 보낸 거 같습니다.
혹여나 더 나은 개발자, 한 단계 성장하는, nextstep으로 가는 개발자가 되고 싶으시면 TDD 강의 수강을 적극 권장합니다!!
※ TDD 강의가 끝난 이후에 어느 기업의 과제를 약 1주일 정도 진행하였습니다. 과제를 하면서 TDD 강의에서 배운 내용을 최대한 적용하려고 노력했는데, 다음에 프로젝트 내용을 정리해보도록 하겠습니다.