전달받은 문자열을 분리된 정수형 리스트로 변환해줘야 하는 상황
개선 전
public class Player {
public List<Integer> generateNumber(String readLine) {
return (List<Integer>) separateReadLine(readLine)
.stream()
.map(Character::getNumericValue)
.collect(toList());
}
private static List<Character> separateReadLine(String readLine) {
List<Character> separate = new ArrayList<>();
for (int index = 0; index < LENGTH.getNumber(); index++) {
char eachNumber = readLine.charAt(index);
separate.add(eachNumber);
}
return separate;
}
}
@ParameterizedTest
@MethodSource("parametersProvider")
public void 사용자_랜덤수_생성(String readLine, List<Integer> expect){
//given
System.setIn(setReadLine(readLine));
//when
List<Integer> actual = player.generateNumber(inputView.putReadLine());
//then
assertEquals(expect, actual);
}
static Stream<Arguments> parametersProvider() {
return Stream.of(
arguments("123", List.of(1,2,3)),
arguments("456", List.of(4,5,6)),
arguments("789", List.of(7,8,9))
);
}
문제점
- 객체가 객체스럽지 않다.
- 테스트 코드에서 기차 충돌 발생
- 이후 프로덕션 코드 구축에서 불필요한 인스턴스 생성으로 디버깅하기 불편했음
개선 후
public enum Player {
PLAYER;
private String readLine;
public List<Integer> number() {
this.readLine = new InputView().putReadLine();
return generateNumber(readLine);
}
private List<Integer> generateNumber(String readLine) {
return separate().stream()
.map(Character::getNumericValue)
.collect(Collectors.toList());
}
private List<Character> separate() {
List<Character> player = new ArrayList<>();
readLine.chars()
.mapToObj(element -> (char) element)
.forEach(player::add);
return player;
}
}
고민2
- 가독성은 미미하게 향상된게 맞는 것 같다.
- 객체가 메시지를 던지는 것은 반쯤 맞은 것 같다.
- 역직렬화를 예방할 수 있는가?
- 복잡한 공격(직렬화, 리플렉션)을 막을 수 있는가?
public enum Separator {
SEPARATOR;
private List<Character> separator;
public List<Character> execute() {
String readLine = new InputView().putReadLine();
separator = new ArrayList<>();
return separate(readLine);
}
private List<Character> separate(String readLine) {
readLine.chars()
.mapToObj(element -> (char) element)
.forEach(separator::add);
return separator;
}
}
public enum Player {
PLAYER;
private String readLine;
public List<Integer> number() {
return generateNumber();
}
private List<Integer> generateNumber() {
return SEPARATOR.execute()
.stream()
.map(Character::getNumericValue)
.collect(Collectors.toList());
}
}
@ParameterizedTest
@MethodSource("parametersProvider")
public void 사용자_랜덤수_생성(String readLine, List<Integer> expect){
//given
System.setIn(setReadLine(readLine));
//when
List<Integer> actual = PLAYER.number();
//then
assertEquals(expect, actual);
}
static Stream<Arguments> parametersProvider() {
return Stream.of(
arguments("123", List.of(1,2,3)),
arguments("456", List.of(4,5,6)),
arguments("789", List.of(7,8,9))
);
}
}