ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,78 @@
+package baseball.controller;
+
+import java.util.List;
+
+import baseball.model.ComputerInputData;
+import baseball.view.PlayerInputView;
+import baseball.model.CompareBallsModel;
+import baseball.service.BaseballGameService;
+import baseball.service.InvalidInputHandler;
+import baseball.service.MoreGameService;
+
+public class GameController {
+    
+    private PlayerInputView playerInputView;
+    private BaseballGameService baseballGameService;
+    private ComputerInputData computerInputData;
+    private CompareBallsModel compareBallsModel;
+    private InvalidInputHandler invalidInputHandler;
+    private MoreGameService moreGameService;
+
+    public GameController() {
+        this.playerInputView = new PlayerInputView();
+        this.baseballGameService = new BaseballGameService();
+        this.computerInputData = new ComputerInputData();
+        this.compareBallsModel = new CompareBallsModel();
+        this.invalidInputHandler = new InvalidInputHandler();
+        this.moreGameService = new MoreGameService();
+    }
+
+
+    public void gameFlow() {
+        boolean gameWon = false;
+
+        while (!gameWon) {
+            String input = playerInputView.getPlayerInput();
+
+            if (!baseballGameService.isValidInput(input)) {
+                invalidInputHandler.invalidInputPrint();
+            }
+
+            List<Integer> computerList = computerInputData.getComputerList();
+            int[] result = compareBallsModel.compareNumbers(input, computerList);
+
+            if (result[0] == 3) {
+                System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+                gameWon = true;
+                continue;
+            }
+
+            printGameResult(result);
+            }
+        if(moreGameService.more() == true) {
+            computerInputData = new ComputerInputData();
+            gameFlow();
+        }
+    }
+
+
+    private void printGameResult(int[] result) {
+        StringBuilder output = new StringBuilder();
+    
+        if (result[0] == 0 && result[1] == 0) {
+            System.out.println("낫싱");
+        }
+        
+        if (result[0] > 0) {
+            output.append(result[0]).append("스트라이크 ");
+        }
+        
+        if (result[1] > 0) {
+            output.append(result[1]).append("볼");
+        }
+        
+        if (output.length() > 0) {
+            System.out.println(output);
+        }
+    }
+}
\ No newline at end of file

리뷰: `result[0]`이 스트라이크 카운터이고 `result[1]`이 볼 카운트인 것을 `BaseballCompareModel` 클래스를 확인해야만 알 수 있는건가?
@@ -0,0 +1,78 @@
+package baseball.controller;
+
+import java.util.List;
+
+import baseball.model.ComputerInputData;
+import baseball.view.PlayerInputView;
+import baseball.model.CompareBallsModel;
+import baseball.service.BaseballGameService;
+import baseball.service.InvalidInputHandler;
+import baseball.service.MoreGameService;
+
+public class GameController {
+    
+    private PlayerInputView playerInputView;
+    private BaseballGameService baseballGameService;
+    private ComputerInputData computerInputData;
+    private CompareBallsModel compareBallsModel;
+    private InvalidInputHandler invalidInputHandler;
+    private MoreGameService moreGameService;
+
+    public GameController() {
+        this.playerInputView = new PlayerInputView();
+        this.baseballGameService = new BaseballGameService();
+        this.computerInputData = new ComputerInputData();
+        this.compareBallsModel = new CompareBallsModel();
+        this.invalidInputHandler = new InvalidInputHandler();
+        this.moreGameService = new MoreGameService();
+    }
+
+
+    public void gameFlow() {
+        boolean gameWon = false;
+
+        while (!gameWon) {
+            String input = playerInputView.getPlayerInput();
+
+            if (!baseballGameService.isValidInput(input)) {
+                invalidInputHandler.invalidInputPrint();
+            }
+
+            List<Integer> computerList = computerInputData.getComputerList();
+            int[] result = compareBallsModel.compareNumbers(input, computerList);
+
+            if (result[0] == 3) {
+                System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+                gameWon = true;
+                continue;
+            }
+
+            printGameResult(result);
+            }
+        if(moreGameService.more() == true) {
+            computerInputData = new ComputerInputData();
+            gameFlow();
+        }
+    }
+
+
+    private void printGameResult(int[] result) {
+        StringBuilder output = new StringBuilder();
+    
+        if (result[0] == 0 && result[1] == 0) {
+            System.out.println("낫싱");
+        }
+        
+        if (result[0] > 0) {
+            output.append(result[0]).append("스트라이크 ");
+        }
+        
+        if (result[1] > 0) {
+            output.append(result[1]).append("볼");
+        }
+        
+        if (output.length() > 0) {
+            System.out.println(output);
+        }
+    }
+}
\ No newline at end of file

