우아한테크코스 6기 프리코스에 참여하게 되어 앞으로 4주간을 기록하고자 한다.
이번 1주차 미션은 근본의 숫자 야구 게임이었다.
필자가 작성한 코드는 밑에 첨부한 링크에서 확인 가능하다.
최근까지 Spring으로 프로젝트를 하다가 순수 Java로만 미션을 진행하니까 색다른 느낌이기도 하고 재미있었다. ㅎㅎ
1주차에는 기본에 충실하면서 남들이 읽기 쉬운 코드를 작성하는 것이 나만의 목표였다.
(과연 읽기 쉬운 코드를 짰는지...는 우테코 디스코드를 통해 PR 리뷰 요청을 해 피드백을 받아볼 예정이다.!)
✏️ PR Review
블로그 보고 들어오시는 분도 있을 것 같아 개인 레포지토리에 리뷰용 PR을 올렸습니다.
↓↓ PR 리뷰는 언제나 환영입니다! ↓↓
https://github.com/jinny-l/java-baseball-6/pull/1
그리고 미션을 구현하면서 전반적인 설계나, 테스트 등 다양한 다양한 고민을 하게 되었다.
본글은 미션을 진행한 과정과 고민등에 대해 기록하고자 한다.
그럼 회고를 시작해보자!
"기능을 구현하기 전 docs/README.md
에 구현할 기능 목록을 정리해 추가한다."라는 요구사항이 있어
우선 기능 목록을 작성하고 기능 구현을 시작했다.
처음부터 모든 목록을 다 작성한 것은 아니고 구현하면서 누락한 내용이 있으면 그때그때 추가했다.
그리고 커밋할 때 구현한 기능은 to do 박스에 체크하면서 진행했다.
사실 정신없이 구현하다보면 어디까지 구현이 되었고, 어느 부분이 남았는지 헤맬때가 있었다.
머리속에 다음에 뭐 해야하지?라는 갈고리(🤯)가 생겼는데, 이때 기능 목록이 길잡이가 되어주었다.
기능 목록에 따라 하나 하나 구현하다보니 기능 구현이 완료되었다.
README.md
(캡쳐하기에 너무 길어서 일부 내용만 캡쳐했다. 원본은 여기서 확인할 수 있다.)
기능 구현을 다하고 기능 확인을 위해 테스트 코드를 작성했다.
테스트 코드 작성 전에도 기능 목록 작성한 것과 같이 README
에 미리 테스트 케이스 목록을 만들었다.
테스트 코드를 짜다보면 어떤 케이스를 테스트했는지, 어떤 케이스를 테스트 안했는지 한눈에 안 보이기도 하고
코드를 짜면서 케이스를 생각하기 어렵다보니 목록을 짜게 되었다.
아직 테스트 코드 짜는 게 어렵지만...
테스트 코드를 짤 때도 케이스가 미리 정리되어 있다보니 한결 수월하게 진행할 수 있었던 것 같다.
README.md
(캡쳐하기에 너무 길어서 일부 내용만 캡쳐했다. 원본은 여기서 확인할 수 있다.)
작년 우테코 요구사항은 Java 11
이었는데, 올해는 Java 17
로 바뀌었다.
지금까지 Java 11
만 썼는데 Java 17
을 사용하기 위해 변경점을 공부했다.!
그리고 변경점만 공부하는 것보다는 올해에는 왜 요구사항이 바뀌었고 Java 17
을 써야 하는지
알고 쓰는 것이 좋을 것 같아서 관련 내용을 공부하고 블로깅하였다.
다음 미션에는 Java 17
에 추가된 기능을 하나씩 사용해볼 예정이다!
숫자 야구는 1부터 9까지 서로 다른 수로 이루어진 3자리의 수로 이루어져 있는데
미션 요구사항을 보면 이 숫자는 제공된 Randoms
API를 활용하여 랜덤 값을 추출하여 만들어야 한다.
그때부터 고민이 시작되었다... 🤔
컴퓨터가 생성한 숫자 야구가 있고, 플레이어의 입력 값에 대한 결과(스트라이크, 볼, 낫싱)를 테스트해야 하는데...
숫자가 랜덤으로 생성되면 어떻게 테스트하지..?
랜덤으로 생성된 숫자를 테스트하는 방법에 대해 찾아보다가 좋은 블로그 글을 발견하게 되어 인사이트를 얻게 되었다!
🔗 참고한 블로그:
바로 인테페이스로 추상화하는 것이다..!
main
에서는 실제로 랜덤으로 숫자를 생성하는 클래스를 구현하고test
에서는 의도한 숫자를 생성하는 클래스를 구현하면 테스트하기 수월해진다.코드로 자세하게 알아보자.
NumberGenerator.java
@FunctionalInterface
public interface NumberGenerator {
List<Integer> generate();
}
RandomNumberGenerator.java - main
에서 사용하는 구현체
: 랜덤 숫자 3개를 리턴하게 구현
@Override
public List<Integer> generate() {
List<Integer> numbers = new ArrayList<>();
while (numbers.size() < BASEBALL_LENGTH) {
int randomNumber = Randoms.pickNumberInRange(BASEBALL_START_NUMBER, BASEBALL_END_NUMBER);
if (!numbers.contains(randomNumber)) {
numbers.add(randomNumber);
}
}
return numbers;
}
TestNumberGenerator.java - test
에서 사용하는 구현체
: 생성자 생성 시 입력받은 값을 그대로 리턴하게 구현
public static class TestNumberGenerator implements NumberGenerator {
private final List<Integer> numbers;
TestNumberGenerator(List<Integer> numbers) {
this.numbers = numbers;
}
@Override
public List<Integer> generate() {
return numbers;
}
}
다음 코드는 실제로 제출한 미션 코드에서 일부를 발췌한 내용이다.
필자는 Service
클래스에서 랜덤 숫자를 생성해 Baseball
을 생성하게끔 구현해서 Service
테스트를 했는데, 각자 상황에 맞게 응용하면 될 듯 하다!
public class GameServiceTest {
private GameService service;
@BeforeEach
void setUp() {
// ↓ 의도한 숫자를 생성하는 TestNumberGenerator 생성(컴퓨터 Baseball이 1, 2 ,3으로 생성됨)
service = new GameService(new TestNumberGenerator(List.of(1, 2, 3)));
service.startGame();
}
@DisplayName("낫싱 상황일 때 맞는 결과를 리턴한다.")
@Test
void get_nothing_game_result() {
// given
service.setPlayerBaseball(List.of(4, 5, 6)); // 플레이어 Baseball을 4, 5, 6으로 생성
// when
GameResult gameResult = service.getGameResult();
// then
assertThat(gameResult).isEqualTo(GameResult.nothing()); // 낫싱 결과 예상
}
// ↓ 테스트용 NumberGenerator 구현
public static class TestNumberGenerator implements NumberGenerator {
private final List<Integer> numbers;
TestNumberGenerator(List<Integer> numbers) {
this.numbers = numbers;
}
@Override
public List<Integer> generate() {
return numbers;
}
}
}
미션도 해야하고, 공부한 내용 정리하고, 회고까지 하니까 1주일이 뚝딱이다. 🥲
마치기 전에 다음주에 개선하고 싶은 점을 쓰고 회고를 마무리하려고 한다.
이번주 미션하면서 다음 미션에는 꼭 개선해야지 했던 것이 있는데... 바로 테스트 코드이다.
기능 구현이 모두 완료되고 나서 테스트 코드를 짜니까 기능이 제대로 동작하는지 바로바로 확인이 어려웠고,
기능 구현 → 기능 확인 간의 호흡이 너무 긴 느낌이 들었다.
다음 목표는 1기능 1테스트 코드 짜는것을 목표로 진행하려고 한다!
이번 미션에 참여한 분들 모두 고생하셨습니다! 🙇🏻
랜덤 숫자 테스트로 저도 애를 먹었는데 비슷한 고민을 하신 분이 있다니 위안이 되네요😂
글 잘 읽었습니다! 코드도 읽어보고 리뷰 남겨 볼게요!📝📝