Skip to content

Conversation

@ghtjr410
Copy link

사다리(생성) 과제 제출

안녕하세요!
사다리(생성) 과제 제출합니다.

과제 진행과정

  • 상향식 개발: Name → Names → Height → Line → Lines → Ladder 순서로 TDD 진행
  • 가장 작은 단위(Name)부터 시작하여 점진적으로 조합
  • 스트림과 람다를 적극 활용하려고 노력

고민한 지점

RandomLineGenerator 테스트 방법

저는 항상 테스트 용이성에 대한 고민을 많이합니다.
이번 과제에서도 랜덤 로직을 어떻게 테스트할지 고민했습니다.

방식 문제점
시드 고정 결과 검증일 뿐, 로직 검증 아님
반복 테스트 100% 보장 안 됨

해결: BooleanGenerator 인터페이스를 추출하여 주입

// Before: Random 직접 사용 → 테스트 어려움
public class RandomLineGenerator implements LineGenerator {
    private final Random random = new Random();
    
    public Line generate(int count) {
        // random.nextBoolean() 사용
    }
}

// After: BooleanGenerator 주입 → 테스트 용이
public class RandomLineGenerator implements LineGenerator {
    private final BooleanGenerator booleanGenerator;
    
    public RandomLineGenerator() {
        this(new Random()::nextBoolean);
    }
    
    public RandomLineGenerator(BooleanGenerator booleanGenerator) {
        this.booleanGenerator = booleanGenerator;
    }
}
@Test
void generate_연속true_방지() {
    Iterator<Boolean> values = List.of(true, true, true).iterator();
    BooleanGenerator generator = values::next;
    
    Line line = new RandomLineGenerator(generator).generate(3);
    
    // true를 계속 줘도 연속되지 않음을 증명
    assertThat(line.points()).containsExactly(true, false, true);
}

배운점

테스트 용이성을 위한 설계

랜덤 로직을 직접 테스트하기 어려울 때, 인터페이스로 추출하여 주입하면 핵심 로직만 검증할 수 있다는 점을 배웠습니다.


리뷰 잘 부탁드립니다!

README.md
- 2단계 문서 링크 누락된 부분을 `02-ladder-creation.md`로 정상 연결

docs/02-ladder-creation.md
- 사다리 생성(2단계) 요구사항 문서 신규 추가
- 기능 요구사항, 프로그래밍 요구사항, 실행 예시, 힌트, PR 체크 항목 포함

docs/checklist.md
- 미션 제출 전 체크리스트 문서 신규 추가
- OOP 원칙, 메서드 작성 원칙, TDD 및 테스트 품질 점검 항목 정리
Name.java
- 이름을 표현하는 `Name` 레코드 추가
- null, 빈 문자열, 공백 입력 시 예외 발생하도록 검증 로직 구현

NameTest.java
- 빈 값(Null, Empty, Blank) 입력 시 예외 발생 테스트 추가
- 예외 메시지 검증 포함
Name.java
- 최대 길이 상수 `MAX_LENGTH`(5) 추가
- 이름 공백·null 검증 시 입력값 포함하도록 예외 메시지 개선
- 이름이 5자를 초과할 경우 예외 발생 로직 추가

NameTest.java
- 5자 초과 입력에 대한 예외 발생 테스트 케이스 추가
- 기존 필수값 검증 테스트 유지
Names.java
- 쉼표로 구분된 문자열을 `Name` 리스트로 변환하는 생성자 추가
- 불변 컬렉션 유지를 위해 `List.copyOf` 적용
- `Name` 리스트를 직접 받는 보조 생성자 구현

NamesTest.java
- 문자열 입력을 쉼표 기준으로 파싱하여 `Names` 객체가 올바르게 생성되는지 검증
- `Name` 객체 리스트와의 동등성 비교 테스트 추가
Names.java
- 최소 참가 인원 상수 `MIN_SIZE = 2` 추가
- `validate` 메서드로 null 입력 및 최소 인원(2명) 미만 입력 시 예외 처리
- 불변 리스트 유지 위해 `List.copyOf` 사용

NamesTest.java
- null 리스트 전달 시 예외 발생 테스트 추가
- 참가자 1명 입력 시 예외 발생 테스트 추가
- 기존 쉼표 파싱 테스트 유지
NameTest.java
- 정상 입력("일", "일이삼사오")에 대해 생성자가 예외를 던지지 않음을 검증하는 파라미터 테스트 추가
Line.java
- 연속된 가로선(Boolean true)이 존재할 경우 예외 발생하도록 검증 로직 추가
- varargs 생성자 추가 및 내부 검증 실행

LineTest.java
- 정상 입력 시 Line 생성 성공 여부 검증
- 연속된 가로선 입력 시 예외 발생 테스트 추가
Line.java
- 입력 리스트 null 또는 empty 여부 검증 추가
- 연속된 가로선 검증 로직에서 변수명 정리(points → inputs)

