Study/우아한 테크 코스 / / 2023. 11. 4. 15:37

[우아한 테크 코스] 프리코스 - 2주차, 레이싱카 회고

1일차

개발에 들어가기 전 기능 목록 구현을 위해 1주차와 마찬가지로
하지만 1주차의 경험을 바탕으로 설계를 진행하였다. 
플로우 차트는 요구 사항에 맞게 금방 구현했었는데, 문제는 역시 클래스 다이어그램을 설계하는 과정이었다. 
이번에는 컨트롤러, 서비스, 뷰, 모델로 프로젝트를 구성하기로 생각을 했었다. 
이유는 컨트롤러에서 프로그램을 제어하는 책임과, 비즈니스 로직까지 포함되어 있어 처음에 계획했던 것 이상의 책임을 가지게 되었기 때문에 비즈니스 로직을 처리하는 서비스를 만들기로 했다. 
서비스에서는 모델에 접근하여 비즈니스 로직을 처리하고, 컨트롤러는 입출력과 서비스를 제어하는 역할을 맡겼다. 이렇게 하니 조금 더 코드가 간결해지고 테스트하기 용이해졌다고 판단했다.

그 다음 고민은, 유효성 검증과 메시지를 변환하는 로직을 어디에서 처리해야 할 지 고민이었는데, 이전 주차의 클래스 다이어그램을 참고하여 설계를 하니 View에서 Convertor와 Validator가 View에 의존하게 되어 SRP를 위반하는 것 같았다. 
그래서 InputView가 변경되면 Validator와 Convertor에도 영향을 주고, 재사용성이 높은 Validator와 Convertor가 다른 context에서 이를 재사용하기 어려울 것 같았고, 테스트하기에도 좋지 않았던 기억이 있었다.
그래서 사용자 입력을 처리하는 InputHandler를 만들고, 처리를 위임하도록 설계를 변경, InputHandler에서 Validator와 Convertor를 생성자 주입을 통해 InputView는 사용자의 입력만 받도록 하고, 이를 handling하는 객체가 유효성 검증과 변환을 담당하도록 설계를 변경했다. 
그리고 도메인 로직이 포함된 model 객체를 직접 반환하는 부분도 추후 model 객체 변경시 api가 변경될 가능성이 있다고 판단하였고, data transfer object를 서비스에서 반환하도록 설계 하였다. 
이 과정에서 리뷰를 받아 공부하여 도입하기로 계획했었던 stream을 사용해 레이싱 경기 완주자를 반환하도록 설계 하였다. 
이렇게 설계하고 나니, 기능 목록을 작성하는 부분은 수월하게 진행하였던 것 같다.

flow chart
Class Diagram

2일차

실제 개발을 진행하였다. 
먼저 model 객체를 생성하기로 마음을 먹었고, Car와 이들을 저장하는 일급 컬렉션 Cars를 구현 하였다. 일급 컬렉션으로 만든 이유는 코드 리뷰를 진행하면서 개념을 알게 되었고, 객체 지향적으로, 리팩토링하기 쉬운 코드를 만들기 위해 이를 고려하게 됐다. 

테스트 코드를 같이 작성하자는 목표에 맞춰 Car를 구현하고, Car의 move 실패, 성공 테스트 케이스를 개발했었는데, 이렇게 하니 move 메소드에서 필요한 유효성 검사와 인스턴스 생성 시 초기 값을 0으로 해주는 등 세세한 부분을 테스트 코드를 작성하며 엣지 케이스에 대해 생각하게 됐다. 

Cars에서 가장 많은 고민이 있었는데, 테스트만을 위한 메소드를 생성하는게 맞을까? 라는 생각이 계속해서 들었다. 정확한 테스트를 위해 List<Car>를 만들고 Car의 name을 비교하려 했었다. 

일급 컬렉션을 처음 만들어 사용하다 보니 생긴 고민이었는데, 패키지 프라이빗 메소드를 사용해서 테스트에 이용할지 getWinner를 사용해 간접적으로 테스트할지 여러 고민이 들었다. 
하지만 애초에 Cars에서 List<String>을 받으려 했던 부분이 문제라는 것을 깨달았고, 메소드에 객체를 생성하는 역할만 부여하기로 변경하여 문제를 해결했다.

 

3일차

3일차에는 설계대로 계속해서 구현했다. 
하나의 기능 작성, 테스트 코드 작성을 반복하였고 1주차에 비해 절반의 시간도 안 들었던 것 같다. 
설계대로 구현하고 코드 리뷰 받은 부분들을 메모해두어 적용해보느라 시간 가는 줄 모르고 몰입해서 개발을 진행했다. 

문제는 초기에는 모델에 있는 비즈니스 로직을 실행하는 계층인 RacingCarService에서 RandomNumber private 정적 멤버 클래스를 만들게 됐는데 정적 멤버 클래스로 만든 이유는 서비스 계층에서 Car를 만들 때만 사용하기 때문에 처음 설계를 그렇게 했었다. 
하지만 이렇게 한 결과 테스트를 컨트롤하기 어려워졌고, mock 객체를 사용해볼지 아니면 설계를 변경할지 고민했었다. 

