post-custom-banner

이어서...

오늘은 하루종일 리팩토링, 버그 픽스, 테스트 코드 작성, 리드미 작성에 시간을 쏟았다. 중간 중간에 제대로 반영하지 못한 요구사항들도 있어서 진땀을 좀 흘렸다...


잘못된 입력시 반복 입력

가장 먼저 한 것은 어제 구현하던 반복 입력 기능을 분리하는 것이었다. 이 반복 입력 요구사항은 여러 검증 클래스에서 쓰여야 하기 때문에, 클래스 분리를 해줬다.일단은 static 으로 만들었는데, 인스턴스 메서드로 만들지는 고민해 봐야한다.

그런데 문제가 있었다. 검증 클래스들은 Validator 인터페이스의 validate() 메서드들을 구현하는데, validateAndGetErrorMessage() 메서드만 외부에 최종적으로 노출되므로 validate 메서드가 외부에 노출될 일이 없는데도 public 으로 선언되어 있었다. 이 메서드를 private 로 만들기 위해서는 인터페이스를 없애야 했는데, 그러기에는 많은 코드를 수정해야 할 것 같았다.

어떻게 할까 고민하다가, 검증 메서드를 호출하는 상위 서비스 객체에서 validateAndGetErrorMessage() 메서드를 호출 하고, 다형성으로 검증하고자 하는 객체를 매개변수로 넣어줬다.
이렇게 기존의 설정을 유지하면서도 새로운 기능을 쉽게 추가할 수 있게 되었다! 인터페이스와 다형성을 사용할 때 확장성의 강력함을 느꼈던 부분이었다.

이렇게 정답 로또 번호 입력에 대해서도 적용시켰다.
이후 공통되게 사용되는 해당 메서드들을 하나로 분리시켰다. | ⬆️ LottoService 클래스의 validateInput() 메서드

이제 외부에서 검증 클래스의 객체와 검증할 입력값을 넣어주기만 하면 로또 구매 금액 입력값이든, 정답 로또 번호 입력값이든 구별하지 않고 검증할 수 있게 되었다. 그리고 출력 부분을 이번 과제때 새로 배웠던 Consumer 인터페이스를 이용해 컨트롤러에서 출력할 것을 주입하게 해 줬다.
| ⬆️ LottoController 클래스의 purchaseLotto() 메서드
| ⬆️ OutputView 클래스의 printErrorMessage() 메서드

이로서 Model이 View를 알지 못하게 하면서도 사용자에게 보여주는 출력은 온전히 View 계층에서 담당하게 되었다!

보너스 검증

반복 입력 구현을 위해 검증 클래스를 살펴보던 중, 보너스 번호 입력에 대한 검증이 없음을 깨달았다.
빠르게 보너스 넘버 검증 기능과 테스트 코드를 작성했다.

컨트롤러, 서비스 레이어 리팩토링

많이 난잡한 컨트롤러와 서비스 레이어의 클래스들을 리팩토링 했다.
어제 코드를 짤 때는 시간의 부족으로 깊게 생각해보지 못하고 머릿속에 떠돌아다니는 생각들을 계속 낚아채면서 구현에 집중했었던지라 리팩토링을 꼭 해야 했다.

1. 불필요한 메서드 삭제

LottoService 클래스의 purchaseLotto() 메서드는 LottoPurchaseServicepurchase() 메서드를 호출해 로또를 구입한 후, PurchasedLottoDto 객체들을 만들어 값을 출력하고 다시 구입한 로또를 반환하고 있다.

여기서 굳이 출력을 위해 DTO를 사용할 필요가 없는게, 부모 클래스인 Lotto 에는 이미 번호들에 대한 getter 메서드가 구현되어 있고, 단순 출력을 위해 getter로 값을 조회하는 건 상관없기 때문이다. 이 불필요한 메서드를 LottoService에서 제거하고 컨트롤러에 역할을 맡겼다.

2. 메서드 분리 및 이동

다형성을 이용해 입력값을 검증하는 메서드를 새로 만들었다. generateBonusNubmer() 메서드처럼 입력값을 저장하는 메서드들의 공통 값을 뽑아와서 메서드를 분리시켰고, 분리한 메서드들과 입력값을 저장하는 메서드들을 서비스 클래스로 이동시키기 위해 getValidInput() 메서드에서 검증 객체, 사용자 입력, 반복시킬 입력 요구 메시지, 출력할 에러 메시지를 매개변수로 설정했다.

입력 다시 받기 - Supplier


리팩토링 중, 문제가 하나 발생했다.

검증 메서드인 getValidInput() 메서드가 매개변수로 입력값을 String 타입의 input 으로 받는데, 이 경우 입력값을 다시 받아올 수 없기 때문에 재입력 요구 메시지가 무한대로 출력되는 문제였다.

매개변수로 입력을 받으면서도 여러번 값을 받기 위해, Supplier 함수형 인터페이스를 사용했다.
이제 validateInput() 메서드에서 에러를 담아 반환할 시 getValidInput() 메서드에서 반복문에 따라 다시 validateInput() 메서드를 실행하고, 이 메서드의 String input = inputSupplier.get() 메서드에 의해 매개변수로 주어진 InputView::getUserInput 을 실행해 값을 새로 받는다. | ⬆️ 인수로 주어지는 InputView::getUserInput

코드가 많이 복잡해졌긴 하지만, 다시 대대적으로 수정하기엔 남은 시간이 얼마 없다. 오늘 마감이니깐...

그 이외에 많은 리팩토링과 테스트 코드 작성

그리고 정말 많은 리팩토링과 단위 테스트를 작성했는데, 이 포스팅에 다 담기에는 하루종일 해도 못할 것 같아서 커밋 기록으로 대체한다...


마무리

또 하나의 과제가 끝났다. 감상은 3주차 전체 회고에 이어서 적겠다.

새로 알게된 점

1. Supplier 타입의 매개변수를 이용해 입력을 필요할 때마다 다시 받을 수 있다.
잘못된 입력에 대한 재입력 요구시 매우 유용할듯 하다. 4주차 과제에도 재입력 요구사항이 있다면 써먹어야겠다.

2. 다형성과 인터페이스는 강력하다는걸 직접 느꼈다.
이걸 잘 써먹고 싶다... 4주차에는 좀 여유롭게 다형성을 활용할 방법을 고민해봐야겠다.

좋았던 점

1. 놓쳤던 요구사항과 개선점들을 단위 테스트를 진행하며, 그리고 회고글을 작성하며 고칠 수 있었던 것

2. 내일부터는 훨씬 더 많은 시간을 들여 새로운 과제를 할 수 있는 것

3. 1주차에 비해 리팩토링에 더 적은 시간을 쓰게 된 것.
그만큼 머리로 하는 시뮬레이션 능력이 향상된 것 같다.

아쉬웠던 점

1. 자식같은 3주차 과제한테 조금은 미안하다.
다른 과제들보다 시간을 더 투자하지 못해서... 프리코스 끝나고 리팩토링 더 해줘야겠다 🥲

도움이 된 자료들

| [Webstorm, intellij] 커밋 취소, 커밋 메시지 수정

| [자바 코딩] 숫자 콤마 찍기 (금액 표기)

profile
자바 백엔드 개발자
post-custom-banner

0개의 댓글