LineTest.java
- 빈값(null, empty) 입력 시 예외 발생 테스트 추가
- 검증 메시지 `"가로선 정보는 필수입니다."` 확인 로직 추가
Height.java
- 최소 높이(MIN_HEIGHT=1) 미만 입력 시 예외 발생하도록 검증 로직 구현

HeightTest.java
- 정상 높이 입력 시 생성 성공 테스트 추가
- 1 미만 입력 시 예외 및 메시지 검증 테스트 추가
LineGenerator.java
- Line 생성을 위한 함수형 인터페이스 정의

Lines.java
- Height와 personCount 기반으로 Line 리스트 자동 생성 로직 구현
- 생성된 Line 리스트 불변화하여 보관

LinesTest.java
- Height 값만큼 Line이 생성되는지 검증 테스트 추가
Line.java
- points 리스트 불변화 처리
- CONNECTED/EMPTY 문자열 상수 추가
- toDisplay() 메서드로 가로선 출력 문자열 생성 기능 구현
- Boolean 값에 따른 segment 변환 로직 추가

LineTest.java
- toDisplay() 결과가 기대 문자열과 일치하는지 테스트 추가
Lines.java
- Lines 전체를 문자열로 변환하는 toDisplay() 메서드 추가
- 각 Line의 toDisplay() 결과를 개행 문자로 이어 붙여 출력

LinesTest.java
- toDisplay()가 기대한 멀티라인 문자열을 생성하는지 검증 테스트 추가
Name.java
- 이름을 6자 고정 길이로 오른쪽 공백을 채워 반환하는 toDisplay() 추가

Names.java
- 각 Name의 toDisplay()를 이어붙여 출력 문자열을 생성하는 toDisplay() 추가

NameTest.java
- toDisplay()가 6자 고정 길이로 공백을 채우는지 검증 테스트 추가

NamesTest.java
- Names의 toDisplay() 결과가 참가자 이름들을 공백 포함 정렬하여 반환하는지 검증 테스트 추가
Line.java
- 세그먼트 문자열(CONNECTED/EMPTY)에 `|` 포함하도록 변경
- toDisplay()에서 구분자 제거 후 연속 문자열로 생성
- 출력 시작 부분을 `"     |"`로 통일하여 정렬 형식 변경

LineTest.java
- 변경된 출력 포맷에 맞춰 toDisplay() 기대값 수정

LinesTest.java
- 여러 줄 출력 시 앞쪽 여백 추가된 새로운 포맷에 맞게 기대값 수정
Ladder.java
- Names와 Lines를 결합한 Ladder 레코드 추가
- names.toDisplay()와 lines.toDisplay()를 조합하여 전체 사다리 출력 문자열 생성

LadderTest.java
- Ladder.toDisplay()가 이름 영역 + 사다리 영역을 올바르게 연결하는지 검증 테스트 추가
BooleanGenerator.java
- 불리언 값을 공급하는 FunctionalInterface 추가

RandomLineGenerator.java
- 연속된 true 방지를 포함한 랜덤 라인 생성 로직 구현
- BooleanGenerator 주입 가능하도록 생성자 오버로드 추가

RandomLineGeneratorTest.java
- 주입된 BooleanGenerator 시퀀스를 사용해 연속 true 방지 동작 검증
Application.java
- 사용자 입력을 받아 Names, Height 생성
- Lines 생성 후 Ladder 구성
- 결과 출력 처리

Names.java
- 참가자 수 반환용 size() 메서드 추가

InputView.java
- 이름 목록 입력 기능 추가
- 사다리 높이 입력 기능 추가

OutputView.java
- 사다리 출력 결과 표시 기능 추가
02-ladder-creation.md
- 참가자 이름/이름 목록 요구사항 정리 추가
- 높이(Height) 검증 및 기능 명세 추가
- Line·Lines 생성 및 출력 규칙 문서화
- LineGenerator·BooleanGenerator·RandomLineGenerator 기능 설명 추가
- Ladder 구성 및 출력 기능 목록 정리
Name.java
- 최대 길이 검증 로직에서 하드코딩된 `5` 제거
- `MAX_LENGTH` 상수를 사용하도록 수정
Copy link
Contributor

@javajigi javajigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 가능한 구조를 만들기 위해 인터페이스로 구현 💯
앞 단계의 미션을 통해 TDD, OOP는 이미 상당 부분의 역량을 쌓은 것 같네요.
이제는 특별히 피드백할 내용이 없네요.

private static final String CONNECTED = "-----|";
private static final String EMPTY = " |";

public Line(Boolean... inputs) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


public record Lines(List<Line> values) {

public Lines(int height, int personCount, LineGenerator generator) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인터페이스 기반으로 개발하고 DI를 통해 주입함으로써 테스트 가능한 구조로 설계 👍

@javajigi javajigi merged commit daaeb6b into next-step:ghtjr410 Dec 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants