Skip to content
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

[LBP] 박세은 사다리 1단계 제출합니다. #36

Open
wants to merge 6 commits into
base: seun0123
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
implementation 'org.slf4j:slf4j-api:2.0.9'
implementation 'org.slf4j:slf4j-simple:2.0.9'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
}

test {
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import controller.LadderController;
import dto.LadderDto;
import utils.exception.ExceptionHandler;
import view.LadderView;

public class Application {
public static void main(String[] args) {
try {
LadderController ladderController = new LadderController(4, 4);
LadderDto ladderDto = ladderController.getLadderData();
LadderView.printLadder(ladderDto);
} catch (Exception e) {
ExceptionHandler.handleException(e);
}
}
}
16 changes: 16 additions & 0 deletions src/main/java/controller/LadderController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package controller;

import domain.Ladder;
import dto.LadderDto;

public class LadderController {
private final Ladder ladder;

public LadderController(int width, int height) {
this.ladder = Ladder.of(width, height);
}

public LadderDto getLadderData() {
return LadderDto.from(ladder);
}
}
53 changes: 53 additions & 0 deletions src/main/java/domain/Ladder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package domain;

import utils.RandomUtil;
import utils.generator.LadderGenerator;
import java.util.List;
import java.util.stream.IntStream;

public class Ladder {
private final Lines lines;

private Ladder(Lines lines) {
this.lines = lines;
}

public static Ladder of(int width, int height) {
return new Ladder(LadderGenerator.generate(width, height));
}

public Lines getLines() {
return lines;
}

public static void validate(List<Line> lines, int width) {
IntStream.rangeClosed(0, width)
.forEach(i -> validateColumn(lines, i, width));
}

private static void validateColumn(List<Line> lines, int col, int width) {
boolean emptyColumn = lines.stream().noneMatch(line -> hasBridgeAt(line, col, width));
if (emptyColumn) {
int randomIndex = RandomUtil.nextInt(lines.size());
connect(lines, randomIndex, col, width);
}
}

private static boolean hasBridgeAt(Line line, int col, int width) {
if (col == 0) return line.hasBridgeAt(col);
if (col == width) return line.hasBridgeAt(col - 1);
return line.hasBridgeAt(col - 1) || line.hasBridgeAt(col);
}

private static void connect(List<Line> lines, int randomIndex, int col, int width) {
Line oldLine = lines.get(randomIndex);

int index = col;
if (col == width) {
index = col - 1;
}

Line updatedLine = oldLine.setBridgeAt(index);
lines.set(randomIndex, updatedLine);
}
}
56 changes: 56 additions & 0 deletions src/main/java/domain/Line.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package domain;

import utils.RandomUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;

public class Line {
private final List<Boolean> points;

public Line(List<Boolean> points) {
this.points = List.copyOf(points);
}

public List<Boolean> getPoints() {
return points;
}
Copy link

Choose a reason for hiding this comment

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

저번 리뷰와 동일합니다 외부에서 변경되면 어떡하죠..? 🤔


public boolean hasBridgeAt(int index) {
return points.get(index);
}

public Line setBridgeAt(int index) {
List<Boolean> newPoints = new ArrayList<>(points);
newPoints.set(index, true);
return new Line(newPoints);
}
Comment on lines +25 to +29
Copy link

Choose a reason for hiding this comment

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

생성자에서도 생성할 수 있고 setBridgeAt()을 통해서도 Line이 생성될 수 있는데
Line을 2가지 방법으로 생성할 수 있게 되는데 이렇게 작성하신 이유가 있을까요?


public static void applyBridges(List<Boolean> points, Set<Integer> reserved, Line prev, boolean isReserved) {
IntStream.range(0, points.size()).forEach(i -> {
boolean shouldAddBridge = (isReserved && reserved.contains(i)) || (!isReserved && RandomUtil.nextBoolean());

if (shouldAddBridge && isValidBridgePosition(points, prev, i)) {
points.set(i, true);
}
});
}
Comment on lines +31 to +39
Copy link

Choose a reason for hiding this comment

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

static 메서드가 매개변수로 참조값을 받고 있어요, 이는 위험한 설계가 될 수 있을 것 같아요
해당 리뷰를 참고하시면 도움이 될 수 있을 것 같아요


public static void ensureOneBridge(List<Boolean> points, Line prev) {
if (points.contains(true)) return;

IntStream.range(0, points.size())
.filter(i -> isValidBridgePosition(points, prev, i))
.findFirst()
.ifPresent(i -> points.set(i, true));
}

private static boolean isValidBridgePosition(List<Boolean> points, Line prev, int index) {
if (prev != null && prev.hasBridgeAt(index)) return false;
if (index > 0 && points.get(index - 1)) return false;
if (index < points.size() - 1 && points.get(index + 1)) return false;
return true;
}
}
15 changes: 15 additions & 0 deletions src/main/java/domain/Lines.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package domain;

import java.util.List;

public class Lines {
private final List<Line> lines;

public Lines(List<Line> lines) {
this.lines = List.copyOf(lines);
}

public List<Line> getLines() {
return lines;
}
Comment on lines +5 to +14
Copy link

Choose a reason for hiding this comment

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

아직 dto의 요구사항을 수행하고 있는 것 같은 모델이 보여요 🤔🤔

}
26 changes: 26 additions & 0 deletions src/main/java/dto/LadderDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dto;

import domain.Ladder;
import domain.Line;
import java.util.List;
import java.util.stream.Collectors;

public class LadderDto {
private final List<List<Boolean>> ladderData;

public LadderDto(List<List<Boolean>> ladderData) {
this.ladderData = ladderData;
}

public static LadderDto from(Ladder ladder) {
return new LadderDto(
ladder.getLines().getLines().stream()
.map(Line::getPoints)
.collect(Collectors.toList())
);
}
Comment on lines +11 to +21
Copy link

Choose a reason for hiding this comment

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

마찬가지로 해당 dto는 정적 팩토리 메서드를 도입했지만 생성자를 활용해서도 사용이 가능한것으로 보여요 🥲


public List<List<Boolean>> getLadderData() {
return ladderData;
}
Comment on lines +23 to +25
Copy link

Choose a reason for hiding this comment

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

해당 중첩 리스트도 외부에서 호출하여 변경 가능성에 취약한 것 같아요 개선해봅시다!

}
15 changes: 15 additions & 0 deletions src/main/java/utils/RandomUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package utils;

import java.util.Random;

public class RandomUtil {
public static final Random random = new Random();

public static boolean nextBoolean() {
return random.nextBoolean();
}

public static int nextInt(int bound) {
return random.nextInt(bound);
}
}
13 changes: 13 additions & 0 deletions src/main/java/utils/exception/ExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package utils.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);

