-
Notifications
You must be signed in to change notification settings - Fork 60
[그리디] 강동현 사다리 미션 제출합니다. #80
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: mintcoke123
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.
안녕하세요, 동현님 :)
리뷰가 늦어 죄송합니다 🥹
그치만,, 힘내서 열심히 달려봐요! 🏃♂️
첫 번째 리뷰라서 우선은 프로덕트 코드 먼저 리뷰 남기도록 하겠습니다!
전체 리뷰
-
코드 정렬 및 개행
전체적으로 코드 정렬 및 개행이 일관적이지 않은데,- 윈도우 : Crlt + Alt + L
- 맥 : Command + Option + L
이 단축키를 활용해서 각 파일의 코드를 정렬시키는 것은 어떨까요?
또한, 개행이 불필요하게 들어가 있는 부분이 꽤 있는 것 같습니다! 제거하면 좋을 것 같아요. -
안 쓰이는 메서드들이 꽤 보이는 것 같습니다. 인텔리제이 기준으로 아래와 같이 회색으로 뜨는 변수나 메서드들은 쓰이지 않는 것들인데요. 다 제거해주시는 게 어떨까요?

-
비즈니스 규칙
현재 동현님의 코드에서는 정사각형 모양의 사다리만 정상 작동하는데요,
4단계 미션 예시에서4명의 사람을 위한 5개 높이 사다리를 만들 경우처럼
플레이어 수보다 높이가 더 높을 경우도 사다리 생성이 완료되어야 할 것 같습니다!

