우아한 테크코스 6기 프리코스 2주 차는 자동차 경주였다.
이번에도 저번 숫자 야구 게임에 이어서 회고의 느낌으로 작성할 예정이다.
내가 했던 고민과 수정했던 부분에 대한 이유를 주로 작성할 것이다.
고민거리
미션 중에 시도 횟수만큼 반복을 하는데, 이때 이 시도 횟수를 어떻게 처리할지에 대한 고민을 했다.
정확히 말하자면 나는 시도 횟수는 양의 정수여야 한다고 판단했다.
그렇다면 이 값에 대한 검증이 존재해야 하는데 이를 어디서 진행할 것인가?
나는 총 3가지를 고민했다.
첫 번째는 InputValidator였다.
즉 inputView를 받자마자 이를 예외를 검증하는 것이다.
하지만 이는 단순히 시도 횟수만을 위한 검증이라는 생각이 들기도 하였고, InputValidator는 빈 값만 체크하도록 전체 공용으로 깔끔하게 사용하고 싶었다.
두 번째는 Converter를 사용하여 String을 int로 바꾸는 과정에 검증을 진행하는 방법이었다. 이는 네이밍에 의미를 담고 있기에 적절하다고 생각했다.
그러다 문득 위치라는 Position도 객체로 보는데, 시도 횟수를 왜 객체로 관리하지 않았지?라는 의문이 들었다.
이후 이를 객체로 관리해 보니, 검증에 대한 확실한 책임도 가져가고 시도 횟수가 끝났는지나 시도 횟수를 감소시켜라는 등의 메시지를 주고받을 수 있어서 이 방법이 옳다고 생각하였다.
이런 식으로 관리하니까 보다 객체지향적이라는 생각이 들었다.
객체에 대한 편견이 무의식 중에 있었던 것 같다.
좀 더 고민하여 객체 지향적인 코드를 작성하려고 노력해 보자.
고민거리
미션내용 중에 위치가 바뀌는 조건이 4 이상의 수가 들어올 때이다.
그렇다면 숫자가 4 이상인지를 판단하는 메서드는 Car에 있어야 하는지, Position에 있어야 하는지 고민했었다.
처음에는 Position에 숫자를 넘기고 4 이상이면 move메서드를 통해 값을 증가시켰다.
이렇게 진행한 이유는 위치에 관련된 일을 모두 Position에 넘기고 싶었기 때문이었다.
하지만 만약 Car가 아니라 기차나 비행기는 숫자가 7 이상일 때 움직여야 한다는 조건이 추가된다면 Position의 변화가 필수적으로 일어나야 했다.
그렇기에 이를 Car에서 이를 확인하고 Position에 명령을 하는 구조로 수정하였다.
이렇게 분리하니까 이후 확장에도 유연하게 대처할 수 있다는 생각이 들었다.
배운 점
테스트를 진행할 때 Fixture를 종종 사용하였다.
이는 객체의 생성이 반복되기에 이를 편하게 진행하기 위해 따로 빼두었던 기능이다. 처음에는 단순히 객체 생성에 대한 코드 중복을 줄이기 위해 사용했었다. 그러다 객체를 생성하는 방식이 생성자에서 정적팩토리 메서드로 바꾸는 일이 있었다.
당연하게도 테스트 코드도 전부 수정해야겠다는 생각을 가지고 있었는데 이를 Fixture에서 관리하다 보니 Fixture만 수정하면 되어 코드 수정이 최소화된다는 장점도 알게 되었다.
위처럼 다른 테스트에서 계속해서 Fixture를 사용했었다.
코드의 중복을 줄이는 것이 얼마나 중요한 것인지 실감하게 되었다.
배운 점
저번 주차에는 각각 예외가 전부 IllegalArgumentException로 구현했었다.
그렇기에 어떤 곳에서 예외가 터졌는지를 정확하게 테스트하려면 메시지까지 테스트를 진행하고는 했다.
그러다 프로덕션 코드의 예외 메시지가 바뀌면 테스트 코드가 깨지는 일이 계속해서 발생하였다.
즉 테스트가 메시지에 의존적으로 되어있었다.
테스트 코드도 결국 관리 대상이기에 이러한 상황 자체가 좋지 않다고 판단했다.
그래서 이를 해결하고자 예외를 커스텀하여 각각의 예외를 테스트하도록 수정해 보았다.
이전 미션의 테스트 코드이다. 딱 보더라도 메시지에 의존적이다.
이번에 커스텀한 예외이다.
이 덕분에 메시지가 바뀌어도 같은 예외가 터졌다는 것을 쉽게 테스트할 수 있었습니다.
배운 점
이펙티브 자바를 보던 중 불필요한 객체 생성을 피하라는 챕터에서 예시로 정규표현식이 나와있었다.
이번 미션에서는 사용하지 않았지만, 이전에 정규표현식을 사용하였기에 더욱 흥미로웠다.
내용을 보니 String.matches를 사용할 경우 계속해서 Pattern 객체를 생성한다는 내용이었다.
즉 계속해서 불필요한 객체 생성이 빈번하게 일어나 성능이 느려진다는 것이었다.
이전 코드이다. 내부에서 계속해서 Pattern객체를 생성하기에 성능이 안 좋다.
Pattern을 캐싱해서 성능 문제를 해결할 수 있다.
고민거리
계속해서 고민했던 부분은 결과를 출력하는 부분이었다. 원래 cars.getCars()를 통해 List를 가져온 뒤에 이를 각각 돌아가며 Dto를 씌우고 View로 보냈다. 하지만 이 방법은 결국 getter를 사용하기도 하고 controller에서 결국 cars 내부를 전부 알게 된다는 단점이 있다고 생각했다. 즉 캡슐화가 깨지고 객체에게 메시지를 전달하고 받는 느낌이 아니었다. 이를 해결하기 위해서 도메인에서 Cars 내부에서 Dto를 List로 만들어서 보내도록 수정하였다. 이러한 설계에도 도메인이 dto를 의존한다는 단점을 가진다고 생각되었다. 하지만 그럼에도 전자의 방법에 비해 얻는 이점이 많다고 생각하여 이렇게 진행했다.
기존에는 controller에서 위의 코드를 실행하였다.
앞서 설명한 대로 단순하게 cars를 가져와서 내부 값들을 하나씩 접근하여 view로 보낸다.
수정한 방법이다. domain이 dto를 의존한다는 단점이 존재하지만, 객체에서 메시지를 주고받는 느낌이 확실히 강했다.
또한 캡슐화가 제대로 이루어진다는 느낌을 받아서 이렇게 코드를 작성했다.
다른 사람들의 생각이 너무나도 궁금했다.
그래서 이를 주제로 토론을 진행해 보았다.
토론을 할수록 느끼는 것은 각자 생각이 다른 점도 있고, 코드에 정답이 없다는 것이다.
어떤 코드를 선택하더라도 확실한 근거를 가지고 작성하자.
토론을 하고 나니 다시 생각이 정리되었다.
결국 도메인이 dto를 의존하는 것은 큰 단점이 된다.
그래서 불변 getter를 열고 dto에서 매개변수로 List <Car>를 받고 이를 알맞은 형식을 바꿔주는 것이 더 좋은 코드인 것 같다.
다음 주차에는 이러한 점을 적용해 봐야겠다.
마무리
이번 미션도 정말 재미있게 진행했던 것 같다. 이에 대해 여러 사람들과 소통하니 너무 좋았고 재미있었다.
이번에도 다른 사람들과 코드 리뷰를 진행해 보았다.
항상 느끼는 것이지만, 다른 사람과 소통하는 것이 너무 재미있다. 특히 다른 사람들이 나의 의견에 대한 생각을 말해주고 서로 지식을 공유하는 것이 같이 성장하는 느낌도 드는 것 같다. 다른 분들이 감사 인사를 전하면 기분도 좋아진다.
이번에는 의식적으로 리뷰가 별로 없어 보이는 사람들에게 리뷰를 달아주었다.
이외에도 많은 고민거리가 있었고, 구현을 하면서 스스로 깨닫거나 학습을 통해 지식을 습득하기도 하였다.
이번 주차는 객체 지향과 책임에 대해 고민을 많이 했던 것 같다.
오늘 새로운 미션이 나왔는데, 공통 피드백도 의식적으로 적용하며 몰입하며 진행해 보자!
실제 작성한 코드이다.
https://github.com/kimtaesoo99/java-racingcar-6/tree/kimtaesoo99
'JAVA' 카테고리의 다른 글
[JAVA] 크리스마스 프로모션을 구현하면서 배운점 (1) | 2023.11.16 |
---|---|
[JAVA] 로또를 구현하면서 배운점 (2) | 2023.11.10 |
[JAVA] 숫자 야구 게임을 구현하면서 배운점 (4) | 2023.10.27 |
[JAVA] 체스를 구현하면서 배운점 (0) | 2023.07.06 |
[JAVA] 블랙잭을 구현하면서 배운 점 (0) | 2023.06.20 |