Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ dependencies {
compile('ch.qos.logback:logback-classic:1.2.3')
testCompile('junit:junit:4.12')
testCompile('org.assertj:assertj-core:3.9.0')
testCompile group: 'org.mockito', name: 'mockito-core', version: '3.3.0'

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

편리하게 Mock을 사용하기 위해서 mockito 프레임워크 의존성을 테스트 디렉토리에 추가했습니다.

}
23 changes: 23 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import lotto.*;
import view.InputView;
import view.ResultView;

import java.util.List;

public class Application {

public static void main(String[] args) {
PurchaseMoney purchaseMoney = new PurchaseMoney(InputView.inputPurchaseMoney());
LottoGame lottoGame = new LottoGame(purchaseMoney.getMoney(), InputView.inputManualLottoCount());
List<String> strings = InputView.inputLottoStrings(lottoGame.getManualLottoCount());


LottoMachine lottoMachine = new LottoMachine();
TargetLottos targetLottos = new TargetLottos(lottoMachine.createManualLottos(strings), lottoMachine.createAutoLottos(lottoGame.getAutoLottoCount()));
lottoGame.registerTargetLottos(targetLottos);

ResultView.showAllLottos(lottoGame);
WinningLotto winningLotto = new WinningLotto(lottoMachine.createManualLotto(InputView.inputWinningLotto()), InputView.inputBonusNumber());
ResultView.showGameResult(lottoGame.createResult(winningLotto));
}
}
24 changes: 0 additions & 24 deletions src/main/java/controller/RacingApplication.java

This file was deleted.

66 changes: 0 additions & 66 deletions src/main/java/controller/RacingGame.java

This file was deleted.

7 changes: 0 additions & 7 deletions src/main/java/controller/StringOutOfBoundsException.java

This file was deleted.

39 changes: 39 additions & 0 deletions src/main/java/lotto/Lotto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package lotto;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Lotto {

private static final int LOTTO_NUMBER_COUNT = 6;

private List<LottoNumber> lottoNumbers;

public Lotto(List<LottoNumber> lottoNumbers) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

원하지 않는 LottoNumbers가 들어오면 예외를 발생시켜서 객체 자체가 만들어지지도 않게끔 Lotto클래스의 생성자에 유효성검사 메소드를 두었습니다.
또한 객체 생성시 동시에 lottoNumbers가 정렬이 될 수 있도록 정렬 메소드도 생성자에 두었습니다.
정렬 메소드 관련해서 어디에 위치시킬까 많은 생각을 해보았지만 Lotto클래스의 생성자자체에서 LottoNumbers에 관한 정렬 책임을 가지는게 가장 이상적이다고 생각되어서 정렬 메소드도 생성자에 위치하였습니다.
나중에 다른 요구사항이 들어와도 lottoNumbers는 중복되지 않고 정렬도 필요하다고 생각해서 생성자에 많은 로직은 좋지 않지만 그럼에도 위치시켰습니다.

validateSize(lottoNumbers);
validateDuplication(lottoNumbers);
this.lottoNumbers = lottoNumbers;
}

private void validateSize(List<LottoNumber> lottoNumbers) {
if (lottoNumbers.size() != LOTTO_NUMBER_COUNT) {
throw new IllegalArgumentException("로또 번호는 6개로 이루어져야 합니다.");
}
}

