Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2c8a53d
docs README.md
oliviarla May 22, 2022
72369e7
feat: inputView, resultView
oliviarla May 22, 2022
9ee8c96
docs: README.md 수정
oliviarla May 22, 2022
44464e3
test: BaseballTest 구현
oliviarla May 22, 2022
bf277a4
feat: main 클래스 추가
oliviarla May 22, 2022
2cfa9fb
feat: Baseball 구현 완료
oliviarla May 22, 2022
15c6b05
docs(baseball): README.md 기능 목록 다시 작성
oliviarla May 26, 2022
01dd974
feat(baseball): InputView 구현
oliviarla May 26, 2022
8024763
test(baseball): InputView test
oliviarla May 26, 2022
eb92b3d
feat(baseball): 엔티티 클래스 구현
oliviarla May 26, 2022
a9185d4
docs(baseball): update README.md
oliviarla May 26, 2022
5f8046b
feat(baseball): OutputView 구현
oliviarla May 27, 2022
b294dca
test(baseball): OutputViewTest 구현
oliviarla May 27, 2022
19461c4
feat(baseball): OutputView 구현
oliviarla May 27, 2022
be73fe2
feat(baseball): RandomNumGenerator 구현
oliviarla May 27, 2022
8829032
test(baseball): RandomNumGenerator 테스트
oliviarla May 27, 2022
967f871
docs(baseball): RandomNumGenerator 구현
oliviarla May 27, 2022
a1bb02d
refactor(baseball): Ball 객체의 혼동 방지 위해 Baseball로 이름 변경 + Baseball에서 순서…
oliviarla May 27, 2022
f13c04b
feat(baseball): BaseballService 구현
oliviarla May 27, 2022
01e34cb
docs(baseball): BaseballService 구현
oliviarla May 27, 2022
5b260ec
test(baseball): BaseballService 테스트 구현
oliviarla May 27, 2022
6c2a62c
feat(baseball): 전체 애플리케이션 구현 완료
oliviarla May 27, 2022
65d6ef8
refactor(baseball): 전체 애플리케이션 수정 및 구현 완료
oliviarla May 27, 2022
bbf4efa
refactor(baseball): 사용자 입력 숫자 개수 예외처리
oliviarla May 27, 2022
f7a0fa7
refactor(baseball): 코드 리뷰에 따라 불변 객체로 수정, Ball 엔티티 추가, 서비스 로직 변경 완료
oliviarla Jun 4, 2022
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
24 changes: 12 additions & 12 deletions src/main/java/baseball/application.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
package baseball;

import baseball.domain.Ball;
import baseball.domain.Baseball;
import baseball.domain.BaseballStatus;
import baseball.service.BaseballService;
import baseball.service.RandomNumGenerator;
import baseball.service.RandomBallGenerator;
import baseball.view.InputView;
import baseball.view.OutputView;

import java.util.stream.Collectors;

public class application {
public static void main(String[] args) throws Exception {
InputView inputView = new InputView();
OutputView outputView = new OutputView();
RandomNumGenerator randomNumGenerator = new RandomNumGenerator();
RandomBallGenerator randomBallGenerator = new RandomBallGenerator();
BaseballService baseballService = new BaseballService();

while(true){
Baseball randomBaseball = new Baseball(randomNumGenerator.makeNum());
BaseballStatus baseballStatus = new BaseballStatus();

while(!outputView.exitGame(baseballStatus)){
do {
Baseball randomBaseball = new Baseball(randomBallGenerator.makeNum());
BaseballStatus baseballStatus;
do {
Baseball userBaseball = inputView.inputBall();
baseballStatus = baseballService.compare(userBaseball, randomBaseball);
outputView.printBaseballStatus(baseballStatus);
}
if(!inputView.resumeGame()){
break;
}
}
} while (!outputView.exitGame(baseballStatus));

}while(inputView.resumeGame());
}
}
13 changes: 13 additions & 0 deletions src/main/java/baseball/domain/Ball.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package baseball.domain;