-
결과 출력 오류
- 사다리 높이 입력 후 엔터를 치면 해당 아무 입력도 없었는데 자동으로
해당 유저가 존재하지 않습니다.
이런 문구가 나타납니다. 이유가 무엇인지 찾아보면 좋을 것 같습니다. - 입력으로 all이 들어왔을 때의 로직이 동작하지 않는 것 같아요!
- 사다리 높이 입력 후 엔터를 치면 해당 아무 입력도 없었는데 자동으로
| } | ||
|
|
||
| public void run() { | ||
| List<String> players = getPlayers(); |
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.
사다리 게임에 참여하는 사람에 이름을 최대 5글자까지 부여할 수 있다.
사다리를 출력할 때 사람 이름도 같이 출력한다.
위 내용은 미션 요구사항 중 하나인데요,
- 동현님은 List players와 같이 원시 컬렉션을 그대로 사용하고 있습니다. 현재 코드에서 위의 요구사항 내용을 구현하려면 어느 클래스에서 검증하면 좋을까요?
- 또한 List는 수정이 가능합니다. 만약 이 Player 리스트를 다른 객체에 넘기는 경우 실수로 값을 추가하거나, 삭제하게 된다면 원본 데이터가 손상될 수도 있을 것 같아요!
- 또한 List이라는 타입만 봐서는 의미가 명확하지 않을 수도 있습니다.
- Controller에
findPrizeForSelectedPlayer메서드는 컨트롤러가 직접 플레이어를 찾고 있습니다. 이는 게임 진행과도 직접적으로 연관되어 있는 부분을 컨트롤러에서 담당하고 있다고도 보여집니다. 어떻게 생각하시나요?
→ 이 모든 것을 해결할 수 있는 방법은 무엇일까요?
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.
또한 prizes역시 일급 컬랙션을 사용하도록 변경하였습니다!
| if(selectedPlayer=="all") outputView.printAllResultMessage(calculatedResult); | ||
| else if(calculatedResult.containsKey(selectedPlayer)){ | ||
| outputView.printSingleResultMessage(calculatedResult.get(selectedPlayer)); | ||
| } | ||
| else{ | ||
| outputView.printInvalidSelectedPlayerMessage(); | ||
| } |
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.
else를 사용하지 않고도 해당 로직이 동작하게 만들 수 있을 것 같습니다.
추가적으로 플레이어를 비교할 때 == 를 사용하여 비교하셨는데,
equals 가 아닌 해당 연산자를 사용하신 이유가 궁금합니다!
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.
조건문 분기 후 바로 return으로 매서드를 종료하면 더 가성비가 좋을 것 같습니다!
또한 ==와 equals에 관해서는, 큰 생각이 없이 코드를 짰었습니다..😢
찾아보니 ==는 주소를 비교하는군요!
코드의 의미를 생각하면 NullPointerException을 방지하기 위해서라도 equals로 수정할 예정입니다!
src/main/java/domain/Ladder.java
Outdated
| } | ||
|
|
||
| private void validateCols(int cols) { | ||
| if (cols < 2) throw new IllegalArgumentException("사다리 너비(cols)는 2 이상이어야 합니다."); |
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 조건문 내부 문장이 하나일 경우라도 괄호를 붙이는데요, 이유는 유지 보수를 하다가 만약 추가적으로 조건문 내부에 문장을 추가해야 하는 경우 다시 괄호를 붙여야 해서 귀찮아지기도 하고 가독성 또한 한 줄로 쓰는 것보다 괄호로 묶는 것이 조금 더 낫다고 생각해서 입니다. (알고리즘 풀 때는 한 줄로 쓰긴 해요 ㅎㅎ) 동현님의 생각은 어떠신가요?
private void validateCols(int cols) {
if (cols < 2) {
throw new IllegalArgumentException("사다리 너비(cols)는 2 이상이어야 합니다.");
}
}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 final String LadderVertical = "|"; | ||
| private static final String LadderHorizontal = "-----"; | ||
| private static final String EmptyHorizontal = " "; |
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.
LadderBuilder 는 도메인 패키지에 위치해있습니다.
만약 사다리의 모양이 “|- - - - -|” → “|~ ~ ~ ~ ~|” 이런식으로 변경된다면 저라면 도메인보다는 뷰 패키지를 먼저 찾을 것 같습니다. 그렇다면 스트링 상수들은 도메인 모델에 어울리는 상수들인지 고민해보는 것은 어떨까요?
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.
그렇네요..
"이중리스트를 받아 StringBuilder로 사다리(string)를 만드는 로직"이 복잡하다고 생각해,
view에서 사용할 가능성을 생각 못했습니다.
협업하는 사람의 입장에서 생각을 못한 것 같습니다.
상수,로직의 위치를 리팩토링하겠습니다!
src/main/java/domain/LinePoints.java
Outdated
| import java.util.List; | ||
|
|
||
| public class LinePoints { | ||
| private final List<Boolean> points; |
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.
Boolean에서 true면 [이동 가능], false면 [이동 불가]로 로직을 작성해주신 것 같습니다!
모든 원시 값과 문자열을 포장한다.
그런데 요 규칙 기억나시나요?! 원시값이 포장되지 않은 상태인 것 같아요. ‘원시값을 포장한다는 게 어떻게 보면 귀찮기도 하고 오히려 너무 과도한 분리가 될 수도 있는데 굳이 왜 하라는 거지?’ 라고 저도 처음엔 그렇게 생각했었는데요, 사다리 미션을 하면서 필요성을 깨닫게 된 것 같아요.
코드를 처음 본 사람 입장에서는 사실 true가 뭐고 false가 뭔지 유추할 뿐이지 확신하기 위해서는 내부 동작 로직을 열어봐야 합니다. 이를 방지하기 위해 true와 false보다는 읽었을 때 바로 “연결”인지 “비연결”인지 알 수 있으면 어떨까요?
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.
원시값의 포장을 간과했네요..
이미 일급컬렉션 안에 일급컬렉션이 존재하는 상황에서, 그 안의 값을 포장하는 것을 생각 못했습니다.
리뷰어님 멘트를 생각해보면서 '너무 많은 컬렉션이 중첩되면 가시성이 오히려 떨어지지 않을까?'라는 생각이 들었었는데,
오히려 원시값을 PointConnection으로 포장하면
LinePoints linePoints = new LinePoints(points);
if (linePoints.getPoints().get(0).isConnected()) { //isConnected
...
}와 같이 가시성이 늘 수도 있을 것 같습니다!
해당 방향으로 수정하겠습니다!
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.
지난 로또 미션에서 학습했던 Enum을 활용해보는 건 어떨까요?
connected 필드를 Enum으로 정의하면 CONNECTED, DISCONNECTED 같은 상수로 상태를 더 명확하게 표현할 수 있습니다.
(또한 여유가 되신다면 이번 미션에서 함수형 프로그래밍을 적용해볼 만한 부분이 있는지도 함께 고민해보면 좋을 것 같습니다!)
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.
ConnectionStatus enum을 추가하여 상태를 상수로 표현했습니다.
이 방식을 적용하니 다른 파일들에서도 상태를 CONNECTED, DISCONNECTED처럼 명확하게 표기할 수 있어 가독성이 향상된 것 같습니다.
질문
다만, enum의 역할이 단순한데도 별도의 파일로 분리하면서 코드 해석 시 오히려 불필요한 파일 해석 시간(탐색 과정)이 늘어난 건 아닌지 고민됩니다.
이 경우에도 enum을 사용하는 것이 적절한 선택일까요?
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.
아아 제 코멘트가 좀 모호했나 봐요!
제가 원시값 포장이라고만 남겨서 동현님이 PointConnection이라는 래퍼 클래스를 만들어주신 것 같아요.
사실 제 원래 의도는boolean 같은 원시값을 다루는 방법이 두 가지가 있다는 걸 말씀드리고 싶었어요.
- 동현님이 하신 것처럼
PointConnection같은 클래스로 포장해서 의미를 부여하는 방법 true/false가 나타내는 상태 자체를CONNECTED/NOT_CONNECTED같은 상수로 만드는 방법
PointConnection 클래스 자체를 아예 enum으로 만들어보는 건 어떨까 했습니다.
ENUM의 역할이 단순하다고 하셨는데, 이렇게 구현하면 ConnectionStatus 같은 별도의 enum을 만들 필요 없이 상태 표현과 관련된 로직(ex : 연결되었는가?, 다음 생성 가능한 상태는 무엇인가?')을 enum이 스스로 갖게 할 수 있습니다. 그러면 파일 수를 줄이면서도 의미적으로 더 응집력 있는 구조가 될 것 같아요.
✚ (참고) 또한 더 나아가 함수형 프로그래밍의 예시를 보여드리자면,
public enum PointConnection {
CONNECTED(true), // 연결된 다리
DISCONNECTED(false); // 빈 공간
private final boolean movable;
LadderBridge(boolean movable) {
this.movable = movable;
}
public boolean canMove() {
return this.movable;
}
/**
* 이전 Step을 기반으로 다음 Step을 생성
*/
public static LadderBridge createNextRandom(LadderBridge previousStep) {
// 이전 스텝이 연결(CONNECTED)이었다면, 다음은 무조건 빈 공간(DISCONNECTED)
if (previousStep == CONNECTED) {
return DISCONNECTED;
}
// 그 외에는 랜덤하게 결정
return (Math.random() < 0.5) ? CONNECTED : DISCONNECTED;
}
}LinePointsGenerator 같은 곳에서 boolean 대신 이 LadderBridge enum을 직접 사용하면, 코드가 훨씬 명확해지고, '연결된 다리 다음엔 연결될 수 없다'는 핵심 비즈니스 로직도 LadderBridge라는 enum이 스스로 갖게 할 수 있죠.
리뷰를 주고 받은 시간이 꽤 흘렀기도 했고, 함수형 프로그래밍 학습테스트를 보지 못하셨다면 바로 적용하기는 어려울 것 같아서 위의 예시는 참고만 해주셔도 될 것 같습니다!
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.
오 그렇군요!
enum이 상태와 규칙을 함께 가지는 것이 좋다는 코멘트를 다빈 리뷰어님께 받았었는데, 이번 미션에 적용할 생각을 하지 않은 것 같습니다!
다음 미션을 진행할 때에는 꼭 염두해두겠습니다!
| public int changeRowLocation(int colIndex, LinePoints linePoints) { | ||
| List<Boolean> p = linePoints.getLinePoints(); | ||
| int size = p.size(); | ||
|
|
||
| if (colIndex > 0 && p.get(colIndex - 1)) return colIndex - 1; | ||
|
|
||
| if (colIndex < size && p.get(colIndex)) return colIndex + 1; | ||
|
|
||
| return colIndex; | ||
| } |
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.
이 함수는 지금 linePoints에서 List 형태로 꺼내와서 p라고 이름 지은 다음에, 움직여야 할지 말지를 p에서 또 get으로 꺼내와서 판단하고 있는 것 같아요. 저희가 스터디 시간에 몇 번 다룬 적이 있었는데, 디미터의 법칙을 기억하시나요?
현재 동현님의 사다리 관련 클래스들은 모두 검증, 저장, 꺼내오기를 제외하면 별다른 일을 하고 있지 않은 것 같습니다. LadderResultCalculator 클래스의 일들 중에서 각 객체가 가진 값을 확인하고 검사하는 일은 해당 객체가 하도록 분담하면 어떨까요?
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.
다시보니 결합도가 높은 상태인 것 같습니다.
calculator → ladder → line → point 식으로 접근하여 리팩토링이 힘들어지겠네요..
위치가 이동하는 판단은 LinePoints나 Ladder가 맡도록 하여 디미터의 법칙을 지키겠습니다!
해당 방식으로 수정하겠습니다!
위 부분은 해결하여 커밋했습니다!
쓰이지 않는 변수나 메서드는 제거하거나, 혹은 활용하겠습니다!
세상에..로직을 이상하게 짰네요...
말씀주신 부분들 토대로 추측해봤습니다. |
|
결과 출력 오류에 대해서는, |
SANGHEEJEONG
left a comment
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/domain/Ladder.java
Outdated
| } | ||
| } | ||
|
|
||
| } 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.
[EOF]
Setting > Editor > General > Ensure every saved file ends with a line break
적용해주시면 좋을 것 같습니다!
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.
eol이 자동으로 적용되도록 설정을 수정했습니다!
src/main/java/domain/Players.java
Outdated
| public Players(List<String> rawPlayers) { | ||
| if (rawPlayers == null) { | ||
| throw new IllegalArgumentException("플레이어 목록이 null 입니다."); | ||
| } |
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.
Ladder에서는 예외처리 메서드를 따로 만드셨는데
ex) validateLines(lines, rows);
Player와 Prizes에서는 만들지 않으신 이유가 궁금합니다!
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.
검증로직을 작성하다가, intellij의 자동완성기능을 따르면서 생긴 실수인걸로 기억합니다..
수정했습니다!
| this.ladderGenerator = new LadderGenerator(); | ||
| this.outputView = new OutputView(); | ||
| this.inputView = inputView; | ||
| this.ladderResultCalculator = new LadderResultCalculator(); |
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.
넵! 일관성 측면에서도 그 편이 나을거라고 생각합니다.
수정했습니다!
| public List<String> asList() { | ||
| return 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, Prizes 캡슐화 asList() 메서드가 원본 List를 그대로 반환하면 밖에서 데이터를 함부로 수정할 수 있습니다. Collections.unmodifiableList()로 감싸서 '읽기 전용' 리스트를 반환하도록 만들면 어떨까요? 저희가 일급 컬렉션을 사용함으로써 얻을 수 있는 큰 장점 중 하나라고 생각합니다!
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.
unmodifiableList에 대해 알아봤습니다.
새로운 리스트를 복사하지 않고, 기존 리스트를 감싸는 래퍼를 반환함으로써 읽기 전용 리스트를 만드는군요!
해당 방식을 사용하면 말씀주신대로 일급 컬랙션을 사용함으로써 얻는 이득이 클 것 같습니다!
수정했습니다!
| for (Map.Entry<String, String> entry : result.entrySet()) { | ||
| String player = entry.getKey(); | ||
| String prize = entry.getValue(); | ||
| if (player == null || player.isBlank()) { | ||
| throw new IllegalArgumentException("플레이어 이름이 비어 있습니다."); | ||
| } | ||
| if (prize == null || prize.isBlank()) { | ||
| throw new IllegalArgumentException("결과가 비어 있습니다."); | ||
| } |
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.
이 부분도 validate 메서드로 따로 빼지 않으신 이유가 궁금합니다!
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/domain/LinePoints.java
Outdated
| public LinePoints(List<Boolean> raw) { | ||
| List<PointConnection> converted = new ArrayList<>(raw.size()); | ||
| for (Boolean b : raw) { | ||
| converted.add(new PointConnection(Boolean.TRUE.equals(b))); | ||
| } | ||
| checkNoduplicationTrue(converted); | ||
| this.points = converted; | ||
| } |
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.
LinePoints 생성자에서 List<Boolean>을 받아 List<PointConnection>으로 변환하는 로직이 포함되어 있네요. 현재 LinePoints가 Boolean이 true면 연결된 상태다라는 해석 로직까지 맡고 있는데,
이 로직은 사실상 데이터를 생성하거나 변환하는 책임에 더 가깝습니다.
이미 LinePointsGenerator 클래스가 존재하므로, 이 변환 로직은 LinePointsGenerator로 이동시키고
LinePoints는 처음부터 List을 인자로 받도록 설계하는 것이 어떨까요?
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.
객체의 책임에 대해 생각이 얕았던 것 같습니다.
LinePoints 생성자를 List을 직접 받도록 변경하고, List → List 변환 로직을 LinePointsGenerator로 이동했습니다.
말씀주신 방향으로 수정하였습니다!
| } | ||
| } | ||
| return new LinePoints(points); | ||
| } |
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.
이 생성 로직은 depth가 깊어보입니다!
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.
int index, List pointConnections를 받아 랜덤한 boolean을 return 하는 booleanConnect 메서드를 만들어 기존 메서드에서 분리하였습니다!
수정했습니다!
SANGHEEJEONG
left a comment
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.
이번이 거의 마지막 리뷰가 될 것 같네요
수고 많으셨습니다. 남은 미션도 파이팅!
전체 리뷰
LadderResult 와 LadderResultCalculator 구조
현재 LadderResult는 결과 데이터를 담는 용도이고, LadderResultCalculator는 그 결과를 계산하는 역할을 하고 있습니다. 그런데 두 클래스가 실제로는 사다리 결과를 계산하고 검증하는 과정을 함께 구성하고 있어서 서로 강하게 연결되어 있는 구조로 보입니다. 이 경우에는 굳이 두 클래스로 나누지 않고, LadderResult 내부에 정적 팩토리 메서드(LadderResult.of(ladder, players, prizes)) 형태로 계산 및 검증 로직을 통합하는 것도 고려해볼 수 있을 것 같습니다.
반대로 “계산 로직과 결과 표현을 명확히 분리하고 싶다”는 의도가 있다면 LadderResult 는 단순히 결과를 저장하는 용도로만 사용되고 있으니 record 형태로 더 간결히 정리하는 것은 어떨까요?
| } | ||
|
|
||
| return resultMap; | ||
| } |
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.
calculateResults() 메서드가 한 번에 너무 많은 일을 하고 있는 것 같습니다.
현재 이 메서드에서 입력값 검증, 사다리 이동 계산, 결과 매핑 생성까지 모두 처리하고 있는 것 같아요.
입력 검증(validatePlayersAndPrizes),
사다리 탐색(calculateEndColumn),
결과 매핑(mapPlayerToPrize)
같은 단위로 로직을 분리하면 역할이 더 명확해지고, 테스트나 유지보수도 수월해질 것 같아요!
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.
좋은 생각입니다!
메서드 분리에 대한 생각이 얕았던 것 같네요..
수정했습니다!
좋은 생각입니다! 결과 표현을 나타내는 객체는 record로 표현하는 것이 적절해 보입니다.
|

