장's 개발생각

[개발생각] 우아한테크코스 5기 4주차 다리게임 회고

장아장 2022. 11. 23. 21:18

시작되는 한장짤

 

Source Code : https://github.com/woowacourse-precourse/java-bridge/pull/106

이번 우테코는 뭐랄까 여태까지 배운 것들을 마무리하면서 해보고 싶은 방향들을 전부 써보면서 즐기듯이 코딩을 했던 것 같다. 

사실 코딩은 그랬지 다른게 너무 바빴다. 전공시험에 과제에....(그스님 으그르스으....!)

 

그래도 코딩 측면에서는 여태까지 공부했던 모든 부분들을 다시 돌아볼 수 있었다. 

TDD를 들어보며 테스트를 먼저 만들기 위해 어떻게 생각해봐야 할지를 다시 생각해 볼 수 있었고,

DDD를 들어보며 도메인적으로 어떻게 도메인을 나누고 이를 어떻게 모델화시켜 모든걸 합쳐 하나의 시퀀스를 만들 수 있는지 생각해볼 수 있었다. 

 

# 기능 목록

## Domain
### Bridge
1. 생성자 : Bridgemaker.makeBridge를 입력해 생성한다.
2. isPlayerRightBridge : 플레이어를 입력받아 플레이어의 길이까지 다리가 같으면 참을 반환
3. getBridge : 다리를 반환해준다. 

### Player
1. 생성자 : 전역변수 List<String>을 생성한다. 전역변수 trialCount를 1로 초기화한다.
2. addNewBridgeInput : 입력 문자열을 리스트에 저장한다. 
3. getBridge : 문자열 리스트를 반환한다.
4. isGameFinished : Bridge를 입력받아 리스트가 서로 같으면 참을 반환
5. clearBridge : 리스트를 초기화시켜준다. 
6. increaseTrialCount : trialCount를 1 증가시킨다. 
7. getTrialCount : trialCount를 반환한다. 

## enum
### BridgeType
UPPER(1, 'U'), LOWER(0 , 'D')로 저장하며 getCommand 메서드를 통해 U, D를 반환한다.
getValue 를 통해 1, 0을 반환한다.

### GameCommand
START('R'), QUIT('Q')로 저장되며 getCommand 메서드를 통해 R, Q를 반환한다. 

### BridgeViewComponent
RIGHT_BRIDGE(" O"), BLANK_BRIDGE("  "), WRONG_BRIDGE(" X"), BRIDGE_CONNECTOR(" |"), BRACKET_STARTED("["), BRACKET_FINISHER(" ]"), LINE_DIVIDER("\n")를 가진다.
getSymbol을 통해 문자열을 출력받아 BridgeViewConstructor에서 출력문을 생성할 때 사용한다. 

## Model
### BridgeGame 
생성자 : 입력변수로 사이즈를 받아 BridgeMaker를 생성해 전역변수 Bridge를 사이즈로 생성해준다. 플레이어를 생성해준다.
1. constructBridge : 플레이어와 Bridge를 입력변수로 다리 결과를 반환한다. 
2. move : 입력 문자열을 플레이어에 넘겨 결과를 반환받는다. 
   1. player.addNewBridgeInput : 플레이어에게 입력 문자열을 주어 다리에 추가한다 .
   2. constructBridge : 플레이어와 Bridge의 리스트를 넘겨 결과를 반환한다. 
3. retry
   1. player.clearBridge : 플레이어의 다리 기록을 초기화한다.
   2. player.increaseTrialCount : 시도 횟수를 증가시킨다. 
4. isPaused : bridge.isPlayerRightBridge(player)의 역을 반환한다. 
5. isSuccess : player.isGameFinished(bridge)를 반환한다.
6. getTotalTrialCount : player.getTrialCount를 반환한다. 