private void validateDuplication(List<LottoNumber> lottoNumbers) {
Set<Integer> integers = new HashSet<>(lottoNumbers.stream()
.map(LottoNumber::getNumber)
.collect(Collectors.toList()));
if (integers.size() != LOTTO_NUMBER_COUNT) {
throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다.");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

애초에 set 을 사용했으면 불필요한 변환과 검증작업이 필요 없어지지 않을까요?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set을 사용하면 불필요한 변환과 검증 작업이 없어진다기 보다는
Lotto 클래스의 불필요한 변환과 검증작업이 User에게서 입력을 받는 단의 근처(Converter, Application)로 옮겨 지겠네요. (1,2,3,4,5,6,6과 1,2,3,4,5,6 입력이 Set에 들어가면 동일해지기 때문에 무조건 Set으로 변환하기전과 후에 Set의 Size를 검사해야한다.)

그렇다면 Lotto클래스보다 Converter나 Application에서 유효성검사를 진행하는게 보다 더 낫나요??
(저는 개인적으로 큰 차이는 없다고 생각합니다. 그치만 초보의 생각으로써 왠지 Lotto 클래스에서 유효성 검사를 하고 예외를 발생하는게 좀 더 맞다는 느낌적인 느낌이..(자바 왕초보 생각))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음.. 필드로 가지고 있는 lottoNumbers 를 Set 으로 구현하는 것에 대한 이야기였는데
말씀해주신 내용을 잘 이해하지 못했습니다. 혹시 추가설명 가능하실까요

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음... 만약
User에게서 1,2,3,4,5,6,6와 같은 입력이 주어질 경우

이를 바로 Set으로 변환한다면 1,2,3,4,5,6 요소를 가진 Set이 되버립니다!!
하지만 1,2,3,4,5,6,6이라는 입력값 자체가 틀리기 때문에 저희 어플리케이션은 예외를 발생해야만 합니다.

그렇다면 lottoNumbers를 Set으로 변환하기전 List또는 Array로 변환해서 중복검사와 사이즈검사를 수행해야되기때문에 변환과 검증작업이 무조건 필요하고 결국에는 Lotto클래스에서 LottoMachine클래스로 변환과 검증 작업이 옮겨진다고 생각했습니다!!

그래서 LottoMachine에서 검증된 데이터에 대해서만 Lotto객체를 무조건 생성할 것인가??
아니면 Lotto객체 자신이 데이터를 검증해서 검증된 데이터에만 Lotto객체를 생성할것인가?
라는 문제로 좁혀지는것 같은데 저는 왠지 LottoMachine에서 변환과 검증이 있기 보다는 Lotto에서 변환과 검증이 존재했으면 좋겠다는 생각이여서 말씀드렸씁니다!!

}

public List<LottoNumber> getLottoNumbers() {
return lottoNumbers;
}

}
70 changes: 70 additions & 0 deletions src/main/java/lotto/LottoGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package lotto;

import java.util.*;

public class LottoGame {

private static final int LOTTO_PRICE = 1000;

private int autoLottoCount;
private int manualLottoCount;
private TargetLottos targetLottos;

public LottoGame(int money, int manualLottoCount) {
this.manualLottoCount = manualLottoCount;
this.autoLottoCount = money / LOTTO_PRICE - manualLottoCount;
}

public TargetLottos getTargetLottos() {
return targetLottos;
}

public int getManualLottoCount() {
return manualLottoCount;
}

public int getAutoLottoCount() {
return autoLottoCount;
}

public void registerTargetLottos(TargetLottos targetLottos) {
this.targetLottos = targetLottos;
}

public LottoResult createResult(WinningLotto winningLotto) {
LottoResult lottoResult = new LottoResult((autoLottoCount + manualLottoCount) * LOTTO_PRICE);
for (Lotto lotto : targetLottos.getLottos()) {
checkLotto(lotto, lottoResult.getLottoRankResults(), winningLotto);
}
return lottoResult;
}

private void checkLotto(Lotto lotto, List<LottoRankResult> lottoRankResults, WinningLotto winningLotto) {
int countOfMatch = 0;
for (LottoNumber lottoNumber : winningLotto.getLotto().getLottoNumbers()) {
countOfMatch += checkNumberMatch(lotto, lottoNumber.getNumber());
}
boolean matchBonus = isBonusMatch(lotto, winningLotto.getBonusNumber());
for (LottoRankResult lottoRankResult : lottoRankResults) {
lottoRankResult.increaseCount(Rank.valueOf(countOfMatch, matchBonus));
}
}

private int checkNumberMatch(Lotto lotto, int number) {
for (int index = 0; index < lotto.getLottoNumbers().size(); index++) {
if (lotto.getLottoNumbers().get(index).getNumber() == number) {
return 1;
}
}
return 0;
}

private boolean isBonusMatch(Lotto lotto, int bonusNumber) {
for (int index = 0; index < lotto.getLottoNumbers().size(); index++) {
if (lotto.getLottoNumbers().get(index).getNumber() == bonusNumber) {
return true;
}
}
return false;
}
}
54 changes: 54 additions & 0 deletions src/main/java/lotto/LottoMachine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package lotto;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class LottoMachine {

private static final int LOTTO_SIZE = 6;
private static final int MIN_LOTTO_NUMBER = 1;
private static final int MAX_LOTTO_NUMBER = 45;

private List<Integer> integers;

public LottoMachine() {
integers = new ArrayList<>();
for (int number = MIN_LOTTO_NUMBER; number <= MAX_LOTTO_NUMBER; number++) {
integers.add(number);
}
}

public List<Lotto> createAutoLottos(int count) {
List<Lotto> lottos = new ArrayList<>();
for (int iteration = 0; iteration < count; iteration++) {
lottos.add(new Lotto(createLottoNumbers()));
}
return lottos;
}

public List<Lotto> createManualLottos(List<String> strings) {
List<Lotto> lottos = new ArrayList<>();
for (String string : strings) {
lottos.add(createManualLotto(string));
}
return lottos;
}

public Lotto createManualLotto(String string) {
return new Lotto(Arrays.stream(string.split(","))
.map(String::trim)
.map(Integer::new)
.map(LottoNumber::new)
.collect(Collectors.toList()));
}

private List<LottoNumber> createLottoNumbers() {
Collections.shuffle(integers);
return integers.subList(0, LOTTO_SIZE).stream()
.map(LottoNumber::new)
.collect(Collectors.toList());
}
}
26 changes: 26 additions & 0 deletions src/main/java/lotto/LottoNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package lotto;