public static void handleException(Exception e) {
System.err.println("시스템 오류 : " + e.getMessage());
logger.error("시스템 오류 : ", e);
}
Comment on lines +9 to +12
Copy link

Choose a reason for hiding this comment

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

ExceptionHandler를 통해서 모든 예외를 "시스템 오류"라고 단정하는 것으로 보여요.
"시스템 오류"라고 한 이유가 있을까요??

}
9 changes: 9 additions & 0 deletions src/main/java/utils/generator/LadderGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package utils.generator;

import domain.Lines;

public final class LadderGenerator {
Copy link

Choose a reason for hiding this comment

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

public final class로 작성하신 이유가 궁금합니다

public static Lines generate(int width, int height) {
return LineGenerator.generate(width, height);
}
}
34 changes: 34 additions & 0 deletions src/main/java/utils/generator/LineGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package utils.generator;

import domain.Ladder;
import domain.Line;
import domain.Lines;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public final class LineGenerator {
public static Lines generate(int width, int height) {
List<Set<Integer>> reserved = ReservedPositionGenerator.generate(width - 1, height);
List<Line> lines = generateLines(width, height, reserved);
Ladder.validate(lines, width - 1);
return new Lines(lines);
}

private static List<Line> generateLines(int width, int height, List<Set<Integer>> reserved) {
List<Line> lines = new ArrayList<>();
for (int row = 0; row < height; row++) {
Line previous = getPreviousLine(lines, row);
Line line = SingleLineGenerator.generate(width - 1, reserved.get(row), previous);
lines.add(line);
}
return lines;
}

private static Line getPreviousLine(List<Line> lines, int row) {
if (row == 0) {
return null;
}
return lines.get(row - 1);
}
Comment on lines +28 to +33
Copy link

Choose a reason for hiding this comment

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

위의 리뷰와 마찬가지로 static메서드가 참조값을 받아오고 있네요
왜 static 메서드가 인스턴스의 상태를 가지면 안될까요?

}
27 changes: 27 additions & 0 deletions src/main/java/utils/generator/ReservedPositionGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package utils.generator;

import utils.RandomUtil;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public final class ReservedPositionGenerator {
public static List<Set<Integer>> generate(int width, int height) {
List<Set<Integer>> reserved = initializeReservedPositions(height);
applyRandomReservations(reserved, width, height);
return reserved;
}

private static List<Set<Integer>> initializeReservedPositions(int height) {
return IntStream.range(0, height)
.mapToObj(i -> new HashSet<Integer>())
.collect(Collectors.toList());
}

private static void applyRandomReservations(List<Set<Integer>> reserved, int width, int height) {
IntStream.range(0, width)
.forEach(i -> reserved.get(RandomUtil.nextInt(height)).add(i));
}
}
20 changes: 20 additions & 0 deletions src/main/java/utils/generator/SingleLineGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package utils.generator;

import domain.Line;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class SingleLineGenerator {
public static Line generate(int width, Set<Integer> reserved, Line prev) {
List<Boolean> points = new ArrayList<>(Collections.nCopies(width, false));

Line.applyBridges(points, reserved, prev, true);
Line.applyBridges(points, null, prev, false);
Line.ensureOneBridge(points, prev);

return new Line(points);
}
Comment on lines +10 to +18
Copy link

Choose a reason for hiding this comment

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

여기도!


}
29 changes: 29 additions & 0 deletions src/main/java/view/LadderView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package view;

import dto.LadderDto;

import java.util.List;

public class LadderView {
private static final String BRIDGE = "-----|";
private static final String SPACE = " |";
private static final String BAR = "|";

public static void printLadder(LadderDto ladderDto) {
ladderDto.getLadderData().forEach(LadderView::printLine);
}

private static void printLine(List<Boolean> line) {
System.out.print(BAR);
line.forEach(LadderView::printPoint);
System.out.println();
}

private static void printPoint(Boolean point) {
if (point) {
System.out.print(BRIDGE);
return;
}
System.out.print(SPACE);
}
}