## util
### BridgeMaker
1. makeBridge : 입력된 size 만큼 'U' 또는 'D' 로 이루어진 문자열 리스트를 반환한다.
   1. constructBridgeAtPoint
   2. chooseSideOfBridge : bridgeNumberGenerator.generate 를 통해 0, 1중에 랜덤값을 반환한다.
   3. changeValueToCommand : 정수를 BridgeType의 command로 반환한다.

### BridgeViewConstructor
1. constructBridge : 플레이어 리스트와 bridge리스트를 입력받아 결과 문자열을 반환한다. 
   1. appendRightAnswer :
      1. isU : U면 참을 반환한다. 
      2. appendWithO : 입력된 다리에 위쪽 다리에 O를 추가한다. 
      3. appendWithBlank : 입력된 다리에 공백을 추가한다. 
   2. appendWrongAnswer : 
      1. isU : 
      2. appendWithBlank
      3. appendWithX : 입력된 다리쪽에 X를 추가한다. 
   3. makeBracket : 위, 아래쪽 다리의 결과에 괄호를 추가한다.
      1. deleteLastDivider : 마지막 |를 제거한다. 
   4. constructBeforeLast : 플레이어 리스트 길이 -1까지 다리들을 추가한다. 
   5. constructLast :
      1. getLastIndex : 리스트의 마지막 값을 반환한다. 
      2. isSameLast : 마지막이 같으면 참을 반환한다. 

## View
### InputView
1. readBridgeSize : 입력을 요청받아 입력이 맞는 입력일 때 까지 반복시킨다.
   1. readInput : 입력 문자열을 출력하여 입력을 요청하고 콘솔의 입력문자열을 반환한다.
   2. validate : BridgeLengthException 에서 validate 을 한 후 정수형으로 반환한다.
2. readMoving : 입력을 요청받아 입력이 맞는 입력일 때 까지 반복시킨다.
   1. readInput : 입력 문자열을 출력하여 입력을 요청하고 콘솔의 입력문자열을 반환한다.
   2. validate : BridgeChoiceException.validate을 실행해 문자열을 반환한다.
3. readGameCommand : 입력을 요청받아 입력이 맞는 입력일 때 까지 반복시킨다.
   1. readInput : 입력 문자열을 출력하여 입력을 요청하고 콘솔의 입력문자열을 반환한다.
   2. validate : GameCommandException.validate를 실행해 문자열을 반환한다.

### OutputView
1. printMap : 입력 문자열 두개를 줄바꿈 처리해서 출력시킨다.
2. printResult : trialCount와  isGameFinished 입력받아
   1. printGameStatus : '게임 성공 여부: '와 makeResultStatement를 출력한다.
      1. makeResultStatement : 입력변수가 참이면 '실패', 아니면 '성공'을 반환한다.
   2. printTrialCounts : '총 시도한 횟수: ' 에 trialCount를 연결해 출력한다.

## 예외처리
### Exceptions
1. executeException : IllegalArgumentException 을 발생시킨다.

### BridgeLengthException (extends Exception)
1. validate : 문자열에서 값을 확인한 후 정수형으로 파싱해 반환한다.
   1. isNotNumber : 입력 문자열이 숫자로 이루어지지 않았을 때 참을 반환한다.
   2. isOutOfRange : 3보다 작고 20보다 클 경우 참을 반환한다.
   3. notBridgeLengthException : '[ERROR] 다리의 길이는 3이상 20이하의 수로 입력해야 합니다'를 출력하고 executeException 을 실행한다.

### BridgeChoiceException (extends Exception)
1. validate
   1. isNotUp : 입력 문자열이 'U'와 다르면 참을 반환
   2. isNotDown : 입력 문자열이 'D'와 다르면 참을 반환
   3. notBridgeException : '[ERROR] 다리는 위의 다리를 고를 때 'U', 아래 다리를 고를 때 'D' 로 입력해야 합니다. '를 출력하고 executeException 을 실행한다.

