우아한테크코스 웹 백엔드 7기 프리코스 3주차 회고
여러가지 일을 하다보니 회고쓰는 것에 신경쓰지 못해 프리코스가 끝난 지금 3주차와 4주차 회고를 올려보려고 합니다.
https://github.com/LimJaeEun0930/java-lotto-7/tree/LimJaeEun0930
요구사항은 위 링크를 통해 확인할 수 있는데요 3주차 미션은 로또를 구현하는 것이었습니다.
지난 2주차미션부터 클래스를 나눠서 설계를 하는 방식을 도입했는데요 이번 미션은 2주차 미션보다 클래스를 어떻게 나눠야 할지에 대한 고민을 더 하게 되었던 것 같습니다. 당첨내역을 출력한 이후 수익률을 콘솔로 출력하는 요구사항이 있는데, 수익률을 저장하기 위해선 구매한 로또중 당첨된 로또의 등수와 당첨개수를 저장할 곳이 필요할텐데 이것을 위해 따로 User 클래스를 만들어야할지, 입력이 잘못된 경우 어디에서 처리해서 어떻게 다시 입력을 받게 할지 등.. 고민거리가 많았고 2주차에 비해 난이도가 확 올라가는 느낌이었습니다.
User 클래스를 넣지 않은 이유는 구현할 프로그램안에서 유저들이 로또를 사는게 아닌, 프로그램을 사용하는 사용자가 로또를 발행하고 수익률을 출력받는 방식이기에 따로 유저를 구현할 필요가 없다고 생각되었습니다.(유저를 구현한다면 유저별로 수익률을 얻을 수 있게 구현했겠지만 요구사항과는 다르기에..)
public class Application {
public static void main(String[] args) {
LottoSystem lottoMachine = new LottoSystem();
int money = View.inputLottoPurchaseMoney(INSERT_MONEY);
List<Lotto> boughtLottos = lottoMachine.buyLotto(money);
System.out.printf("%n");
lottoMachine.printLottoNumbers(boughtLottos);
System.out.printf("%n");
HashSet<Integer> numbers = View.inputWinningNumbers(INSERT_WINNING_NUMBERS);
lottoMachine.setWinningNumbers(numbers);
System.out.printf("%n");
int bonusNumber = View.inputBonusNumber(INSERT_BONUS_NUMBER, lottoMachine.getWinningNumbers());
lottoMachine.setBonusNumber(bonusNumber);
lottoMachine.processLottoResult(boughtLottos);
System.out.printf("%n");
lottoMachine.printWinningStatistics();
}
}
Application 클래스의 main메서드에 전체적인 코드를 짰습니다. 후에 코드리뷰를 받았는데 Application클래스가 컨트롤러의 역할을 하는 것 같다는 의견을 듣고 mvc패턴에 대해 알아보게 되었습니다. 위의 코드를 보시면 전체적인 흐름을 보실 수 있을 것이라 생각합니다.
프로그램은 대략 이렇게 실행됩니다.
사용자가 로또구매금액을 입력한다. -> 1000원단위의 입력이라면 로또를 구매한다. -> 로또 당첨번호, 보너스 번호를 입력한다. -> 사용자가 구매한 로또들의 번호와 당첨번호를 대조해서 당첨이 되었다면 LottoPrize enum의 각 enum(1등,2등,3등..)의 상태인 당첨횟수를 +1해준다. -> 구매금액과 당첨금액의 비율을 구해 수익률을 계산하고 보여준다.
고민한 점
어디서 input을 받을것이냐
InputView라는 클래스를 1,2주차까지 사용하지 않았습니다. 이번 미션에서도 초반에는 LottoSystem::buyLotto 메서드에서 입력을 받으려고 했지만 이번 기능요구사항에
사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, "[ERROR]"로 시작하는 에러메시지를 출력 후 그 부분부터 입력을 다시 받는다
라는 지침이 있었고 사용자가 값을 잘못 입력한 경우 에러메시지를 발생하고 입력을 다시 받는 로직을 buyLotto메서드에 쓰는 것은 가독성을 해치고 메서드의 주제에 넘어선다고 생각되어 스터디원들과 코드리뷰를 할 때에 발견한 InputView 클래스를 생각하게 되었습니다.
InputView에 대해 공부한 후 클래스를 만들어 이 클래스의 메서드에서 입력을 받고 잘못입력한 경우 처리를 수행하였습니다. 값 검증에 대한 Validator클래스를 또 만들어야하나 고민했지만 프로그램의 규모가 그렇게 크지 않기 때문에 따로 만들지는 않았습니다.
금액입력을 제외한 나머지 입력기능에 대해서도 이 클래스에서 메서드를 만들어 입력을 받았습니다.
아쉬운점
당첨번호와 보너스번호를 입력한 다음 사용자가 구매한 로또들의 번호와 대조해서 당첨금액을 산정하는 메서드인 LottoSystem::processLottoResult메서드 구현을 깔끔하게 하지 못한 것 같다. 지금 다시 구현하라고 하면 로또당첨개수(보너스번호 포함)와 보너스번호 포함여부를 나타내는 boolean값을 저장하는 클래스를 만들고 이 클래스의 개체를 통해 당첨등수를 뽑아내는 로직을 짤 것 같다.
깨달은 점, 공부하게 된 것
mvc패턴에 대해 다시 공부하게 되었고(오래전에 스프링 공부할때 한번 보긴 했지만 오래되어서..) InputView,OutputView를 통해 입출력에 관한 부분을 따로 뺐을때, 메서드의 책임이 줄어들고 가독성이 좋아지며, 검증과 같은 기능을 넣었을때 부담이 줄어든다는 것을 알 수 있었다.
공부할만한 것
EnumMap의 개념에 대해 알게되었지만 시간상의 이유로 사용할 정도로 습득하지 못했다. 다시 로또문제를 풀어보게 된다면 이를 사용해 해결해보고 싶다.