public class LottoNumber {


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

불필요한 공백

private static final int MAX_LOTTO_NUMBER = 45;
private static final int MIN_LOTTO_NUMBER = 1;

private int number;

public LottoNumber(int number) {
validateRange(number);
this.number = number;
}

private void validateRange(int number) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로또 번호 자체는 1이상 45이하의 자연수 이기 때문에 조건에 맞지 않는 인자가 들어오면 객체 자체를 생성조차 하지 못하게끔 만드는 메서드이다.

if (number > MAX_LOTTO_NUMBER || number < MIN_LOTTO_NUMBER) {
throw new IllegalArgumentException("로또 번호는 1이상 45이하의 자연수만 가능합니다.");
}
}

public int getNumber() {
return number;
}

}
30 changes: 30 additions & 0 deletions src/main/java/lotto/LottoRankResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package lotto;

public class LottoRankResult {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rank 하나가 저장되고 LottoGame의 결과로써 해당 Rank가 몇개 나왔는지 count또한 저장될 수있게끔 하는 메소드이다.


Rank rank;
int count;

public LottoRankResult(Rank rank) {
this.rank = rank;
this.count = 0;
}

public Rank getRank() {
return rank;
}

public int getCount() {
return count;
}

public void increaseCount(Rank rank) {
if (this.rank == rank) {
count++;
}
}

public int getWinningMoney() {
return rank.getWinningMoney() * count;
}
}
31 changes: 31 additions & 0 deletions src/main/java/lotto/LottoResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package lotto;

import java.util.ArrayList;
import java.util.List;

public class LottoResult {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rank enum의 모든 Rank와 갯수가 저장되어 있는 List lottoRankResults와 RateOfProfit을 산출할 수 있는 purchaseMoney를 가진 클래스이다. 이 객체를 통해서 LottoGame은 View에게 잘 가공된 데이터를 넘겨 줄수 있다.
왠지 느낌이 이런걸 DTO라고 할 것 같다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DTO는 아닙니다.
DTO 는 데이터의 역할만해서 getter setter 밖에 없습니다.
DTO 를 의도하신거면 비즈니스 로직을 다른 곳에 위임해보는 게 어떨까요


private List<LottoRankResult> lottoRankResults;
private int money;

public LottoResult(int money) {
this.money = money;
lottoRankResults = new ArrayList<>();
for (int index = 0; index < Rank.values().length; index++) {
lottoRankResults.add(new LottoRankResult(Rank.values()[index]));
}
}

public List<LottoRankResult> getLottoRankResults() {
return lottoRankResults;
}

public double createRateOfProfit() {
int profit = 0;
for (LottoRankResult lottoRankResult : lottoRankResults) {
profit += lottoRankResult.getWinningMoney();
}
return (double) profit / money;
}

}
Loading