Conversation
| public List<Integer> problemNumbersGenerate() { | ||
| List<Integer> numbers = new ArrayList<>(); | ||
| while (numbers.size() < 3) { | ||
| int num = random.nextInt(9) + 1; | ||
| if (!numbers.contains(num)) { | ||
| numbers.add(num); | ||
| } | ||
| } | ||
| return numbers; | ||
| } |
There was a problem hiding this comment.
랜덤한 숫자가 잘 나오는 지 테스트 하는 방법은 없을까? 현재는 Random() 이 잘 작동하도록 기도하는 수 밖에 없다.
| throw new IllegalArgumentException("숫자는 1-9 사이여야 합니다."); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
숫자가 3이여야 한다는 것은 정책 아닌가? 이 숫자가 여러 번 등장하는데, 정책이 바뀔 때 마다 여러 번 등장하는 해당 숫자가 변경되어야 한다.
상수로 처리하거나, 로직을 변경하는 게 좋을 듯 하다
There was a problem hiding this comment.
테스트 가능한 코드를 위해 NumberGenerator 인터페이스 추가
이렇게 인터페이스를 추상화해야 테스트에서 임의의 값을 생성할 수 있음
=> 그러나 추상화에 대한 이해가 잘 안됨 좀더 고민이 필요한듯..
=> 왜 interface로 선언해야하지? 최소한의 동일성을 위해?
현재 프로젝트가 너무 단순해서 필요성을 못 느껴서 그럴 수 있겠단 생각
요구사항이 많아질수록 인터페이스를 쓰는게 테스트하기 더 좋아지지 않을까
(테스트를 위해 전부 다시 선언하는건 너무 소모적이라?)
There was a problem hiding this comment.
@SongHanSol1140
인터페이스의 장점을 잘 생각하면 좋을 듯 하다. 이 경우 아래와 같이 사용했다. (네가, 일부는.)
- 운영 환경 : RandomNumberGenerator
- 테스트 환경 : FixedNumberGenerator -> 이 구현체는 항상 '5'를 반환한다.
이 경우 테스트 환경에만 존재하는 FixedNumberGenerator 를 Stub 이라고 하며, 인터페이스의 반환값이나 입력값이 변경되지 않는 한 해당 구현체도 변경 될 필요가 없다.
현재 구현에서는 "랜덤 넘버를 만든다" 자체를 테스트 하기가 어렵기 때문에 위와 같이 작성해야 했는데, 이 외에도 여러 장점이 있다.
- V1, V2 ... 버전이 몇 개 생기더라도, 이전 버전 클래스를 삭제하지 않고 사용하다가 이후 버전으로 마이그레이션 가능하다. (e.g @deprecated)
- 하나의 인터페이스에 여러 구현체가 존재하며, 구현체 타입별로의 분기가 가능하다. (e.g PG사)
- 네이버페이.pay
- 카카오페이.pay
- ...
| public static BaseBallNumbers parseIntegerList(String input) { | ||
| List<Integer> numbers = new ArrayList<>(); | ||
| for (char c : input.toCharArray()) { | ||
| numbers.add(Character.getNumericValue(c)); | ||
| } | ||
| return new BaseBallNumbers(numbers); | ||
| } |
There was a problem hiding this comment.
- 스태틱 메서드는 클래스 상단에 위치해야 한다. (생성자 위, 프로퍼티 아래)
- 유저의 인펏으로만 생성되는 인스턴스라면, 생성자는 private이어도 무관 할 것이다.
- 반드시 유저의 인펏으로만 생성된다면, 생성자 패러미터 자체를 Input 으로 변경해도 무방 할 것이다.
There was a problem hiding this comment.
유저의 input으로만 생성되는 인스턴스라면 생성자는 private여도 무관할 것이다.
=> .from과 .parse로만 객체를 반환하니 생성자는 외부에서 호출될 필요가없기때문에 private 시키는것이 타당함
반드시 유저의 인펏으로만 생성된다면, 생성자 패러미터 자체를 Input 으로 변경해도 무방 할 것이다.
=> 현재 입력 타입들이 List와 String 두 종류로 되어있어서(generate -> List, input -> String)때문에 변경할 필요 없을듯
There was a problem hiding this comment.
타입자체가 통일하는게 좋지않겠냐는 말은 동의함..
| inputHandler.close(); | ||
| } catch (IllegalArgumentException error) { | ||
| System.out.println(error.getMessage()); | ||
| System.exit(0); |
There was a problem hiding this comment.
이거 exit안하면 앱 살아잇는줄 알았는데 빼도 죽네; 지우는게 맞는듯
| // 자릿수 체크 | ||
| if (input.length() != 3) { | ||
| throw new IllegalArgumentException("3자리 숫자를 입력하세요."); | ||
| } |
There was a problem hiding this comment.
모델 BaseBallNumbers에 게임에 사용될 숫자 갯수 상수로 수정
| inputHandler.close(); | ||
| } catch (IllegalArgumentException error) { | ||
| System.out.println(error.getMessage()); | ||
| System.exit(0); |
| public static BaseBallNumbers parseIntegerList(String input) { | ||
| List<Integer> numbers = new ArrayList<>(); | ||
| for (char c : input.toCharArray()) { | ||
| numbers.add(Character.getNumericValue(c)); | ||
| } | ||
| return new BaseBallNumbers(numbers); | ||
| } | ||
|
|
||
| public BaseBallNumbers(List<Integer> numbers) { | ||
| validate(numbers); | ||
| this.numbers = numbers; | ||
| } |
There was a problem hiding this comment.
그냥 생성자랑 parseIntegerList 생성자랑 용도가 다른 건 이해했다. 그러나 해당 생성자를 사용하는 다른 개발자는 이 용도를 곡해 할 여지가 있다. (해당 구현은 너무나 간단해서 오해의 소지가 적지만, 더 복잡한 구현이라면 얼마든지 가능하다)
그러므로 둘이 어느 용도로 쓰이는 건 지 모두 static 생성자로 분리하는것이 좋다.
There was a problem hiding this comment.
정적팩토리 메서드 사용
BaseBallNumbers problemNumbers = new BaseBallNumbers(numberGenerator.generate());
=>
BaseBallNumbers problemNumbers = BaseBallNumbers.from(numberGenerator.generate());
from은 'return new BaseBallNumbers(numbers); 밖에 안하므로 사실상 완벽히 같은동작을 수행함
그러나 기존 .parseIntegerList함수를 .parse로 변경
from, parse 사용하여 BaseBallNumbers 생성 양식 통일이 가능해짐
기존
BaseBallNumbers problemNumbers = new BaseBallNumbers(numberGenerator.problemNumbersGenerate());
BaseBallNumbers userNumbers = BaseBallNumbers.parseIntegerList(userInput);
변경 후
BaseBallNumbers problemNumbers = BaseBallNumbers.from(numberGenerator.generate());
BaseBallNumbers userNumbers = BaseBallNumbers.parse(userInput);
숫자 야구게임 풀 리퀘스트