public class Ball {

Choose a reason for hiding this comment

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

Ball 객체를 구현하셨군요!! 👍
해당 Ball 객체를 구현하면서 들어가게 되는 숫자의 유효성 검사를 해당 Ball에서 구현하는건 어떨까요?
즉, InputView에서 Balseball에 들어가는 숫자들의 유효성 검사를 Ball 구현체에서 진행하게 된다면 InputView와 그 외 객체들의 결합력을 낮추고 Ball이라는 구현체의 응집도를 높일 수 있을 것 같아요!

Choose a reason for hiding this comment

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

추가적으로 Ball의 생애주기와 Baseball의 생애주기가 같은지에 대해서도 고민해보시는 걸 추천 드립니다! 힌트를 드리자면, 엔티티와 값 객체의 차이가 되겠군요! 👍

private final int number;

public Ball(final int number) {
this.number = number;
}

public int getNumber() {
return number;
}
}
25 changes: 19 additions & 6 deletions src/main/java/baseball/domain/Baseball.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
package baseball.domain;

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

public class Baseball {

Choose a reason for hiding this comment

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

InputView에서 Balseball의 리스르 크기 검사를 Baseball 구현체에서 진행하는건 어떨까요? ☺️

List<Integer> baseballs;
private final List<Ball> baseballs;

public Baseball(List<Integer> balls) {
this.baseballs = balls;
public Baseball(final List<Ball> ballList){
this.baseballs= new ArrayList<>(ballList);
isDistinct();
}

public List<Integer> getBaseballs() {
return baseballs;
public List<Ball> getBaseballs() {
return Collections.unmodifiableList(baseballs);
Copy link

@this-is-spear this-is-spear Jun 4, 2022

Choose a reason for hiding this comment

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

리스트를 조회할 때, unmodifiableList 메서드를 사용해 수정할 수 없도록 구현하셨군요!
좋은 방법입니다. 👍
하지만 unmodifiableList 메서드만 사용해서 리스트를 호출하게 되면 정말 수정이 불가능할까요? ☺️
이 부분에 대해서는 수정이 필요하진 않지만, 생각해보는걸 추천드려요! 👍

}
}

public void isDistinct(){

Choose a reason for hiding this comment

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

해당 메서드의 depth가 4칸 정도 되는 것 같아요! depth를 낮추는 방법이 있을까요? ☺️

for(int i=0;i<this.baseballs.size();i++){
for(int j=0;j<i;j++){
if(this.baseballs.get(i).getNumber() == this.baseballs.get(j).getNumber()){
throw new RuntimeException("중복된 값이 있습니다.");
}
}
}
}
}
23 changes: 13 additions & 10 deletions src/main/java/baseball/domain/BaseballStatus.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
package baseball.domain;

public class BaseballStatus {
int ball;
int strike;
private final int ball;
private final int strike;

public BaseballStatus(int ball, int strike) throws Exception {
this.ball = ball;
this.strike = strike;
this.isValid();

Choose a reason for hiding this comment

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

해당 유효성 검사를 제일 아래에 선언하게 되면 실패하는 상황에서도 필요없는 명령어가 실행이 되는 것 같아요!

}
private void isValid() throws Exception{
if (!this.existsBall() && !this.existsStrike() && !this.nothing())
throw new Exception("결과를 반환할 수 없습니다");
}


public int getBall() {
return ball;
Expand All @@ -12,14 +23,6 @@ public int getStrike() {
return strike;
}

public void setBall(int ball) {
this.ball = ball;
}

public void setStrike(int strike) {
this.strike = strike;
}

@Override
public String toString() {
return "BaseballStatus{" +
Expand Down
25 changes: 11 additions & 14 deletions src/main/java/baseball/service/BaseballService.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
package baseball.service;

import baseball.domain.Action;
import baseball.domain.Ball;
import baseball.domain.Baseball;
import baseball.domain.BaseballStatus;

public class BaseballService {
public boolean isStrike(int userNum, int randomNum) {
return userNum == randomNum;
public boolean isStrike(Ball userBall, Ball randomBall) {
return userBall.getNumber() == randomBall.getNumber();
}

public boolean isBall(int userNum, int userIdx, Baseball randomBall) {
if (!isStrike(userNum, randomBall.getBaseballs().get(userIdx))) {
return randomBall.getBaseballs().contains(userNum);
}
return false;
public boolean isBall(Ball userBall, Baseball randomBall) {
return randomBall.getBaseballs().stream().anyMatch(ball -> ball.getNumber()==userBall.getNumber());
}

public BaseballStatus compare(Baseball userBall, Baseball randomBall) {
int strike = 0, ball = 0;
public BaseballStatus compare(Baseball userBall, Baseball randomBall) throws Exception {
int strike = 0;
int ball = 0;
for (int i = 0; i < userBall.getBaseballs().size(); i++) {
if (isStrike(userBall.getBaseballs().get(i), randomBall.getBaseballs().get(i))) {
strike++;
continue;
}
if (isBall(userBall.getBaseballs().get(i), i, randomBall)) {
if (isBall(userBall.getBaseballs().get(i), randomBall)) {
ball++;
}
}
BaseballStatus baseballStatus = new BaseballStatus();
baseballStatus.setBall(ball);
baseballStatus.setStrike(strike);
return baseballStatus;
return new BaseballStatus(ball, strike);
}
}
27 changes: 27 additions & 0 deletions src/main/java/baseball/service/RandomBallGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package baseball.service;

import baseball.domain.Ball;

import java.util.*;

public class RandomBallGenerator {
static int MAX_SIZE = 3;
static int MAX_NUM = 9;
Comment on lines +8 to +9

Choose a reason for hiding this comment

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

static을 사용해서 변수를 공유할 수 있게 됐군요!
하지만 값이 변경될 수 있기 때문에 이슈가 발생할 수 있는 코드입니다. 😱
final 변수를 생성할 때에는 static은 선택적이지만, static일 때에는 final은 필수일 것 같아요! ☺️

그리고 추가적으로 접근 제어자를 선언하지 않는다면 기본적으로 설정되는 접근 제어자가 무엇일지 고민해봐도 좋을 것 같습니다. ☺️ 물론 생략은 좋지 않아요 👍


public List<Ball> makeNum(){
Random random = new Random();
Set<Integer> set = new HashSet<>();

while(set.size()<MAX_SIZE){
int num = random.nextInt(MAX_NUM)+1;
set.add(num);
}

List<Ball> balls = new ArrayList<>();
for(int e: set){
Ball ball = new Ball(e);
balls.add(ball);
}
return balls;
}
}
16 changes: 0 additions & 16 deletions src/main/java/baseball/service/RandomNumGenerator.java

This file was deleted.

30 changes: 20 additions & 10 deletions src/main/java/baseball/view/InputView.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
package baseball.view;

import baseball.domain.Ball;
import baseball.domain.Baseball;

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.*;
import java.util.stream.Collectors;


public class InputView {
public Baseball inputBall() throws Exception {
static int MAX_SIZE = 3;

private void isValidInput(List<Ball> ballList) throws RuntimeException{
if(ballList.size()!=MAX_SIZE){
Copy link

@this-is-spear this-is-spear Jun 4, 2022

Choose a reason for hiding this comment

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

줄 정렬이 필요해보이는 코드이군요 ☺️
그 외적인 코드들도 줄 정렬이 필요한 부분들이 많았습니다. 프로젝트를 전체 줄 정렬을 해주는 기능을 인텔리제이에서 제공해주고 있으니 한 번 사용해보시는 걸 추천드려요!

throw new RuntimeException("3자리 숫자여야 합니다.");
}
if(!ballList.stream().allMatch(ball -> ball.getNumber()>0 && ball.getNumber()<=9)){
throw new RuntimeException("범위를 벗어납니다.");
}
}

public Baseball inputBall() throws RuntimeException {
Scanner scanner = new Scanner(System.in);
System.out.print("숫자를 입력해 주세요 : ");
String input = scanner.next();
List<Integer> list = Arrays.stream(input.split("")).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList());
if(list.size()!=3){
throw new Exception("3자리 숫자여야 합니다.");
}

List<Ball> list = Arrays.stream(input.split("")).mapToInt(Integer::parseInt).mapToObj(Ball::new).collect(Collectors.toList());
isValidInput(list);
return new Baseball(list);
}

Expand All @@ -26,4 +34,6 @@ public boolean resumeGame() {
int input = scanner.nextInt();
return input == 1;
}
}


}
9 changes: 4 additions & 5 deletions src/main/java/baseball/view/OutputView.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
import baseball.domain.BaseballStatus;

public class OutputView {
public String outputBaseballStatus(BaseballStatus baseballStatus) throws Exception {
public String outputBaseballStatus(BaseballStatus baseballStatus) {
String result = "";
if (!baseballStatus.existsBall() && !baseballStatus.existsStrike() && !baseballStatus.nothing())
throw new Exception("결과를 반환할 수 없습니다");

if (baseballStatus.existsBall()) {
result += baseballStatus.getBall() + Action.볼.toString() + " ";
}
Expand All @@ -20,7 +19,7 @@ public String outputBaseballStatus(BaseballStatus baseballStatus) throws Excepti
return result;
}

public void printBaseballStatus(BaseballStatus baseballStatus) throws Exception {
public void printBaseballStatus(BaseballStatus baseballStatus) {
System.out.println(outputBaseballStatus(baseballStatus));
}

Expand All @@ -31,4 +30,4 @@ public boolean exitGame(BaseballStatus ballStatus) {
}
return false;
}
}
}
20 changes: 10 additions & 10 deletions src/test/java/baseball/service/BaseballServiceTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package baseball.service;

import baseball.domain.Ball;
import baseball.domain.Baseball;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -20,29 +21,28 @@ void setUp(){

@Test
void isStrikeTest(){
Baseball userBall = new Baseball(Arrays.asList(1,2,3));
Baseball randomBall = new Baseball(Arrays.asList(1,2,3));
Baseball userBall = new Baseball(Arrays.asList(new Ball(1),new Ball(2),new Ball(3)));
Baseball randomBall = new Baseball(Arrays.asList(new Ball(1),new Ball(2),new Ball(3)));
for(int i=0;i<3;i++){
assertThat(baseballService.isStrike(userBall.getBaseballs().get(i), randomBall.getBaseballs().get(i))).isTrue();
}
}

@Test
void isBallTest(){
Baseball userBall = new Baseball(Arrays.asList(1,3,2));
Baseball randomBall = new Baseball(Arrays.asList(2,1,3));
Baseball userBall = new Baseball(Arrays.asList(new Ball(1),new Ball(3),new Ball(2)));
Baseball randomBall = new Baseball(Arrays.asList(new Ball(2),new Ball(1),new Ball(3)));
for(int i=0;i<3;i++){
assertThat(baseballService.isBall(userBall.getBaseballs().get(i), i, randomBall)).isTrue();
assertThat(baseballService.isBall(userBall.getBaseballs().get(i), randomBall)).isTrue();
}
}

@ParameterizedTest
@CsvSource({"1,2,6,1,9,2,1,1", "3,7,5,7,3,9,2,0", "1,2,3,4,5,6,0,0", "3,4,8,3,4,2,0,2"})
void compareTest(int u1,int u2,int u3,int r1,int r2,int r3, int e1, int e2){
Baseball userBall = new Baseball(Arrays.asList(u1, u2, u3));
Baseball randomBall = new Baseball(Arrays.asList(r1, r2, r3));
void compareTest(int u1,int u2,int u3,int r1,int r2,int r3, int e1, int e2) throws Exception {
Baseball userBall = new Baseball(Arrays.asList(new Ball(u1),new Ball(u2),new Ball(u3)));
Baseball randomBall = new Baseball(Arrays.asList(new Ball(r1),new Ball(r2),new Ball(r3)));

assertThat(new int[]{baseballService.compare(userBall, randomBall).getBall(), baseballService.compare(userBall, randomBall).getStrike()}).isEqualTo(new int[]{e1, e2});
//assertThat().isEqualTo(ballStatus.getStrike());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package baseball.service;

import baseball.domain.Ball;
import baseball.domain.Baseball;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -9,18 +10,18 @@

import static org.assertj.core.api.Assertions.assertThat;

public class RandomNumTest {
RandomNumGenerator randomNumGenerator;
public class RandomBallTest {
RandomBallGenerator randomBallGenerator;

@BeforeEach
public void setUp() {
randomNumGenerator = new RandomNumGenerator();
randomBallGenerator = new RandomBallGenerator();
}

@Test
@DisplayName("3개의 서로다른 숫자가 생성되는지 확인하는 테스트입니다.")
public void makeNumTest() {
List<Integer> list = randomNumGenerator.makeNum();
List<Ball> list = randomBallGenerator.makeNum();

Baseball randomNum = new Baseball(list);
assertThat(randomNum.getBaseballs().size()).isEqualTo(3);
Expand All @@ -29,8 +30,8 @@ public void makeNumTest() {
@Test
@DisplayName("1부터 9 사이의 값인지 확인하는 테스트입니다.")
public void rangeTest() {
List<Integer> list = randomNumGenerator.makeNum();
List<Ball> list = randomBallGenerator.makeNum();

assertThat(list.stream().filter(integer -> integer >= 1 && integer <= 9).count()).isEqualTo(3);
assertThat(list.stream().filter(ball -> ball.getNumber() >= 1 && ball.getNumber() <= 9).count()).isEqualTo(3);
}
}
Loading