-
Notifications
You must be signed in to change notification settings - Fork 60
[그리디] 서현진 사다리 미션 제출합니다. #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: nonactress
Are you sure you want to change the base?
Conversation
사다리 사이를 연결해주는 다리 클래스
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요 현진님~! 저도 잘 부탁드립니다 🙇♂️
각 사다리가 연결이 안되는 구조 발생 시키지 않는 로직 설계
지금 코드에선 Bridge클래스에서 무조건 랜덤한 값을 기준으로 생성 유무를 판단하고 있어서 만약 같은 열에 모두 NONE(0)이 된다면 이론상 사다리간 다리가 놓이지 않는 구조가 나옵니다. 이러한 경우를 없앨 수 있는 논리적 구조가 어떻게 구현 가능 할 지 궁금합니다.
이거 한 번에 생성하기엔 힘들 것 같고, 두 번 나눠서 생성해야할 것 같아요
(n-1)개의 가로선 먼저 생성 + 이후 완전 랜덤 생성 = 한쪽이 연결되지 않는 경우가 없는 게임 생성
고민해봤을 때 현재 코드에서 가장 간단하게 추가할 수 있는 방법은 처음에 먼저 (n-1)개의 가로선부터 먼저 랜덤하게 생성할 때 BridgeStep을 NONE, EXIST 말고도 FIXED 같은 상태명을 둬서 삭제하지 못하도록 하는 코드가 덧붙여질 것 같네요
만약 많이 뜯어 고친다고 생각한다면 하나의 Row에 랜덤하게 생성하는 로직 대신, Row 내부도 for문으로 이전에 가로줄을 만들었는지 검증하고, 이후 랜덤하게 생성하는게 현재 코드보다 로직상 간단한 코드가 생성될 것 같아요
- 현재 로직: 랜덤으로 가로줄 생성 > 이후 연속된 가로줄이 있으면 랜덤으로 왼쪽 or 오른쪽 가로줄 삭제
- 개선 로직: 이전에 가로줄을 생성했으면 건너뛰고, 그게 아니면 랜덤으로 가로줄 생성
테스트 코드 작성 기준 및 케이스 나누기
요번 미션을 진행하며 테스트 코드를 작성할 때 제미나이의 도움을 아주 많이 받으면서 작성했습니다. 특히 어떤 케이스를 테스트를 해야하나 기준을 나누는 것이 어려운 것 같습니다. 어떤 식으로 학습하고 테스트 코드를 작성 해야 하는지 궁금합니다
이거는 현진님이 미션을 어떻게 진행하는지부터 출발해야할 것 같아요
- 코딩하면서 어떤 객체와 기능들을 만들지 생각하면서 만든다
- 우선 대략적인 구조를 생각해보고 이후에 코딩한다
- 메모장에 구현할 기능들을 분해한 뒤 코딩한다
- 그림판에 대략적인 구조를 그리고, 메모장에 구현할 기능들을 분해한 뒤 코딩한다
가장 이상적인 방식은 4번인데, 이거는 지금 미션처럼 처음부터 코딩할 때 생각의 일관성을 지켜주니 개발 속도도 빨라지고, 앞으로의 방향성을 잡아준다는 장점이 있을 것 같아요 (= 따로 메모를 안하다보면 잊어버려서 똑같은걸 또 다시 생각하는 날도 많음)
이걸 이야기하는 이유는 3,4번으로 코딩하게 되면 대략적인 메서드가 어떤게 생기고, 각 메서드는 어떤 역할을 할지 정해지게 되는데요. 그러면 어느 케이스의 테스트 코드를 작성하면 되는지 알 수 있게 됩니다.
테스트 코드 리뷰는 지금 리뷰 드리면 한 번에 리뷰하는 양이 많아져서 다음 리뷰에 드릴게요
- 어떤 케이스를 테스트 해야하는지?: 모든 public 메서드에 대해 모든 경우의 수를 테스트하는게 가장 이상적임
- 어떤 식으로 학습하고 테스트 코드를 작성해야하는지?: 테스트 코드 학습은 개발과는 다른 테스트만을 위한 개발 내용을 공부해야해서 나중에 필요할 때 학습하는게 제일 좋아요 (ex. 동시성, LocalDateTime, ..) 그래서 문서 용도로 활용할 수 있도록 given-when-then 패턴처럼 규칙성 있고 깔끔하게 작성하는게 베스트라고 생각하시면 됩니다
| OutputView outputView = new OutputView(); | ||
|
|
||
| public void startLadder() { | ||
| int height; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
height와 isAll이 가장 위에 있는데 먼저 선언한 이유가 있나요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
따로 의미를 두고 필드를 위에 선언 한 이유는 없습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아하 보통 변수는 선언과 동시에 초기화하는게 좋아요
| outputView.askPlayers(); | ||
| String inputs = inputView.getScanner().nextLine(); | ||
| Player players = new Player(inputs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
지금 줄바꿈으로 구역을 나눠주어서 쉽게 변경 가능할만한 것 같은데요
한가지 목적을 위해 생성되는 코드들은 private 메서드로 하나로 합쳐주면 좀 더 역할 분담이 잘된 코드가 생길 것 같아요
private Player getPlayers() {
outputView.askPlayers();
String inputs = inputView.getScanner().nextLine();
return new Player(inputs);
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 수정하겠습니다!
| Player players = new Player(inputs); | ||
|
|
||
| outputView.askRewards(); | ||
| inputs = inputView.getScanner().nextLine(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
변수명에 의미를 담아주시면 훨씬 좋아보여요
ex) inputs: 무엇을 하는 inputs일까?? >> 윗줄을 보고 askRewards임을 알 수 있지만, rewardInputs로 변수명을 사용하면 굳이 윗줄 코드에 대해 생각하지 않아도 됨
그리고 변수는 기본적으로 한 번 초기화된 상태로 쭉 사용하는 용도이고, 같은 변수가 여러번 달라지는건 특별한 경우라고 생각하시면 편해요. 일종의 국룰? 같은거로 생각하시면 됩니다. 왜냐하면 코드 읽는 입장에서는 코드 읽으면서 특정 변수도 계속 기억해야하는 상황이기 때문에 코드 이해하는 속도가 느려진다고 생각하시면 좋아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아아 저는 다시 변수를 선언하는 것이 오히려 불필요한 과정이라고 생각했었는데 오히려 가독성 부분에선 리뷰어님의 말씀이 맞는 거 같습니다. 기억해 놓겠습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
개발은 읽기 쉬운 코드, 관리하기 쉬운 코드가 1순위라고 생각하시면 좋습니다요
| while (!isAll) { | ||
| outputView.askResults(); | ||
| String string = inputView.getScanner().nextLine(); | ||
|
|
||
| isAll = outputView.printRewards(rewards, players, string); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isAll을 계속 가지고 있는 상태로 while문을 돌리는 대신, 차라리 무한루프문을 만들어서 all을 입력할 때 break문으로 탈출하는건 어떨까요??
아래에 적어둔 OutputView 코멘트도 그렇고, 위에 isAll 선언도 그렇고 isAll이 범인이네요 ㅋㅋ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저 혹시 무한루프와 isAll을 가지고 있는 while문에 어떤 차이가 존재하는지 궁금합니다.
printRewards가 all이라면 true를 리턴하는 메소드여서 while문의 조건으로 구조했었는데 저는 무한루프와 큰차이를 모르겠어서 질문드립니다!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드를 읽을 때 변수를 하나 더 기억하고, 관련 메서드를 확인해야하는지의 유무라고 생각하시면 됩니다
앞으로 개발하면서 우리는 새로 작성하는 코드보다 같은 코드를 반복해서 읽는 시간이 많다는 점을 알고 있어야 하는데요
(읽어보면 좋은 글)
이런 맥락으로 생각하면 코드 자체는 isAll이든 무한루프문이든 큰 차이는 없지만, 무한루프문이 코드 읽고 수정하는 입장에서는 하나의 메서드만 봐도 되니 좀 더 관리하기 편한 코드라고 생각하시면 편해요
- isAll을 가지고 있는 while문: isAll을 결정하는
outputView.printRewards(...)내부 코드까지 확인해야함 - 무한루프문:
string == "all"을 통해 break문을 사용하면outputView.printRewards(...)를 선택적으로 볼 수 있는 기회가 주어짐
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아아 넵 감사합니다!! 메소드를 실행하기 전에 if문으로 메소드의 실행여부를 한번 확인하는 로직이 관리하기 편한 코드가 된다는 걸 이해했습니다!
src/main/java/Model/SplitMethod.java
Outdated
| import java.util.regex.Pattern; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class SplitMethod { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
입력값을 모델에서 처리하기 위해 SplitMethod로 만들고, Player, Rewards가 상속하도록 만들었군요?!
그런데 상속의 경우에는 단 하나의 클래스만 상속이 가능하기 때문에 최대한 사용을 지양하는게 좋은 편입니다
(ex. 나중에 여러 종류의 Rewards와 Player가 나와서 최상위 클래스가 필요하다면?)
Player, Rewards 코드는 최대한 유지하면서 extends를 사용 안하게끔하는게 뭐가 있을까 고민해봤는데, splitMethod의 역할은 입력값을 정상적인 값들만 리스트 형태로 변환해서 반환하는 메서드이므로 여러 곳에 사용이 가능하니 유틸 클래스라고 생각할 수 있어보여요
그리고 SplitMethod를 Model에서 처리하는게 아니라 Controller에서 사용해서 Player와 Rewards에서는 배열로 파라미터를 받아서 처리하면 model은 깔끔한 코드가 유지될 것 같습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 반영해보겠습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/main/java/view/OutputView.java
Outdated
| System.out.println("결과를 보고 싶은 사람은?"); | ||
| } | ||
|
|
||
| public boolean printRewards(Rewards rewards, Player players, String inputNames) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OutputView는 단순히 출력해야하는 목적만 가지고 있으면 베스트인데, 여기서 all을 입력했는지 or 안했는지도 판단해서 boolean을 반환하고 있네요. 요거는 위에 isAll 관련 코멘트 해결하면 같이 해결될 것으로 보이네요
추가로 단순 출력 목적만 생각하면 지금처럼 if문으로 나누기보다는 all을 출력하는 메서드와 사용자를 출력하는 메서드 두가지로 나눠서 만들 수도 있을 것 같네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 수정하겠습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/main/java/Model/Rewards.java
Outdated
| public String getRewardskey(int index) { | ||
| return rewards.get(index); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rewards는 Players의 이름 순서와 Rewards의 보상 순서가 서로 매칭된다는 내용을 알고 있어야 이해할 수 있는 코드인데요
Rewards가 이름과 보상 모든 정보를 가지고 있으면 위 히스토리를 몰라도 독립적으로 사용할 수 있어보여요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/main/java/Model/Player.java
Outdated
| public void playerOnDestination(Bridge bridge) { | ||
| LadderDescentService descentService = new LadderDescentService(bridge); | ||
|
|
||
| for (String player : players) { | ||
| destinatioinPos.add(descentService.descent(players.indexOf(player))); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 수정하겠습니다!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/main/java/Model/Bridge.java
Outdated
|
|
||
| public class Bridge { | ||
|
|
||
| private final List<List<BridgeStep>> rows; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2차원 배열보다는 List<BridgeStep>을 한 번 더 감싼 BridgeLine 같은 객체가 있으면 좋아보여요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 수정하겠습니다!
|
|
||
| import java.util.List; | ||
|
|
||
| public class LadderDescentService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
로직 깔끔해서 좋네요 👍👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨어요 현진님 🥳 리뷰 남겼습니다~
반영하시면서 아래 내용도 시간 나실 때 보면 좋아보여요
- 객체지향 SOLID 원칙
- 객체지향의 사실과 오해
- 인프랩 - 테스트 코드를 왜 그리고 어떻게 작성해야 할까? - 테스트 코드를 왜 작성하는 것인가? 항목
- 토스ㅣSLASH 21 - 실무에서 바로 쓰는 Frontend Clean Code
(프론트 코드는 몰라도 알갱이 내용은 좋아서 배속으로 보시는거 추천드려요) - 망나니 개발자 - [개발서적] 좋은 코드, 나쁜 코드 핵심 내용 정리 및 요약
| Rewards rewards = getRewards(); | ||
|
|
||
| outputView.askLadderHeight(); | ||
| height = inputView.getWidthAndHeight(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
맨위에 있는 height는 여기랑 합치면 좋아보여요~
| height = inputView.getWidthAndHeight(); | |
| int height = inputView.getWidthAndHeight(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정하겠습니다!
| private static List<String> split(String input) { | ||
|
|
||
| final Pattern DELIMITER = Pattern.compile(","); | ||
|
|
||
| if (input == null || input.isEmpty()) { | ||
| return Collections.emptyList(); | ||
| } | ||
|
|
||
| return DELIMITER.splitAsStream(input) | ||
| .map(String::trim) // 양쪽 공백 제거 | ||
| .filter(name -> !name.isEmpty()) // 빈 값 제거 (예: "neo,,brie") | ||
| .collect(Collectors.toList()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
헙 저는 SplitMethod.java는 그대로 두고 Controller에서 SplitMehtod.split(...)을 사용하는걸 생각했는데 Controller 안에 메서드를 넣으셨군요. 요것도 괜찮아보여요
|
|
||
| inputView.getScanner().nextLine(); | ||
|
|
||
| while (true) { | ||
| outputView.askResults(); | ||
| String string = inputView.getScanner().nextLine(); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while문 밖에 inputView.getScanner().nextLine(); 코드가 있어서 확인해보니 outputView.askResults();가 출력되기도 전에 먼저 줄바꿈을 입력 받게 되는 케이스가 있네요
찾아보니 해결방법이 inputView getWidthAndHeight 내부 로직을 nextInt() 대신 nextLine()으로 String으로 값을 받아 int 형으로 변환을 해주면 while문 밖의 코드도 사라질 것 같아요
이게 대표적으로 사연 있는 코드인데, 최대한 사연 없는 코드로 만들어주시는게 좋습니다 😄
원래 코드에서는 없어야만하는 코드인데, 다른 방법으로 해결하지 못하는 내용이라면 먼저 코멘트로 알려주는게 좋아요
| public Bridge(int height, int width) { | ||
| this.rows = new ArrayList<>(); | ||
| initializeBridgeRows(height, width); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거는 생성자 방식으로 만들기보다 정적 팩토리 메서드 방식으로 만드는게 좋아보여요~
| public class Player { | ||
| List<String> players; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
객체명은 플레이어라는 단수지만, 내부는 플레이어들이라는 복수형을 사용하고 있네요
요런 내용은 일급 컬렉션으로 따로 단수 객체는 단수 객체로, 복수 객체는 일급 컬렉션으로 나눠주면 좋습니다~
이렇게 나누게 되면 Players가 할 수 있는 내용이랑 Player만 할 수 있는 메서드로 나뉘게 되는데요
코드 반영하기엔 시간이 오래 걸릴 것 같아 상상 코딩을 하자면 아래 메서드를 각각 어느 클래스에 둘 수 있을까요??
Controller에서는 지금처럼 무조건 Players만 호출이 가능하다고 가정해봅시다
- getPlayers
- getPlayersNumber
- getPlayerName
- getPlayerIndex
| // then | ||
| assertEquals("꽝", rewards.getReward(0)); | ||
| assertEquals("5000", rewards.getReward(1)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기는 Assertion과 SoftAssertion에 대한 차이점을 확인해보고, SoftAssertions 활용하면 좋아보여요~
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기 링크 참고하셔서 인텔리제이에서 설정 추가해주시면 좋아요~
| private Bridge createTestBridge(List<BridgeStep> steps) { | ||
| return new Bridge(Collections.singletonList(new BridgeRow(steps.size(), new Random()) { | ||
| @Override | ||
| public List<BridgeStep> getSteps() { | ||
| return steps; | ||
| } | ||
| })); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기는 BridgeRow.generateRandomRow(..)의 랜덤으로 인해 값이 정해진 사다리를 만들 수 있게 해둔 메서드로 보이네요
사실 리뷰 마지막에 고민해보시라고 코멘트 남기려고 했었지만, 지금 관련 코드가 있으니 지금 이야기 해볼게요 😁
프로덕션 코드가 Random에 의존하게 된다면 Bridge에서 테스트 코드를 만들기도 어렵고, Bridge를 사용하는 다른 테스트 클래스에서도 어려움이 발생하는데요
예시
- BridgeRowTest: 사다리 생성에서 제일 중요한 로직들이 모여있는데 Random에 의존하는 내용이 많아 테스트 불가능
- BridgeStepTest: createRandomStep처럼
true면 EXIST 반환,false면 NONE을 반환하는지 테스트 불가능 - LadderDescentServiceTest: 사다리 결과 계산 테스트가 틀리면 사다리 생성 로직을 배제할 수 없어서 사다리 생성 코드도 확인하게 됨
지금은 createTestBridge로 getSteps만 호출되기에 임시방편으로 해결했지만, 근본적으로 Bridge에 대한 객체가 정상적으로 만들어지지 않았으니, 만약 다른걸 호출하는 케이스가 있으면 문제가 될 수 있을 것 같아요
그래서 자동차 경주 미션에서 전략 패턴을 사용한 것처럼 Random 대신 다른 것도 갈아 끼울 수 있도록 방식을 사용하는게 좋아요~
참고로 createTestBridge를 사용하는 방식은 mock 테스트라고 부르는데, 지금 미션에서 쓰일만한 방식은 아닌 것 같네요
| public Bridge(List<BridgeRow> rows) { | ||
| this.rows = rows; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 생성자는 테스트 코드만을 위한 생성자인데, 테스트 코드만을 위한 코드를 만드는게 좋은가?에 대해서는 다른 분들이랑 이야기 해볼만한 주제인 것 같아요~
| @Test | ||
| @DisplayName("'all' 입력 시 모든 결과를 출력한다") | ||
| void printAllResultsTest() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이제 outputView 로직에 대한 고민을 해보면 좋아보이네요
현재 outputView에서 printAllResults, printSpecificResults에서 사다리, 플레이어, 보상 결과 데이터를 조립해서 출력하고 있는데, View라는 목적을 가진 클래스가 내부에서 조립해서 보여준다는건 단순히 출력해주는 역할에서 벗어난 것 같아요
만약 수정한다면 어떻게 수정하는게 좋을까요?

안녕하세요! 다빈님 사다리 미션 잘 부탁드립니다!!
코드 설명
Application.java: 프로그램의 시작점입니다. 전체 게임의 흐름을 제어합니다.controller패키지:Controller.java: 사용자의 입력을 받아 Model을 업데이트하고, 결과를 View에 전달하는 등 게임의 핵심 로직을 관리합니다.model패키지: 게임의 데이터와 비즈니스 로직을 담당합니다.Player.java: 게임에 참여하는 플레이어들의 정보를 관리합니다.Rewards.java: 사다리 게임의 결과로 주어지는 보상 정보를 관리합니다.Bridge.java: 전체 사다리의 구조를 나타냅니다. 가로 줄(BridgeStep)들의 리스트로 구성됩니다.BridgeStep.java: 사다리의 한 칸이 가로 줄을 가지고 있는지 여부(EXIST또는EMPTY)를 나타내는 Enum입니다.LadderDescentService.java: 플레이어가 사다리를 내려가는 과정을 처리하는 서비스 클래스입니다.SplitMethod.java: 사용자 입력을 쉼표 기준으로 분리하는 유틸리티 클래스입니다.view패키지: 사용자 인터페이스(입력/출력)를 담당합니다.InputView.java: 사용자로부터 플레이어 이름, 보상, 사다리 높이 등의 입력을 받습니다.OutputView.java: 게임 진행 상황, 사다리 모양, 최종 결과 등을 콘솔에 출력합니다.궁금한 점
각 사다리가 연결이 안되는 구조 발생 시키지 않는 로직 설계
지금 코드에선 Bridge클래스에서 무조건 랜덤한 값을 기준으로 생성 유무를 판단하고 있어서 만약 같은 열에 모두 NONE(0)이 된다면 이론상 사다리간 다리가 놓이지 않는 구조가 나옵니다. 이러한 경우를 없앨 수 있는 논리적 구조가 어떻게 구현 가능 할 지 궁금합니다.
테스트 코드 작성 기준 및 케이스 나누기
요번 미션을 진행하며 테스트 코드를 작성할 때 제미나이의 도움을 아주 많이 받으면서 작성했습니다. 특히 어떤 케이스를 테스트를 해야하나 기준을 나누는 것이 어려운 것 같습니다. 어떤 식으로 학습하고 테스트 코드를 작성 해야 하는지 궁금합니다
rewards.getRewardskey(players.getDestinatioinPos(trimmedName))간소화 방법OutputView.java의 메소드인printRewards.java가 매우 비효율적으로 어떤 값에 도달 했는지 판단하고 있다고 생각이 듭니다. 위와 같은 방식에서 도착 지점 클래스 값들을 관리 하는 클래스를 다시 만들어야 하는지 아니면OutputView.java에서 호출 해도 되는 지 궁금합니다