### GameCommandException (extends Exception)
1. validate
   1. isNotRestart : 입력 문자열이 'R'와 다르면 참을 반환
   2. isNotQuit : 입력 문자열이 'Q'와 다르면 참을 반환
   3. notGivenOpinionException : '[ERROR] 개임을 재시작할 때 'R', 개임을 끝낼 때 'Q' 로 입력해야 합니다.'를 출력하고 executeException 을 실행한다.
   4. getStatusByCommand을 통해 문자열을 받아 해당하는 GameStatus를 반환한다.

## Controller
### BridgeGameController
1. 생성자 : InputView.readBridgeSize를 입력받아 Bridge를 생성하고 Player을 생성해준다. 전역변수 trialCount를 1로 초기화해준다.
2. runGame : moveUntilStop을 반복한다. bridgeGame.isSuccess이거나 isQuit면 반복을 멈추고 결과를 반환한다. 반복이 다시될 때 resetGame해준다.
   1. moveUntilStop : isPaused나 isSuccess일 때 까지 moveAStep해준다
      1. moveAStep : Input.readMoving을 입력받아 bridgeGame.move의 입력변수로 연산하고 결과를 outputView.printMap한다. 
   2. resetGame : bridgeGame.retry해준다.
   3. isQuit : 출력이 Q이면 참을 반환한다. 
      1. readFinalCommand : 출력을 반환한다. 
   4. concludeGame : OutputView.printResult에 bridgeGame.constructBridge와 bridgeGame.getTotalTrialCount를 넣어 결과를 출력한다.

이 기능목록이 기능이 추가되거나 메서드의 이름이나 인자값이 바뀌지 않는 한 최대한 건드리지 않게 초기에 만들 수 있도록 생각을 반복했다. 

정말 머리속으로 얼마나 생각해야 하는지, 그리고 모든 경우를 생각해야 하는지를 느꼈다. 

왜냐면 마지막 코드를 위해 한 3번정도를 생각을 철회하고 다시 고치기를 하기도 했다. 

그런데, 이런 과정이 너무 재미있었다. 생각의 전환이 되고, 다른 방향성을 생각해보며 그 경우를 상상하는 재미에 빠졌다. 

 

프로젝트의 모델링을 하며 처음 생각이 들었던 것은, 상식적으로는 게임을 하는 플레이어와, 다리의 정답이 있어야 하는데 이를 어떻게 푸는게 더 확실하게 만들어질까가 생각이 되었다. 

 

도메인이라는 기능적 최소 단위들을 모아서 모델을 만들고, 모델을 MVC로 만들면 어떨까라는 생각을 했다. 

플레이어, Bridge라는 모델을 가지고 BridgeGame이라는 모델에 넘겨 BridgeGameController를 통해 연산을 출력하는 식으로 정리를 했다. 

 

3주차에 비해 아쉬움은 적고 개인적으로 머리속에 담아두고만 있던 방식들을 다 풀어볼 수 있었다. 

 

어떻게 보면 혼자 따로 다른방식으로 만든 BridgeGame은 어떨지 비교해보며 혼자 재미를 느껴볼 수 있었다.

 

저번 주차에 머리를 더 굴려서 그런가 이번 주차는 재미가 있었다. 

내 머리는 돌멩이인가봐요...매우 아프고 딱딱하게 굳었어요...

 

 

 

 

 

 

 

 

 

 

앞으로의 목표를 잡아봐야 할 때가 온 것 같다. 

2주차부터 4주차까지의 문제들을 다시 풀어보라는 포비멘토님의 조언이 있었다. 

해당 주차에 작성했던 회고록과 리뷰파일을 보면서 해당 부분들을 고칠 수 있게 노력해야겠다. 

개인적으로는 타이머를 켜두고 시간을 정해서 문제를 풀어봐야겠다. 

여태까지 만들어봤던 코드들도 한번씩 리펙토링해봐야지....

 

개인적으로 할게 쌓이는데 그게 또 나름 재미있다.

어쩌면 나 M쪽일수도 있어...?

 

이렇게까지 열성적인적이 많지 않았는데...사실 되게 행복하다ㅎㅎㅎ

(일단 기말고사도...하핳)

열심히 살아야지