리뷰: 왜 `BaseballCompareModel` 클래스만 인스턴스명이 달라?
@@ -0,0 +1,78 @@
+package baseball.controller;
+
+import java.util.List;
+
+import baseball.model.ComputerInputData;
+import baseball.view.PlayerInputView;
+import baseball.model.CompareBallsModel;
+import baseball.service.BaseballGameService;
+import baseball.service.InvalidInputHandler;
+import baseball.service.MoreGameService;
+
+public class GameController {
+    
+    private PlayerInputView playerInputView;
+    private BaseballGameService baseballGameService;
+    private ComputerInputData computerInputData;
+    private CompareBallsModel compareBallsModel;
+    private InvalidInputHandler invalidInputHandler;
+    private MoreGameService moreGameService;
+
+    public GameController() {
+        this.playerInputView = new PlayerInputView();
+        this.baseballGameService = new BaseballGameService();
+        this.computerInputData = new ComputerInputData();
+        this.compareBallsModel = new CompareBallsModel();
+        this.invalidInputHandler = new InvalidInputHandler();
+        this.moreGameService = new MoreGameService();
+    }
+
+
+    public void gameFlow() {
+        boolean gameWon = false;
+
+        while (!gameWon) {
+            String input = playerInputView.getPlayerInput();
+
+            if (!baseballGameService.isValidInput(input)) {
+                invalidInputHandler.invalidInputPrint();
+            }
+
+            List<Integer> computerList = computerInputData.getComputerList();
+            int[] result = compareBallsModel.compareNumbers(input, computerList);
+
+            if (result[0] == 3) {
+                System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+                gameWon = true;
+                continue;
+            }
+
+            printGameResult(result);
+            }
+        if(moreGameService.more() == true) {
+            computerInputData = new ComputerInputData();
+            gameFlow();
+        }
+    }
+
+
+    private void printGameResult(int[] result) {
+        StringBuilder output = new StringBuilder();
+    
+        if (result[0] == 0 && result[1] == 0) {
+            System.out.println("낫싱");
+        }
+        
+        if (result[0] > 0) {
+            output.append(result[0]).append("스트라이크 ");
+        }
+        
+        if (result[1] > 0) {
+            output.append(result[1]).append("볼");
+        }
+        
+        if (output.length() > 0) {
+            System.out.println(output);
+        }
+    }
+}
\ No newline at end of file