안녕하세요. 정상희 리뷰어님!
리뷰이로써 만나뵙는건 처음이네요, 잘부탁드립니다!
이번 리뷰 좋은 티키타카가 오갔으면 좋겠습니다~!
===
이번 미션을 진행하면서, 아래와 같은 방식으로 코드 구조를 작성하였습니다!
🤔 고민했던 부분들
사다리 가로줄 구현
처음 코드를 작성할 때에는, 사다리의 가로줄 위치를 저장할 생각을 하지 않고 StringBuilder로 사다리를 만들며 그 반복문 안에 랜덤하게 가로줄을 작성할 예정이었습니다.
하지만 이렇게 하면 사다리의 구조를 재사용하거나 테스트하기 어렵고,
출력 로직과 데이터 로직이 뒤섞여 유지보수가 힘들다는 문제점이 있었습니다.
그래서 이후에는 가로줄의 유무를 논리적으로 먼저 저장하는 구조를 도입했습니다.
LinePoints 클래스를 만들어 한 줄에 대한 boolean 리스트를 관리하고,
각 칸마다 가로줄이 존재하면 true, 없으면 false로 표현했습니다.
이렇게 하면 사다리의 모양을 문자열로 출력하는 대신
데이터로 먼저 모델링할 수 있고, 이후 LadderBuilder가 이 데이터를 바탕으로
실제 문자열 형태(|-----|)의 사다리를 생성하도록 책임을 분리할 수 있었습니다.
결과적으로,
로 나뉘어, 사다리 구조를 테스트하기 훨씬 명확하고 유연하게 구현할 수 있었습니다.
이번 미션 기간 동안 여러 과제와 이사 일정이 겹쳐 충분히 고민하며 진행하지 못한 점이 아쉽습니다.
다만 주말에는 어느정도 여유가 생길 예정이니, 제가 보완하거나 더 깊이 살펴보면 좋을 부분이 있다면 말씀해주시면 감사하겠습니다!