private HashMap<Rank, Integer> resultRankMap = new HashMap<>();
private Map<Rank, Integer> resultRankMap = new HashMap<>();
이펙티브 자바 아이템 64. 객체는 인터페이스를 사용해 참조하라를 참고해주세요~
다른 부분도(ex. ArrayList -> List)도 같이 확인해주세요 :)
수정완료!
if (countOfMatch == 6) {
return FIRST;
}
if (countOfMatch == 5 && matchBonus) {
return SECOND;
}
if (countOfMatch == 5 && !matchBonus) {
return THIRD;
}
if (countOfMatch == 4) {
return FOURTH;
}
if (countOfMatch == 3) {
return FIFTH;
}
하드코딩을 하지 않고 Rank의 값을 활용해보면 어떨까요!?
아래와 같이 수정.
public static Rank valueOf(int countOfMatch, boolean matchBonus) {
if (countOfMatch == Rank.FIRST.getCountOfMatch()) {
return FIRST;
}
if (countOfMatch == Rank.SECOND.getCountOfMatch() && matchBonus) {
return SECOND;
}
if (countOfMatch == Rank.THIRD.getCountOfMatch() && !matchBonus) {
return THIRD;
}
if (countOfMatch == Rank.FOURTH.getCountOfMatch()) {
return FOURTH;
}
if (countOfMatch == Rank.FIFTH.getCountOfMatch()) {
return FIFTH;
}
return MISS;
}
int numOfLotto = inputView.requestInput();
ArrayList<ArrayList<Integer>> issuedLottoList = customer.buyLotto(numOfLotto);
resultView.printIssuedLottoList(issuedLottoList);
ArrayList<Integer> winningLottoNumberList = winningLottoNumbers.checkValidInput(inputView.requestWinningLottoNumber());
int bonusBallNumber = inputView.requestBonusBall();
전체적으로 객체들을 원시값과 문제열로 포장하고 일급 콜렉션을 사용해보면 어떨까요!?
규칙 3: 모든 원시값과 문자열을 포장한다.
규칙 8: 일급 콜렉션을 쓴다.
아래와 같이 수정 완료
LottoInfo lottoInfo = new LottoInfo(inputView.requestInput());
LottoTicket lottoTicket = new LottoTicket(customer.buyLotto(lottoInfo.getCount()));
resultView.printNumOfLotto(lottoInfo.getCount());
resultView.printIssuedLottoList(lottoTicket.getBundle());
WinningLotto winningLotto = new WinningLotto(inputView.requestWinningLottoNumber());
BonusBall bonusBall = new BonusBall(inputView.requestBonusBall(), winningLotto.getNumbers());
if (issuedLotto.contains(bonusNumber)) {
return true;
}
return false;
아래와 같이 수정
return issuedLotto.contains(bonusNumber);
public ArrayList<Integer> getRandomNumberLotto() {
해당 부분에 랜덤한 요소가 존재한다면 해당 메서드는 어떻게 테스트할 수 있을까요?
랜덤한 값에 대한 테스트는 불가능하다고 생각하였습니다.
그래서 LottoMachineTest 부분에서 랜덤한 값 자체를 테스트 하기 보다는
값의 중복이 존재하지 않는가에 초점을 맞추어 테스트를 진행해보았습니다!
전체 코드
package step3.domain;
import java.util.List;
public class BonusBall {
private int number;
public BonusBall(int number,List<Integer> winningLottoNumberList) {
compareWithWinningLottoNumbers(number, winningLottoNumberList);
this.number = number;
}
public int getNumber() {
return number;
}
public void compareWithWinningLottoNumbers(int bonusBallNumber, List<Integer> winningLottoNumberList) {
if (winningLottoNumberList.contains(bonusBallNumber)) {
throw new IllegalArgumentException("보너스 볼의 번호는 당첨 번호와 일치할 수 없습니다.");
}
}
}
package step3.domain;
import step3.util.Rank;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Customer {
private static int resultPrize = 0;
private static final LottoMachine lottoMachine = new LottoMachine();
private HashMap<Rank, Integer> resultRankMap = new HashMap<>();
public Customer() {
preareRankMap();
}
private void preareRankMap() {
for (Rank rank: Rank.values()) {
resultRankMap.put(rank,0);
}
}
public List<List<Integer>> buyLotto(int numOfLotto) {
return lottoMachine.issue(numOfLotto);
}
public void compareWinningLottoNumbersAndIssuedLottoList(List<Integer> winningLottoNumberList, List<List<Integer>> issuedLottoList, int bonusNumber) {
int numOfLotto = issuedLottoList.size();
for (int i = 0; i < numOfLotto; i++) {
System.out.println(issuedLottoList.get(i));
getMatchedNumber(issuedLottoList.get(i), winningLottoNumberList, bonusNumber);
}
}
public int getResultPrize() {
return resultPrize;
}
public Map<Rank, Integer> getResultRankMap() {
return resultRankMap;
}
public void getMatchedNumber(List<Integer> issuedLotto, List<Integer> winningLottoNumberList, int bonusNumber) {
boolean isMatched = false;
isMatched = compareWithBonusBall(issuedLotto, bonusNumber);
issuedLotto.retainAll(winningLottoNumberList);
int matchedNumber = issuedLotto.size();
Rank rank = Rank.valueOf(matchedNumber, isMatched);
resultRankMap.put(rank,resultRankMap.get(rank)+1);
resultPrize += rank.getWinningMoney();
}
private boolean compareWithBonusBall(List<Integer> issuedLotto, int bonusNumber) {
return issuedLotto.contains(bonusNumber);
}
}
package step3.domain;
public class Lotto {
private static final String LOTTO_NUMBER_RANGE_ERROR_MESSAGE = "로또 당첨번호는 1과 45 사이의 정수이어야 합니다.";
private static final int MIN_OF_LOTTO_NUMBER = 1;
private static final int MAX_OF_LOTTO_NUMBER = 45;
private final int number;
public Lotto(int number) {
checkRange(number);
this.number = number;
}
private void checkRange(int number) {
if (number > MAX_OF_LOTTO_NUMBER || number < MIN_OF_LOTTO_NUMBER) {
throw new IllegalArgumentException(LOTTO_NUMBER_RANGE_ERROR_MESSAGE);
}
}
public int getNumber() {
return number;
}
}
package step3.domain;
public class LottoInfo {
private static final int chargeOfLotto = 1000;
private int charge;
private int count;
public LottoInfo(int charge) {
calculateNumOfLotto(charge);
this.charge = charge;
}
private void calculateNumOfLotto(int charge) {
this.count = charge/chargeOfLotto;
}
public int getCharge() {
return charge;
}
public int getCount() {
return count;
}
}
package step3.domain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LottoMachine {
private List<List<Integer>> lottoList = new ArrayList<>();
static final private List<Integer> lottoNumberCandidateList = new ArrayList<>();
public LottoMachine() {
getLottoNumberCandidateArray();
}
public List<List<Integer>> issue(int numOfLotto) {
for (int i = 0; i < numOfLotto; i++) {
lottoList.add(getRandomNumberLotto());
}
return lottoList;
}
public List<Integer> getRandomNumberLotto() {
List<Integer> lotto = new ArrayList<>();
Collections.shuffle(lottoNumberCandidateList);
for (int i = 0; i < 6; i++) {
lotto.add(new Lotto(lottoNumberCandidateList.get(i)).getNumber());
}
return lotto;
}
private void getLottoNumberCandidateArray() {
for (int i = 1; i <= 45; i++) {
lottoNumberCandidateList.add(i);
}
}
}
package step3.domain;
import java.util.List;
public class LottoTicket {
private List<List<Integer>> bundle;
public LottoTicket(List<List<Integer>> bundle) {
this.bundle = bundle;
}
public List<List<Integer>> getBundle() {
return bundle;
}
}
package step3.domain;
import java.util.ArrayList;
import java.util.List;
public class WinningLotto {
private static final int numOfWinningLottoNumber = 6;
private static final String winningLottoNumberErrorMessage = "당첨 번호는 6개로 구성되어야 하며, ', ' 을 이용하여 구분하고 있습니다.";
private List<Integer> numbers;
public WinningLotto(String stringNumbers) {
this.numbers = checkValidInput(stringNumbers);
}
public List<Integer> getNumbers() {
return numbers;
}
public List<Integer> checkValidInput(String s) {
String[] winningLottoNumberStringList = s.split(", ");
if (winningLottoNumberStringList.length != numOfWinningLottoNumber) {
throw new IllegalArgumentException(winningLottoNumberErrorMessage);
}
return makeIntList(winningLottoNumberStringList);
}
private List<Integer> makeIntList(String[] winningLottoNumberStringList) {
List<Integer> winningLottoNumberIntList = new ArrayList<>();
for (String stringLottoNumber : winningLottoNumberStringList) {
winningLottoNumberIntList.add(Integer.parseInt(stringLottoNumber));
}
return winningLottoNumberIntList;
}
}
package step3.util;
public enum Rank {
FIRST(6, 2_000_000_000),
SECOND(5, 30_000_000),
THIRD(5, 1_500_000),
FOURTH(4, 50_000),
FIFTH(3, 5_000),
MISS(0, 0);
private int countOfMatch;
private int winningMoney;
private Rank(int countOfMatch, int winningMoney) {
this.countOfMatch = countOfMatch;
this.winningMoney = winningMoney;
}
public int getCountOfMatch() {
return countOfMatch;
}
public int getWinningMoney() {
return winningMoney;
}
public static Rank valueOf(int countOfMatch, boolean matchBonus) {
if (countOfMatch == Rank.FIRST.getCountOfMatch()) {
return FIRST;
}
if (countOfMatch == Rank.SECOND.getCountOfMatch() && matchBonus) {
return SECOND;
}
if (countOfMatch == Rank.THIRD.getCountOfMatch() && !matchBonus) {
return THIRD;
}
if (countOfMatch == Rank.FOURTH.getCountOfMatch()) {
return FOURTH;
}
if (countOfMatch == Rank.FIFTH.getCountOfMatch()) {
return FIFTH;
}
return MISS;
}
}
package step3.view;
import java.util.Scanner;
public class InputView {
static final String INPUT_MESSAGE = "구입 금액을 입력해주세요.";
static final String INPUT_LAST_LOTTO_NUMBER = "지난 주 당첨 번호를 입력해 주세요.";
static Scanner sc = new Scanner(System.in);
public int requestInput() {
System.out.println(INPUT_MESSAGE);
int charge = sc.nextInt();
sc.nextLine();
return charge;
}
public String requestWinningLottoNumber() {
System.out.println(INPUT_LAST_LOTTO_NUMBER);
String lastWinningLottoNum = sc.nextLine();
return lastWinningLottoNum;
}
public Integer requestBonusBall() {
System.out.println("보너스 볼을 입력해 주세요.");
return sc.nextInt();
}
}
package step3.view;
import step3.util.Rank;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ResultView {
private static final Double chargeOfLotto = 1000.0;
static final String INPUT_INFO_MESSAGE = "개를 구매했습니다.";
public void printMatchedLottoRecord(Map<Rank, Integer> matchedLottoRecordArray) {
System.out.println("당첨 통계");
System.out.println("-------");
System.out.printf("%s개 일치 (%s)- %s개\n",Rank.FIFTH.getCountOfMatch(),Rank.FIFTH.getWinningMoney(),matchedLottoRecordArray.get(Rank.FIFTH));
System.out.printf("%s개 일치 (%s)- %s개\n",Rank.FOURTH.getCountOfMatch(),Rank.FOURTH.getWinningMoney(),matchedLottoRecordArray.get(Rank.FOURTH));
System.out.printf("%s개 일치 (%s)- %s개\n",Rank.THIRD.getCountOfMatch(),Rank.THIRD.getWinningMoney(),matchedLottoRecordArray.get(Rank.THIRD));
System.out.printf("%s개 일치 (%s)- %s개\n",Rank.SECOND.getCountOfMatch(),Rank.SECOND.getWinningMoney(),matchedLottoRecordArray.get(Rank.SECOND));
System.out.printf("%s개 일치 (%s)- %s개\n",Rank.FIRST.getCountOfMatch(),Rank.FIRST.getWinningMoney(),matchedLottoRecordArray.get(Rank.FIRST));
}
private void printResultMessage(double yield) {
if (yield < 1) {
System.out.printf("총 수익률은 %s입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임)",yield);
return;
}
if (yield >= 1) {
System.out.printf("총 수익률은 %s입니다.(기준이 1이기 때문에 결과적으로 이익이라는 의미임)",yield);
return;
}
}
public void printNumOfLotto(int numOfLotto) {
System.out.println(numOfLotto+INPUT_INFO_MESSAGE);
}
public void printIssuedLottoList(List<List<Integer>> issuedLottolist) {
issuedLottolist.stream()
.forEach(issuedLotto -> System.out.println(issuedLotto));
}
public void printResultPrice(int resultPrice, int numOfLotto) {
Double totalSpendMoney = numOfLotto * chargeOfLotto;
Double yeild = resultPrice / totalSpendMoney;
printResultMessage(yeild);
}
}
package step3;
import step3.domain.*;
import step3.view.InputView;
import step3.view.ResultView;
import java.util.List;
public class LottoApp {
public static void main(String[] args) {
InputView inputView = new InputView();
ResultView resultView = new ResultView();
Customer customer = new Customer();
LottoInfo lottoInfo = new LottoInfo(inputView.requestInput());
LottoTicket lottoTicket = new LottoTicket(customer.buyLotto(lottoInfo.getCount()));
resultView.printNumOfLotto(lottoInfo.getCount());
resultView.printIssuedLottoList(lottoTicket.getBundle());
WinningLotto winningLotto = new WinningLotto(inputView.requestWinningLottoNumber());
BonusBall bonusBall = new BonusBall(inputView.requestBonusBall(), winningLotto.getNumbers());
customer.compareWinningLottoNumbersAndIssuedLottoList(winningLotto.getNumbers(), lottoTicket.getBundle(), bonusBall.getNumber());
resultView.printMatchedLottoRecord(customer.getResultRankMap());
resultView.printResultPrice(customer.getResultPrize(), lottoInfo.getCount());
}
}
'강의 > TDD, Clean Code with Java 12기' 카테고리의 다른 글
[로또] step4 - 로또(수동) - 29일차 (0) | 2021.08.17 |
---|---|
[로또] step4 - 로또(수동) - 29일차 (step3 피드백 및 피드백 반영) (0) | 2021.08.17 |
[로또] step3 - 로또(2등) - 26일차 (0) | 2021.08.14 |
[로또] step2 - 로또(자동) - 최종 피드백 (22일차) (0) | 2021.08.10 |
[로또] step2 - 로또(자동) - 피드백 및 피드백 반영(21일차) (0) | 2021.08.09 |