고민 끝에 RandomNumber interface를 서비스에서 주입 받았고, 테스트하는 경우에는 익명 클래스로 초기화하고 실제 로직 에서는 DefaultRandomNumber 객체를 만들어 random 라이브러리를 호출하게 만들었다. 이렇게 하면 되겠지? 라고 생각했었고, 익명 클래스라는 걸 처음 알게 되어 사용해봤는데 테스트 시에 상당히 유용한 것 같다고 생각했다. 나머지 부분에 대한 개발은 순조롭게 진행됐고, 3일차에 모든 테스트에 성공하게 됐다.



4일차

리펙토링을 주로 했었던 4일차였다. 
 mvc와 같은 패턴이 아닌 내가 직접 추가해나갔던 방식이 처음에는 컨트롤러에 InputView와 OutputView를 주입하고, View들에서 Validator와 Convertor를 Utils로 사용하도록 단순하게 사용했었는데 만약 View가 변경되는 시점에 문제가 생길 것 같다. 라는 고민이 있었어서

 지금의 구조인 Input을 할때 Validator와 Convertor를 따로 두고 이를 Handler가 관리하게 설계했는데 이 방식이 맞을지? 에 대해 많이 고민했다. 

결론은 자바 api에서 얻었던 것 같다. 
단순히 InputView에서는 값을 가져와 변환해서 컨트롤러에 던져주고, 변환하는 클래스에서 유효성 검증도 같이 한다. 하지만 이때 도메인의 유효성까지 같이 검사하지 않고 각각의 클래스에 맞는 유효성 검증을 한다. 로 굳혔다. 
이유는 HashMap같이 자주 쓰는 api들의 내부 로직을 다시 봤었는데 Exception을 던지는 부분은 각각 다 달랐기 때문이다.

 

5일차

5일차는 마찬가지로 설계에 대해서 고민했었다. 
주로 고민을 많이 했던 부분에 대해 깊게 생각하고, 자료를 많이 봤었던 것 같다. 

가장 큰 고민은 흔하게 사용하는 mvc 패턴을 꼭 사용해야 하는지 였다. 이에 확신을 얻기 위해 공통 피드백에서 말해줬던 우아한 테코톡의 mvc에 대한 발표를 전부 봤었던 것 같다. 
나의 경우에는 서로 간의 관심사의 분리를 통해 유지 보수를 쉽게 하기 위해 사용했었다. 발표들을 다 봤는데 결국 대부분 같은 말을 하고 있었다. 

모듈 간 결합도를 낮추는 것. 그리고 그에 대한 규칙이나 구현은 달랐다. 나의 경우에는 mvc를 더욱 효율적으로 적용하기 위해 도기의 발표에서 본 dto를 도입하여 model을 view가 알지 못하도록 적용했고, 범블비 발표를 통해 유효성 검사에 대한 고민도 더욱 명확히 해결했다.

mvc 관련 우아한 테코톡 발표를 정리하여 포스팅도 하였다!

6일차

6일차는 테스트 코드에 관해서 고민을 했다. 
private 메소드를 테스트 해야 하는지 에 대한 질문에 답변을 하다 해당 문제에 관련해서 찾아보았다. 
이번 주차에 개발 시간의 50%는 테스트 코드의 작성에 대한 고민에 있었는데, 대부분의 문서에서 private 메소드는 테스트 할 필요가 없다. 라고 했다. 

그 이유는 3가지 정도인데, public에서 private을 호출하니 필요가 없다. 
테스트가 정말 필요하다면 클래스로 빼야 되는 과한 역할을 맡고 있지는 않은지 확인해야 한다. 
애초에 private이면 안된다. 이 3가지 중 하나 인 경우가 많다고 했다. 

이번 주차 테스트 코드를 작성하면서 대부분의 시간을 테스트 하는데에 사용했는데, 마지막에 이걸 알게 돼서 조금 허탈한 기분이다. 

내가 왜 이걸 테스트 하려고 했을까? 를 생각해 보니 이펙티브 자바에서 테스트할 때 private을 풀어도 되는가? 에 대한 문제에서
 "private -> package-private까지는 괜찮지만, 그 이상은 안된다. 즉 public으로 만들 필요는 없고, package-private으로 만든 뒤 같은 패키지 위치에 테스트를 작성하면 된다." 만 기억했고 
뒤에 나오는 테스트의 경우 접근 제한자를 풀어가며 해야 하는 게 올바른 것인지 한번 더 생각해보라고 블로그를 작성해뒀는데, 이 부분만 까맣게 잊어버렸다. 결국 이로 인해서 "왜 public만 작성해도 괜찮은지"에 대한 공부를 했기 때문에 차 주에는 정확한 테스트를 작성 하는 게 목표이다. 

 

이에 관한 정리와 나의 생각은 여기와 같이 정리했다.


차주의 목표

- mvc 패턴에 맞게 유효성 검사하기
- public 메소드만 테스트하기

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유