리뷰: [else 문을 지양하는 이유](https://opendeveloper.tistory.com/entry/%EC%BD%94%EB%93%9C%EC%9D%B4%EC%8A%88-if%EB%AC%B8%EC%97%90%EC%84%9C-else%EC%99%80-else-if%EB%A5%BC-%EC%A7%80%EC%96%91%ED%95%98%EB%8A%94-%EC%9D%98%EA%B2%AC%EC%97%90-%EB%8C%80%ED%95%9C-%EC%83%9D%EA%B0%81%EC%A0%95%EB%A6%AC)
@@ -0,0 +1,78 @@
+package baseball.controller;
+
+import java.util.List;
+
+import baseball.model.ComputerInputData;
+import baseball.view.PlayerInputView;
+import baseball.model.CompareBallsModel;
+import baseball.service.BaseballGameService;
+import baseball.service.InvalidInputHandler;
+import baseball.service.MoreGameService;
+
+public class GameController {
+    
+    private PlayerInputView playerInputView;
+    private BaseballGameService baseballGameService;
+    private ComputerInputData computerInputData;
+    private CompareBallsModel compareBallsModel;
+    private InvalidInputHandler invalidInputHandler;
+    private MoreGameService moreGameService;
+
+    public GameController() {
+        this.playerInputView = new PlayerInputView();
+        this.baseballGameService = new BaseballGameService();
+        this.computerInputData = new ComputerInputData();
+        this.compareBallsModel = new CompareBallsModel();
+        this.invalidInputHandler = new InvalidInputHandler();
+        this.moreGameService = new MoreGameService();
+    }
+
+
+    public void gameFlow() {
+        boolean gameWon = false;
+
+        while (!gameWon) {
+            String input = playerInputView.getPlayerInput();
+
+            if (!baseballGameService.isValidInput(input)) {
+                invalidInputHandler.invalidInputPrint();
+            }
+
+            List<Integer> computerList = computerInputData.getComputerList();
+            int[] result = compareBallsModel.compareNumbers(input, computerList);
+
+            if (result[0] == 3) {
+                System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+                gameWon = true;
+                continue;
+            }
+
+            printGameResult(result);
+            }
+        if(moreGameService.more() == true) {
+            computerInputData = new ComputerInputData();
+            gameFlow();
+        }
+    }
+
+
+    private void printGameResult(int[] result) {
+        StringBuilder output = new StringBuilder();
+    
+        if (result[0] == 0 && result[1] == 0) {
+            System.out.println("낫싱");
+        }
+        
+        if (result[0] > 0) {
+            output.append(result[0]).append("스트라이크 ");
+        }
+        
+        if (result[1] > 0) {
+            output.append(result[1]).append("볼");
+        }
+        
+        if (output.length() > 0) {
+            System.out.println(output);
+        }
+    }
+}
\ No newline at end of file

리뷰: 메서드명에 `print`가 들어가면 `Controller`의 관심사가 맞는걸까?
@@ -0,0 +1,35 @@
+package baseball.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import camp.nextstep.edu.missionutils.Randoms;
+
+public class ComputerInputData {
+
+    private List<Integer> computerList;
+
+    public ComputerInputData() {
+        computerList = picking();
+    }
+
+    public static List<Integer> picking() {
+        Set<Integer> uniqueNumbers = new HashSet<>();
+
+        while (uniqueNumbers.size() < 3) {
+            uniqueNumbers.add(Randoms.pickNumberInRange(1, 9));
+        }
+
+        List<Integer> randomList = new ArrayList<>(uniqueNumbers);
+        Collections.shuffle(randomList);
+
+        return randomList;
+    }
+
+    public List<Integer> getComputerList() {
+        return computerList;
+    }
+}

리뷰: 여기서 `static`을 사용한 이유가 뭐야?
@@ -0,0 +1,35 @@
+package baseball.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import camp.nextstep.edu.missionutils.Randoms;
+
+public class ComputerInputData {
+
+    private List<Integer> computerList;
+
+    public ComputerInputData() {
+        computerList = picking();
+    }
+
+    public static List<Integer> picking() {
+        Set<Integer> uniqueNumbers = new HashSet<>();
+
+        while (uniqueNumbers.size() < 3) {
+            uniqueNumbers.add(Randoms.pickNumberInRange(1, 9));
+        }
+
+        List<Integer> randomList = new ArrayList<>(uniqueNumbers);
+        Collections.shuffle(randomList);
+
+        return randomList;
+    }
+
+    public List<Integer> getComputerList() {
+        return computerList;
+    }
+}

리뷰: `set` -> `List`로 형변환 할 때 자동으로 정렬되기 때문에 `shuffle`을 한 건 좋은 것 같아 👍 
그런데 단위 테스트를 할 때 랜덤 값에 원하는 값을 넣는 경우도 있을텐데 `shuffle`을 이용하면 원하는 테스트를 하기 어렵지 않을까?

예를 들어서 우리는 `6`, `1`, `9`를 넣어서 테스트 하고 싶은데 저 순서를 보장할 수 있을까?
@@ -0,0 +1,35 @@
+package baseball.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import camp.nextstep.edu.missionutils.Randoms;
+
+public class ComputerInputData {
+
+    private List<Integer> computerList;
+
+    public ComputerInputData() {
+        computerList = picking();
+    }
+
+    public static List<Integer> picking() {
+        Set<Integer> uniqueNumbers = new HashSet<>();
+
+        while (uniqueNumbers.size() < 3) {
+            uniqueNumbers.add(Randoms.pickNumberInRange(1, 9));
+        }
+
+        List<Integer> randomList = new ArrayList<>(uniqueNumbers);
+        Collections.shuffle(randomList);
+
+        return randomList;
+    }
+
+    public List<Integer> getComputerList() {
+        return computerList;
+    }
+}

리뷰: 분명 `computerList`는 `private`로 선언했지만 이런식으로 리턴하면 불변 리스트를 보장할 수 있어?
[참고 자료](https://colabear754.tistory.com/185)
@@ -0,0 +1,33 @@
+package baseball.service;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class BaseballGameService {
+    
+    public boolean isValidInput(String input) {
+        // 3자리 체크
+        if(input.length() != 3) {
+            return false;
+        }
+
+        boolean onlyNumber = input.chars().allMatch(Character::isDigit);
+        if(!onlyNumber) {
+            return false;
+        }
+
+        Set<Character> charSet = new HashSet<>();
+        for (char c : input.toCharArray()) {
+            charSet.add(c);
+        }
+
+        if(charSet.size() != 3) {
+            return false;
+        }
+
+        return true;
+
+    }
+
+
+}

리뷰: ```java
Set<Character> charSet = new HashSet<>();
for (char c : input.toCharArray()) {
    if (!charSet.add(c)) { // 중복된 문자가 들어오면 false 리턴
        return false;
    }
}
```
@@ -0,0 +1,33 @@
+package baseball.service;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class BaseballGameService {
+    
+    public boolean isValidInput(String input) {
+        // 3자리 체크
+        if(input.length() != 3) {
+            return false;
+        }
+
+        boolean onlyNumber = input.chars().allMatch(Character::isDigit);
+        if(!onlyNumber) {
+            return false;
+        }
+
+        Set<Character> charSet = new HashSet<>();
+        for (char c : input.toCharArray()) {
+            charSet.add(c);
+        }
+
+        if(charSet.size() != 3) {
+            return false;
+        }
+
+        return true;
+
+    }
+
+
+}

리뷰: `isValidInput`이 무슨 의미야? `BaseballGameService` 보다는 `InvalidInputHandler`에 있는게 더 어울릴 것 같은데 메서드명인데
@@ -0,0 +1,26 @@
+package baseball.service;
+
+import camp.nextstep.edu.missionutils.Console;
+
+public class MoreGameService {
+    InvalidInputHandler invalidInputHandler;
+
+    public MoreGameService() {
+        this.invalidInputHandler = new InvalidInputHandler();
+    }
+
+
+    public boolean more() {
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+        String input = Console.readLine();
+        if ("1".equals(input)) {
+            return true;
+        } else if ("2".equals(input)) {
+            return false;
+        } else {
+            invalidInputHandler.invalidInputPrint();
+            return false;
+        }
+    }
+    
+}

리뷰: `Service` 계층에서 다른 `Service`를 사용하면 결합도가 너무 높은거 아닌가?
@@ -0,0 +1,26 @@
+package baseball.service;
+
+import camp.nextstep.edu.missionutils.Console;
+
+public class MoreGameService {
+    InvalidInputHandler invalidInputHandler;
+
+    public MoreGameService() {
+        this.invalidInputHandler = new InvalidInputHandler();
+    }
+
+
+    public boolean more() {
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+        String input = Console.readLine();
+        if ("1".equals(input)) {
+            return true;
+        } else if ("2".equals(input)) {
+            return false;
+        } else {
+            invalidInputHandler.invalidInputPrint();
+            return false;
+        }
+    }
+    
+}

리뷰: 마찬가지로 `else`를 사용하지 않는 게 훨씬 좋은 코드인 것 같아
@@ -0,0 +1,26 @@
+package baseball.service;
+
+import camp.nextstep.edu.missionutils.Console;
+
+public class MoreGameService {
+    InvalidInputHandler invalidInputHandler;
+
+    public MoreGameService() {
+        this.invalidInputHandler = new InvalidInputHandler();
+    }
+
+
+    public boolean more() {
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+        String input = Console.readLine();
+        if ("1".equals(input)) {
+            return true;
+        } else if ("2".equals(input)) {
+            return false;
+        } else {
+            invalidInputHandler.invalidInputPrint();
+            return false;
+        }
+    }
+    
+}

리뷰: 여기도 마찬가지로 `Service` 계층에서 `System.out.println`을 하는 것이 적절한가?
@@ -0,0 +1,12 @@
+package baseball.view;
+
+import camp.nextstep.edu.missionutils.Console;
+
+public class PlayerInputView {
+
+    public String getPlayerInput() {
+        System.out.print("숫자를 입력해주세요 : ");
+        return Console.readLine();
+    }
+
+}

리뷰: `System.out.print`는 `InputView`보다는 `OutputView`이지 않을까?
@@ -0,0 +1,78 @@
+package baseball.controller;
+
+import java.util.List;
+
+import baseball.model.ComputerInputData;
+import baseball.view.PlayerInputView;
+import baseball.model.CompareBallsModel;
+import baseball.service.BaseballGameService;
+import baseball.service.InvalidInputHandler;
+import baseball.service.MoreGameService;
+
+public class GameController {
+    
+    private PlayerInputView playerInputView;
+    private BaseballGameService baseballGameService;
+    private ComputerInputData computerInputData;
+    private CompareBallsModel compareBallsModel;
+    private InvalidInputHandler invalidInputHandler;
+    private MoreGameService moreGameService;
+
+    public GameController() {
+        this.playerInputView = new PlayerInputView();
+        this.baseballGameService = new BaseballGameService();
+        this.computerInputData = new ComputerInputData();
+        this.compareBallsModel = new CompareBallsModel();
+        this.invalidInputHandler = new InvalidInputHandler();
+        this.moreGameService = new MoreGameService();
+    }
+
+
+    public void gameFlow() {
+        boolean gameWon = false;
+
+        while (!gameWon) {
+            String input = playerInputView.getPlayerInput();
+
+            if (!baseballGameService.isValidInput(input)) {
+                invalidInputHandler.invalidInputPrint();
+            }
+
+            List<Integer> computerList = computerInputData.getComputerList();
+            int[] result = compareBallsModel.compareNumbers(input, computerList);
+
+            if (result[0] == 3) {
+                System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
+                gameWon = true;
+                continue;
+            }
+
+            printGameResult(result);
+            }
+        if(moreGameService.more() == true) {
+            computerInputData = new ComputerInputData();
+            gameFlow();
+        }
+    }
+
+
+    private void printGameResult(int[] result) {
+        StringBuilder output = new StringBuilder();
+    
+        if (result[0] == 0 && result[1] == 0) {
+            System.out.println("낫싱");
+        }
+        
+        if (result[0] > 0) {
+            output.append(result[0]).append("스트라이크 ");
+        }
+        
+        if (result[1] > 0) {
+            output.append(result[1]).append("볼");
+        }
+        
+        if (output.length() > 0) {
+            System.out.println(output);
+        }
+    }
+}
\ No newline at end of file

리뷰: 이 부분은 view에서 처리하는 걸로 해야 하는데 너무 간단한 로직 처리를 Model -> Controller -> View -> Controller 이렇게 처리하는게 오히려 더 비효율적이지 않을까 생각해서 이렇게 작성해봤는데 아직 정답을 잘 모르겠습니다.
@@ -0,0 +1,26 @@
+package baseball.service;
+
+import camp.nextstep.edu.missionutils.Console;
+
+public class MoreGameService {
+    InvalidInputHandler invalidInputHandler;
+
+    public MoreGameService() {
+        this.invalidInputHandler = new InvalidInputHandler();
+    }
+
+
+    public boolean more() {
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+        String input = Console.readLine();
+        if ("1".equals(input)) {
+            return true;
+        } else if ("2".equals(input)) {
+            return false;
+        } else {
+            invalidInputHandler.invalidInputPrint();
+            return false;
+        }
+    }
+    
+}

리뷰: 아래 코멘트하고도 관련되어 있는 사항인데 Service의 역할이 다르고, 단순한 호출 형식인데 이 부분도 결합이 높은건지 궁금합니다.
@@ -0,0 +1,26 @@
+package baseball.service;
+
+import camp.nextstep.edu.missionutils.Console;
+
+public class MoreGameService {
+    InvalidInputHandler invalidInputHandler;
+
+    public MoreGameService() {
+        this.invalidInputHandler = new InvalidInputHandler();
+    }
+
+
+    public boolean more() {
+        System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
+        String input = Console.readLine();
+        if ("1".equals(input)) {
+            return true;
+        } else if ("2".equals(input)) {
+            return false;
+        } else {
+            invalidInputHandler.invalidInputPrint();
+            return false;
+        }
+    }
+    
+}

리뷰: 내가 생각하는 결합도는 만약 `InvalidInputHandler`에 요구 사항이 변경돼서 수정하게 되면 당연히 `MoreGameService`에도 문제가 생길 가능성이 높겠지
지금은 매우 간단한 로직을 처리해서 1개의 의존밖에 없지만 반대로 얘기하면 간단한 로직도 의존성이 발생하는데 복잡한 로직엔 얼마나 강한 결합이 발생하고 리팩토링이 어려워질까? 하는 생각이 드는 것 같아