안녕하세요. Brad입니다. 오늘 하루도 정말 빠르게 지나갔네요. 그러고보니 올해도 얼마가 안 남았어요.. 흑흑.. 눈물을 닦아내고 오늘 진행한 내용에 대해 기록해보려 합니다. 오늘은 새로운 미션 '로또게임'의 step1을 구현하여 PR보내는 것이 목표였는데요. 설계부터 구현까지 생각보다 오래걸렸습니다.
이렇게 그리는 것이 맞는지는 모르겠지만 이번엔 설계를 해가면서 어떻게 구현해야할지 구상해봤습니다. 이 중에 막혔던 부분은 다음과 같습니다.
InputView
에서 값을 받아서 가공(문자열을 정수 리스트로 반환, 나누기 등)을 View에서 처리해서 보내나? 아님 Controller? 또 그것이 아니라면 Domain에서?- 전 Domain에서 받는 즉시 바꾸도록 처리하였습니다. 그 이유는 View에서는 오로지 입력만 받게끔 하고 싶었고 Controller에서도 데이터에 대한 가공이 포함되어 있는 것이 적절하지 않다고 생각했기 때문입니다.
로또들을 어디에 저장시키는게 좋을까?
- 처음에 고려해둔 곳은 Controller 였습니다. 하지만 InputView 내용 가공을 안하는 것과 같은 이유로 적절하지 않다고 생각했습니다.
- 따라서 Domain 중 전반적인 로직 운영을 담당하는
LottoGame
이라는 클래스 안에서 구현하였습니다.
ResultView
에는 어떻게 구성된 DTO를 받을 것인가?- 가장 오랜 시간 동안 고민했던 부분입니다. 결국 이에 따라서 어떻게 데이터를 담아줘야할지, 그리고 어떤 클래스들이 추가적으로 만들어 구성할건지 결정할 수 있기 때문입니다.
- 출력값을 고려하면 '매칭수', '산 로또 중 매칭수에 충족하는 로또의 수', '매칭수별 상금', '이익률'이 필요하였습니다. 이렇게 요구되는 정보가 많았기 때문에 우선 로직과 크게 관련없는 것들은 뒤로 빼고 중요한 부분만 도메인에서 DTO로 보낸다음 로직이 없어 중요하지 않아 뺀 것은 따로 불러와야 했습니다.
- 구체적으로
LottoGame
에서 로또들을 다 만들고 checkLotto()를 통해 '매칭수', '산 로또 중 매칭수에 충족하는 로또의 수'를int[]
로 담아 반환합니다. 다시 Controller에서makeResultDto
로 보내어 그곳에서int[]
정보를 Map에 담고 이익률을 계산하는 작업을 추가적으로 하여ResultDto
를 만들었습니다.
왜 자꾸 똑같은 값이 출력될까?
Lotto를 한 줄씩 만들어주는
LottoNumGenerator
에서 이해할 수 없는 오류가 계속 발생하였습니다. 분명 매번 랜덤값을 통해 다르게 만들어주는데LottoDto
에는 같은 값이 담기는 것입니다.코드는 다음과 같이 구현되어 있었습니다.
public class LottoNumGenerator { private static List<Integer> lottoNums = new ArrayList<>(); static { for (int i = LOTTO_NUM_START; i <= LOTTO_NUM_END; i++) { lottoNums.add(i); } } public static List<Integer> generate() { Collections.shuffle(lottoNums); return lottoNums.subList(0, 6); } }
이유를 알 수 없어 저와 같은 레벨의 잘하는 다른 멤버에게 물어봐 해결할 수 있었습니다. 문제가 발생한 이유는 반환할 때 주소값(reference)을 반환한다는 것이었습니다.
12줄에서 lottoNums의 인덱스 번호 0부터 5까지를 잘라서 보내는데 이때 보내는 것은 lottoNums에 대한 주소값이었던 겁니다. 저는 로또 번호를 매번 1부터 45까지 새로 생성하는 것이 비효율적이라 static으로 선언하여 한번만 생성되게 하였는데 결국 이 주소가 로또의 개수만큼 다 같이 사용되고 있었던 것입니다.
다시 이 프로그램 안에서 오류가 발생된 이유를 시뮬레이션을 하면 우선 로또가 10개가 생성되어야 한다고 가정하겠습니다. 그럼 먼저 한 줄의 로또가 생성됩니다. 그리고 예를들어 '1f2gsa4f'라는 주소값을 보냈다고 생각하겠습니다. 그리고 DTO에 넣습니다. 그리고 두번째 로또가 기존 로또 배열에서 shuffle된 다음 '1f2gsa4f'로 보냅니다(이 경우 첫번째 넣은 값이 두번째 값으로 바뀝니다. 주소가 같은 상태에서 shuffle되었기 때문입니다). 다음도 마찬가지로 3번째 셔플이 발생하면 3번째 값으로 1,2번째값도 바뀝니다. 따라서 결국엔 제일 마지막 값으로 생성된 로또 모두 변하는 것입니다.
이 경우 반환할 때 새로운 객체로 만들어 반환하면 새로운 주소값을 보내기 때문에 이와 같은 오류를 막을 수 있습니다. 다시 말하면 12줄을
return ArrayList<>(lottoNums.subList(0, 6));
로 바꾸는 것이죠.
오늘 추가적으로 공부한 부분
'TIL' 카테고리의 다른 글
Today's Dev Notes(2018-10-23) (2) | 2018.10.24 |
---|---|
Today's Dev Notes(2018-10-19) (0) | 2018.10.20 |
Today's Dev Notes(2018-10-16) (0) | 2018.10.16 |
Today's Dev Notes(2018-10-15) (0) | 2018.10.15 |
Today's Dev Notes(2018-10-12) (0) | 2018.10.12 |