1부터 9까지 서로 다른 수로 이루어진 3자리의 숫자를 맞추는 게임을 구현해야 한다.
먼저 구현해야 하는 기능 목록을 작성했다.
1. 구현할 기능 목록 작성
2. 코드 작성
처음에는 코딩 테스트처럼 main 함수에 기능 요구사항을 만족하는 전체 기능을 구현했었다.
하지만 JAVA는 객체지향 언어이고, 객체의 역할과 용도에 따른 구분이 필요하다는 생각이 들었다.
먼저 역할에 따라 클래스를 구분했다.
- 애플리케이션 전체 실행을 컨트롤하는 클래스 (BaseballApp)
- 애플리케이션 전체 설정을 담당하는 클래스 (AppConfigure)
- 랜덤 숫자(정답)를 생성하는 클래스 (RandomNum)
- 사용자로부터 숫자를 입력받는 클래스 (InputNum)
- 입력받은 숫자를 검증하는 클래스 (CheckNum)
최대한 하나의 클래스에서는 하나의 역할을 담당할 수 있도록 분리해 보았다.
또한 향후 프로그램이 수정되거나 확장되었을 때 어떻게 구현하는 게 유리할지 고민해 보았다.
만약 설정 변경이 필요하면 AppConfigure 클래스를, 입력받은 숫자 검증 방식을 수정하려면 InputNum클래스를 수정하는 등 필요에 따라 해당 클래스를 수정하면 되도록 설정하였다.
1) BaseballApp, AppConfigure
main() 함수에서는 BaseballApp의 start() 메서드를 실행시킨다. (이때 필요한 설정들은 AppConfigure에서 수정해서 적용한다.)
BaseballApp의 start() 메서드에서 기능과 관련된 모든 로직을 컨트롤하게 된다.
public class Application {
public static void main(String[] args) {
AppConfigure appConfigure = new AppConfigure(); // 설정 변경은 main()에서 하지 않고 AppConfigure에서 한번에 처리한다.
BaseballApp baseballApp = new BaseballApp(
appConfigure.randomNum(),
appConfigure.inputNum(),
appConfigure.checkNum()
);
baseballApp.start(); // 실제 애플리케이션 동작 부분
}
}
2) RandomNum
주어진 라이브러리를 활용해 List<Integer> 형태의 세 자리 랜덤숫자를 생성하였다.
3) InputNum
사용자로부터 숫자를 입력받고 적절한 숫자인지 확인하는 역할을 한다.
사용자로부터 입력받는 숫자는 크게 두 가지로, 랜덤 숫자를 맞추기 위한 숫자와 게임을 종료할지 여부를 응답하는 숫자였다.
(1) 랜덤 숫자 맞추기용 - getPlayerNum()
숫자 입력 시 주어진 라이브러리를 사용해야 했고 유효성 검사를 진행해야 했다. (3자리 숫자인지, 중복되는 숫자는 없는지)
주어진 메서드를 활용하면 입력받은 값의 타입은 String이었다.
생성된 랜덤숫자와의 원활한 비교를 위해 List<Integer>로 변경하는 로직을 추가했다.
길이, 숫자 중복여부, 0 포함 여부를 검사하여 유효성 검사에 실패하면 IllegalArgumentException을 발생시켰다.
(2) 게임 종료 여부 확인용 - getExitNum()
랜덤 숫자 3개를 모두 맞추면 게임을 종료할 수 있다. 새로 시작하려면 1, 종료하려면 2를 입력한다.
입력된 숫자를 String으로 반환한다.
4) CheckNum
게임의 핵심 비즈니스 로직이다. 플레이어로부터 입력받은 숫자와 생성된 랜덤 숫자를 비교하여
스트라이크, 볼의 개수를 계산하고 그 결과를 출력한다.
해당 코드를 실행시킨 결과 아래와 같이 주어진 요구사항을 만족하고, 주어진 테스트 코드도 정상적으로 통과하는 것을 확인했다.
[ 1차 과제 회고 ]
간단한 미션이었지만 많은 것들을 생각해 볼 수 있는 시간이었다.
가장 크게 와닿은 것은 객체, MVC, TDD 등 여러 가지를 고려해야 한다는 점이었다.
처음에는 기능 구현만 생각해서 코드를 작성했으나 프로그램의 유지 보수나 확장을 고려해서 코드를 설계해야 한다는 생각이 들었다.
코드가 어떤 흐름으로 동작하는지, 클래스 간에 어떤 관계를 갖는지 고려하고 향후 프로그램이 어떻게 확장/변경될 수 있을지까지 생각해 보면 좋을 것 같다.
두 번째는 네이밍과 관련된 부분이었다.
가독성 좋은 코드를 작성하기 위해 쉽게 이해할 수 있는 클래스명, 메서드명을 사용하고 싶었다.
그런데 네이밍도 생각보다 간단하지만은 않았다. 이 부분은 다른 사람들의 코드를 많이 보면서 배우고 익숙해져야 할 것 같다.
과제를 하면서 전체적으로 든 생각은 '다른 사람의 코드를 많이 보자'였다.
이때까지는 수업 내용과 과제 수행에만 집중했었다면, 앞으로는 여러 코드들을 보면서 다양한 방식과 기술을 학습해야겠다.
이번 우테코 프리코스를 통해 많은 사람들의 이야기도 들어보고 결과물도 공유하면서 많은 것들을 학습할 수 있기를 기대해본다.
1차 과제 코드: (링크)
* 부족한 부분이 많은 코드입니다. 코드 리뷰는 언제든지 환영입니다.^^
'우아한테크코스 프리코스' 카테고리의 다른 글
[우아한테크코스 6기] 최종 코딩테스트: 비상 근무표 작성 (0) | 2023.12.17 |
---|---|
[우아한테크코스 6기] 프리코스 4차 과제: 크리스마스 프로모션(구조 설계, 테스트 커버리지, 최종 회고) (0) | 2023.11.15 |
[우아한테크코스 6기] 프리코스 3차 과제: 로또(@ParameterizedTest, @CsvSource) (0) | 2023.11.08 |
[우아한테크코스 6기] 프리코스 2차 과제: 레이싱 게임(JUnit5, System.setIn, System.setOut) (0) | 2023.10.31 |
[우아한테크코스] 프리코스 시작 (환경 설정) (0) | 2023.10.19 |