[๐ ์ฌ์ดํด2 - ๋ฏธ์ (๊ธฐ๋ฌผ ํ์ฅ + DB ์ ์ฉ)] ๋ฃจ๋๋น์ฝ ๋ฏธ์ ์ ์ถํฉ๋๋ค.#325
[๐ ์ฌ์ดํด2 - ๋ฏธ์
(๊ธฐ๋ฌผ ํ์ฅ + DB ์ ์ฉ)] ๋ฃจ๋๋น์ฝ ๋ฏธ์
์ ์ถํฉ๋๋ค.#325HyoYoonNam wants to merge 73 commits intowoowacourse:hyoyoonnamfrom
Conversation
๊ธฐ์กด์๋ Piece์ movablePaths() ๋ฉ์๋ ๋ด์์ PieceType์ movablePaths()์ movableDestinations๋ฅผ ์ ์ฐจ์ ์ผ๋ก ํธ์ถํ๋ค. ์ด๋ฅผ PieceType์ด ์์จ์ ์ผ๋ก ํ๋ํ ์ ์๋๋ก movableDestinations๋ง ์ธ๋ถ๋ก ๊ณต๊ฐํ๋ค. ๋ํ Piece์ movablePaths()๊ฐ List<Intersection>์ ๋ฐํํ๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ, ๋ฉ์๋๋ช ์ด 'Paths'์ฌ์ ์ด๋ฅผ 'Destinations'๋ก ๋ณ๊ฒฝํ๋ค.
๊ธฐ์กด์๋ Piece.EMPTY ์์๋ฅผ public์ผ๋ก ์ ๊ณตํ๊ธด ํ์ง๋ง, new Piece(PieceType.EMPTY, Side.NONE)์ฒ๋ผ ์์ฑ์๋ก ๊ฐ์ ์์ฑํ๋ฉด ์๋ก์ด ๋น ๊ธฐ๋ฌผ ์ธ์คํด์ค๊ฐ ๋ฆฌํด๋๋ ๊ฒ์ ๋ง์ ์ ์์๋ค. Piece์ ์์ฑ์๋ฅผ private์ผ๋ก ๊ฐ์ถ๊ณ , ์ ์ ํฉํฐ๋ฆฌ ๋ฉ์๋ of()๋ง ์ธ๋ถ๋ก ์ด์ด ๋ง์ฝ ๋น ๊ธฐ๋ฌผ์ ์์ฑํ๋ ค๊ณ ํ๋ฉด ๋ด๋ถ์์ ์์๋ก ๊ด๋ฆฌํ๋ EMPTY๋ฅผ ๋ฆฌํดํ๋๋ก ํ๋ค.
๊ธฐ์กด์๋ 'Point'๋ฅผ ์ฌ์ฉํ๋ค. ํ์ง๋ง ์๋ก์ด ์๊ตฌ์ฌํญ์์์ '์ ์'๊ฐ ์ฅ๊ธฐ ๋๋ฉ์ธ์์ 'Point'๋ก ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ํผ๋์ ๋ฐฉ์งํ๊ณ ์ 'Position'์ผ๋ก ๋ณ๊ฒฝํ๋ค.
๊ธฐ์กด ๋ฌธ์ 1: ์์ด ์กํ๋๋ฐ๋ ์ ์ ๊ธฐ๋ฐ์ผ๋ก ์นํจ๋ฅผ ํ์ ํด๊ฒฐ 1: ์์ด ์กํ๋ค๋ฉด, ๋ฌด์กฐ๊ฑด ์กํ์ง ์์ ์ชฝ ์น๋ฆฌ. ๊ธฐ์กด ๋ฌธ์ 2: ์์ด ์กํ์ ๋๋ง ๊ฒ์์ด ์ข ๋ฃ ํด๊ฒฐ 2: ์์ด ์กํ์ง ์์๋๋ผ๋ ์์ธก ์ง์ ์ ์๊ฐ ๋ชจ๋ 30์ ๋ฏธ๋ง์ด๋ฉด ์ข ๋ฃ ๊ธฐํ ๊ฐ์ 1: TestFixture ๋์ ํ์ฌ ์ด๊ธฐ ์ํฉ ์ ํ ์ ๋จ์ํ ๊ธฐํ ๊ฐ์ 2: ์นํจ ํ์ ์ ๊ทผ๊ฑฐ(์ ์กํ or ์ ์ ๋์)๋ฅผ ํจ๊ป ์ถ๋ ฅ ๊ธฐํ ๊ฐ์ 3: GameResult record ๋์
ํด๋น ๋ฉ์๋๋ ๊ฐ์ interface์ default method์ธ palaceDiagonalPaths์์๋ง ํธ์ถ๋๊ธฐ ๋๋ฌธ์ ๋ถํ์ํ ์ธ๋ถ ๋ ธ์ถ์ ์์ ๊ณ ์ private์ผ๋ก ๋ณ๊ฒฝํ๋ค.
Choi-JJunho
left a comment
There was a problem hiding this comment.
๋ฃจ๋๋น์ฝ step2๋ ๊ณ ์ํ์
จ์ต๋๋ค~
์ง๋ฌธ์ฃผ์ ๋ด์ฉ๊ณผ ์ฝ๋ ๊ด๋ จํด์ ๋ช๊ฐ์ง ์ฝ๋ฉํธ ๋จ๊ฒผ์ผ๋ ํ์ธ ๋ถํ๋๋ฆด๊ฒ์
There was a problem hiding this comment.
CREATE TABLE IF NOT EXISTS piece (
game_id INTEGER NOT NULL,
position_row INTEGER,
position_file INTEGER,
side VARCHAR(10) NOT NULL,
piece_type VARCHAR(10) NOT NULL,
FOREIGN KEY (game_id) REFERENCES game(game_id),
PRIMARY KEY (game_id, position_row, position_file)
);varchar 10์ผ๋ก ์ค์ ํด์ค ์ด์ ๊ฐ ์์๊น์?
There was a problem hiding this comment.
์ข์ ์๋์๋ค๊ณ ์๊ฐํฉ๋๋ค~! ๋ค๋ง ์ธ์คํด์ค ๋ณ์๋ก Map์ ๋๋ฉด์ ํํํ๋ ค๋ค๋ณด๋ ๊ณผ๋ํ ์ถ์ํ์ฒ๋ผ ๋ค๊ฐ์ค๊ธฐ๋ ํ๋ค์
YANGI : You Ainโt Gonna Need It ๋ผ๋ ๋ง์ด ์์ต๋๋ค. ํ์ํ ์์
๋ง์ ํ๋ผ๋ ์๋ฏธ์ธ๋ฐ์. ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ค๋ณด๋ฉด ์ง๊ธ์ฒ๋ผ ํ์ฌ๋ ์ฌ์ฉํ์ง ์์ง๋ง, ํ์ฅ์ฑ์ ๊ณ ๋ คํด ๋ฏธ๋ฆฌ ์์
ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ฑ์ฅํ๊ธฐ๋ ํฉ๋๋ค. ์ฃผ์ด์ง ์๊ตฌ์ฌํญ์ ์ง์คํ๊ณ , ์ด๋ฐ ํ์๋ฅผ ์ง์ํ๋ผ๋ ์๋ฏธ๋ก ์ฌ์ฉ๋๋ ๋ง์ธ๋ฐ ์ด ์๋ฏธ๋ฅผ ๋ฐ์ํด์ ๊ฐ๋จํ๊ฒ ํํํด๋ณผ๊น์?
์กฐ๊ฑด์ด 2~3๊ฐ๋ฐ์ ์๋๋ ์ด๋ฐ ๊ฒฝ์ฐ๋ ๊ฐ๋จํ ์กฐ๊ฑด ๋ถ๊ธฐ๊ฐ ์คํ๋ ค ์ฝ๊ธฐ ์ฌ์ธ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค
src/main/java/domain/game/Side.java
Outdated
| public abstract double bonusPoint(); | ||
|
|
There was a problem hiding this comment.
ํ์ฌ Side๊ฐ ๊ฐ์ง ์ฑ
์์ด ๋ง์์ง๋ฉด์ ์ด๋ฐ ๊ณ ๋ฏผ์ด ๋๋๊ฒ ๊ฐ๋ค์
Side์ ์ญํ ๊ณผ ์ฑ
์์ ํ๋ฒ ๋ค์ ์๊ฐํด๋ณด๋ฉด์ ์ ์ ํ๊ฒ ๊ตฌ์ฑ๋์ด์๋์ง ๊ฒํ ํด๋ณด๋ฉด ์ข๊ฒ ๋ค์
bonusPoint ๊ฐ์ ๋ฉ์๋๋ ์ ๋ง๋ก Side๊ฐ ๊ฐ์ ธ์ผํ๋ ํ์์ผ๊น์?
| public final class StraightLineMovement extends Movement { | ||
| public final class StraightLineMovement extends Movement implements PalaceMovement { | ||
|
|
||
| private static final MoveAmount MOVE_AMOUNT = new MoveAmount(1); | ||
|
|
||
| @Override | ||
| protected List<Path> candidatePaths(Intersection from, Side side) { | ||
| return allDirectionPaths(from, side); | ||
| List<Path> paths = new ArrayList<>(); | ||
|
|
||
| List<Path> orthogonalPaths = allDirectionPaths(from, side); | ||
| List<Path> palaceDiagonalPaths = PalaceMovement.super.palaceDiagonalPathsForStraight(from); | ||
| paths.addAll(orthogonalPaths); | ||
| paths.addAll(palaceDiagonalPaths); | ||
|
|
||
| return List.copyOf(paths); |
There was a problem hiding this comment.
์ ์๊ฒฌ์ ๋จผ์ ๋ง์๋๋ฆฌ๊ธฐ ์ ์ ๋ฃจ๋๋น์ฝ์ ์๊ฐ์ ๋จผ์ ๋ฃ๊ณ ์ถ๋ค์! (์ง๋ฌธ์ ์ง๋ฌธ์ผ๋ก ๋ตํ๊ฒ๋์๋ค์ ๐
)
๋ฃจ๋๋น์ฝ๊ฐ ์๊ฐํ๋ ์ธํฐํ์ด์ค์ ๋ณธ๋ถ์ ๋ฌด์์ธ์ง ๊ถ๊ธํฉ๋๋ค! default ๋ฉ์๋๋ ์ ์กด์ฌํ ๊น์?
| if (from.row() == 1 || from.row() == 3) { | ||
| return new Intersection(2, 5); | ||
| } | ||
|
|
||
| return new Intersection(9, 5); | ||
| } |
There was a problem hiding this comment.
์๋ฏธ๊ฐ ๋ชจํธํ ๊ฐ๋ค (๋งค์ง๋๋ฒ)๋ค์ด ์์ฃผ ๋ฑ์ฅํ๋ ๊ฒ ๊ฐ๋ค์ ๐ ์์๋ก ์ถ์ถํ ๋ฐฉ๋ฒ์ด ์์๊น์?
There was a problem hiding this comment.
(PalaceMovement์ Intersection์์ ์ฌ์ฉ๋๋ ๋งค์ง๋๋ฒ ๊ด๋ จ)
๊ถ์ฑ๊ณผ ๊ด๋ จํ ํ๋จ ๋ฐ ๋งค์ง๋๋ฒ๋ฅผ Palace ๋ฉ์๋ ๋ฐ ์์๋ก ์ด๋ํ์ต๋๋ค!
java-janggi/src/main/java/domain/board/Palace.java
Lines 6 to 84 in 9328d22
src/main/java/domain/game/Side.java
Outdated
| public static Side from(String sideName) { | ||
| return Arrays.stream(values()) | ||
| .filter(side -> side.name().equals(sideName)) | ||
| .findAny() | ||
| .orElse(NONE); | ||
| } |
There was a problem hiding this comment.
์ฌ์ฉ์์ ์ ๋ ฅ์ด๋, DB์ ์๋ชป๋ ๊ฐ์ด ์ ์ฅ๋์ด์์ผ๋ฉด ์์ธ์์ด NONE์ด ๋ฐ์ํ๊ฒ๋๋๋ฐ์ ์ด ๋ถ๋ถ์ ์๋ํ์ ๋ถ๋ถ์ผ๊น์?
There was a problem hiding this comment.
์๋ํ์ง ์์๊ณ , ์ ๊ฐ ์ ๋๋ก ํ์ธํ์ง ์์ ๋ฐ์ํ ์ํฉ์ด์์ต๋๋ค.
ํด๋น ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ์ํ์ฌ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ orElseThrow()๋ฅผ ๋์ง๋๋ก ๊ฐ์ ํ๋๋ฐ์.
์ด ๊ฒฝ์ฐ ๊ฒฐ๊ตญ Enum์ด ์์ฒด์ ์ผ๋ก ์ ๊ณตํ๋ valueOf()์ ๋ก์ง์ด ๋์ผํ๋ค๊ณ ํ๋จํ์ฌ Side.from() ์์ฒด๋ฅผ ์ ๊ฑฐํ๊ณ , ์ด๋ฅผ ํธ์ถํ๋ ๊ณณ์์๋ Side.valueOf()๋ฅผ ํธ์ถํ๋๋ก ๋ณ๊ฒฝํ์ต๋๋ค.
public static <T extends Enum<T>> T valueOf(Class<T> enumClass,
String name) {
T result = enumClass.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumClass.getCanonicalName() + "." + name);
}| public static MoveCommand from(String rawMoveCommand) { | ||
| if (rawMoveCommand.equalsIgnoreCase("exit")) { | ||
| // TODO ์ด๊ฒ๋ null ๋ฃ์ด์ ๋ฑ๋ ๊ฑฐ ํธ์ถ๋ถ์์๋ ๋ฐฉ์ด์ ์ผ๋ก ์ฌ์ฉํ๋๋ฐ, ์ ์ด์ null ๋ฑ๋ ๋ฐฉ์์ด ๋ฌธ์ ๊ธด ํ ๋ฏ | ||
| return new MoveCommand(Type.EXIT, null); | ||
| } |
There was a problem hiding this comment.
TODO๊ฐ ๋จ์์๋ค์ ๐ ์ด๋ถ๋ถ์ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น์?
There was a problem hiding this comment.
null์ด๋ ๊ฐ ๋์ Optional์ ๋ฑ๋๋ก ํ์ฌ ์ด๋ฅผ ์ฌ์ฉํ๋ ์ปจํธ๋กค๋ฌ์์ ๊ฒ์ฆ ํ ์ฌ์ฉํ๋๋ก ํ์ต๋๋ค.
java-janggi/src/main/java/controller/JanggiController.java
Lines 156 to 159 in eb25725
| public boolean isPalaceCenter() { | ||
| return (row == 2 || row == 9) | ||
| && file == 5; | ||
| } | ||
|
|
||
| public boolean isPalaceCorner() { | ||
| return (row == 1 || row == 3 || row == 8 || row == 10) | ||
| && (file == 4 || file == 6); | ||
| } |
There was a problem hiding this comment.
ํ๋์ฝ๋ฉ๋ ๊ฐ๋ค์ด ๋ง๋ค์ ๐ซ
์ด๋ฐ๊ฒ๋ค์ ์ด๋ป๊ฒ ๊ด๋ฆฌํ๊ธฐ ํธํ๊ฒ ๋ง๋ค ์ ์์๊น์?
There was a problem hiding this comment.
(PalaceMovement์ Intersection์์ ์ฌ์ฉ๋๋ ๋งค์ง๋๋ฒ ๊ด๋ จ)
๊ถ์ฑ๊ณผ ๊ด๋ จํ ํ๋จ ๋ฐ ๋งค์ง๋๋ฒ๋ฅผ Palace ๋ฉ์๋ ๋ฐ ์์๋ก ์ด๋ํ์ต๋๋ค!
java-janggi/src/main/java/domain/board/Palace.java
Lines 6 to 84 in 9328d22
| public long save(JanggiGame janggiGame) { | ||
| String sql = "INSERT INTO game (current_turn) VALUES (?)"; | ||
|
|
||
| try ( | ||
| Connection conn = dataSource.getConnection(); | ||
| PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) | ||
| ) { | ||
| pstmt.setString(1, janggiGame.currentTurn().name()); | ||
| pstmt.executeUpdate(); | ||
| // TODO: ResultSet ์์๋ ๋ซ์์ผ ๋จ์ ์ธ์งํด์ ์ผ๋จ ์ค์ฒฉ try-with-resources๋ก ๋์ํ์ง๋ง, ์ค์ฒฉ์์ด ํด๊ฒฐ ๊ฐ๋ฅํ ์ง ๊ณ ๋ฏผ ํ์. | ||
| try (ResultSet rs = pstmt.getGeneratedKeys()) { | ||
| if (rs.next()) { | ||
| long gameId = rs.getLong(1); | ||
| insertPieces(conn, janggiGame, gameId); | ||
|
|
||
| return gameId; | ||
| } | ||
| } | ||
|
|
||
| throw new SQLException("๊ฒ์ ์์ฑ์ ์คํจํ์ต๋๋ค."); | ||
| } catch (SQLException e) { | ||
| throw new IllegalStateException(e); | ||
| } | ||
| } |
There was a problem hiding this comment.
game INSERT์ piece INSERT๊ฐ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ์ฌ์์ง ์๋ค์. insert๊ฐ ์๋ฃ๋๊ณ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ์ด๋ค ์ผ์ด ๋ฐ์ํ ๊น์?
There was a problem hiding this comment.
๊ฒ์์ ์ ์ฅ๋์ง๋ง ๊ทธ์ ๋ํ ๊ธฐ๋ฌผ ์ ๋ณด๋ ์ ๋๋ก ๋ฐ์๋์ง ์๋ ์ฌ๊ฐํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
ํธ๋์ญ์
๊ด๋ฆฌ๋ฅผ ๋ฆฌํฌ์งํ ๋ฆฌ๊ฐ ์๋ TransactionTemplate๊ฐ ๋ด๋นํ๋๋ก ๋ณ๊ฒฝํ๋ ๊ณผ์ ์์ ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค!
java-janggi/src/main/java/support/TransactionTemplate.java
Lines 20 to 40 in 9328d22
java-janggi/src/main/java/service/JanggiService.java
Lines 23 to 29 in 9328d22
src/main/java/dto/GameSummary.java
Outdated
|
|
||
| import java.util.Date; | ||
|
|
||
| public record GameSummary(long id, Date startedAt, String currentTurn) { |
There was a problem hiding this comment.
Date์ LocalDateTime ์ ์ฐจ์ด๋ฅผ ํ๋ฒ ํ์ธํด๋ณด๊ณ ์ด์ผ๊ธฐํด์ฃผ์ธ์!
There was a problem hiding this comment.
Date์ ๊ฒฝ์ฐ JDK 1.0๋ถํฐ ํฌํจ๋ ๊ฒ์ผ๋ก '๊ฐ๋ณ์ '์ด๋ผ๋ ํฐ ๋จ์ ์ ๊ฐ์ง๊ณ ์์์ ํ์ธํ์ต๋๋ค.
๋ํ java.util ํจํค์ง ํ์์ ์์นํด์๋๋ฐ, ์ค๋ผํด์์ "Contains the collections framework, legacy collection classes, event model, date and time facilities" ๋ผ๊ณ ์ค๋ช
ํ๋, ์๊ฐ์ ๋ค๋ฃจ๋ '๋ ๊ฑฐ์'ํ ๋ฐฉ๋ฒ์์ ํ์ธํ์ต๋๋ค.
์ดํ JDK 1.8์์ ๋ ์ง์ ์๊ฐ์ ์ ์ฉ์ผ๋ก ๋ค๋ฃจ๋ java.time ํจํค์ง๊ฐ ๋ฑ์ฅํ๊ณ , LocalDateTime์ด ์ฌ๊ธฐ์ ์ํ๊ฒ ๋ฉ๋๋ค.
๊ฐ์ฅ ํฐ ๋ณํ๋ก๋ '๋ถ๋ณ'์ด๋ผ๋ ๊ฒ์ด๊ณ , ์ด์ธ์ ๋ ์ง/์๊ฐ ๊ณ์ฐ์ ์ํ ํธ์ ๋ฉ์๋ ์ถ๊ฐ ๋ฑ์ด ๋์์์ ํ์ธํ์ต๋๋ค.
The main API for dates, times, instants, and durations.
...
All the classes are immutable and thread-safe.
๊ฒฐ๊ณผ์ ์ผ๋ก, ๋ค์์ฒ๋ผ LocalDateTime์ ์ฌ์ฉํ๋๋ก ๋ณ๊ฒฝํ์ต๋๋ค!
java-janggi/src/main/java/dto/GameSummary.java
Lines 5 to 6 in 43dcc80
java-janggi/src/main/java/repository/JanggiGameRepository.java
Lines 127 to 142 in 43dcc80
๊ธฐ์กด์๋ ํธ๋์ญ์ ๊ด๋ฆฌ๋ฅผ ์๋น์ค ๊ณ์ธต์์ ์ํํ๋ค. ๊ด๋ฆฌ๋ฅผ ์ํ ์ค๋ณต ์ฝ๋๋ฅผ ํ ํ๋ฆฟํํ๋ค. ๋ํ ๋๋ถ์ ์๋น์ค ๊ณ์ธต์์๋ DB ์ข ์์ ์ธ ์์ธ๋ฅผ ๋ค๋ฃจ์ง ์์๋ ๋๋ค.
๊ธฐ์กด์ from()์ ์ฐพ์ง ๋ชปํ๋ฉด NONE์ ๋ฆฌํดํ๋ค. ํ์ง๋ง ์ด๋ฅผ ํ์๋ก ํ๋ ๊ณณ์ด ์์๊ณ , ์คํ๋ ค ์กฐ์ฉํ ์คํจ๋ก ์ธํด ๋ฌธ์ ์์ธ์ ํ์ ํ๊ธฐ ์ด๋ ต๊ฒ ํ๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ณ ์ orElse(NONE)์ orElseThrow(...)์ผ๋ก ๋ณ๊ฒฝํ๋๋, ๊ทธ ๊ตฌ์กฐ๊ฐ Enum์ด ์์ฒด์ ์ผ๋ก ์ ๊ณตํ๋ valueOf()์ ๋์ผํจ์ ํ์ธํ๋ค. ๋ฐ๋ผ์ ์ค๋ณต์ ์ผ๋ก ๊ตฌํํ์ง ์๊ณ , JDK ์์์ ์ด๋ฏธ ๊ตฌํ๋ Enum.valueOf()๋ฅผ ์ฌ์ฉํ๋ค.
์ง์๋ณ ๋ณด๋์ค ์ ์, ์ฆ '์ ์'๋ ๊ฒ์์ ์งํํ๋ ์ํฉ์์ ํ์ํ ๊ฐ๋ ์ด๋ค. ๋ฐ๋ผ์ ์ง์ ๊ทธ ์์ฒด๋ก ๋ณด๋์ค ์ ์๋ฅผ ๊ฐ์ง๋ ๊ฒ์ด ์๋๋ผ, ๊ฒ์์์ ์ฑ ์์ ๊ฐ์ง์ด ์ ์ ํ๋ค.
๊ธฐ์กด์๋ DB ๊ด๋ จ ์์ธ๋ง ํธ๋ค๋งํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์์ ๋ฐ์ํ ์์ธ์๋ ๋กค๋ฐฑ์ด ์ํ๋์ง ์๋ ๋ฌธ์ ๊ฐ ์๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด DB ์์ธ ๋ฟ๋ง ์๋๋ผ RuntimeException๋ ์ถ๊ฐ๋ก ๋ค๋ฃฌ๋ค.
HyoYoonNam
left a comment
There was a problem hiding this comment.
์๋ ํ์ธ์, ์ฃผ๋ ธ!
์ด๋ฒ์๋ ์ ๋ถํ๋๋ฆฌ๊ณ , ์๋กญ๊ฒ ์์๋๋ ํ ์ฃผ๋ ํ์ดํ ์ ๋๋ค!!
There was a problem hiding this comment.
์ปจํธ๋กค๋ฌ ๋ด๋ถ์์ if ๋ถ๊ธฐ๋ฅผ ์ถ์ํํ์ฌ ๊ฐ์ง๋ Map์ ์ ๊ฑฐํ๊ณ , ๋ช ์์ ์ผ๋ก if ๋ฌธ์ ์ฌ์ฉํ๋๋ก ๋ณ๊ฒฝํ์ต๋๋ค!
java-janggi/src/main/java/controller/JanggiController.java
Lines 92 to 106 in c86894b
| public static MoveCommand from(String rawMoveCommand) { | ||
| if (rawMoveCommand.equalsIgnoreCase("exit")) { | ||
| // TODO ์ด๊ฒ๋ null ๋ฃ์ด์ ๋ฑ๋ ๊ฑฐ ํธ์ถ๋ถ์์๋ ๋ฐฉ์ด์ ์ผ๋ก ์ฌ์ฉํ๋๋ฐ, ์ ์ด์ null ๋ฑ๋ ๋ฐฉ์์ด ๋ฌธ์ ๊ธด ํ ๋ฏ | ||
| return new MoveCommand(Type.EXIT, null); | ||
| } |
There was a problem hiding this comment.
null์ด๋ ๊ฐ ๋์ Optional์ ๋ฑ๋๋ก ํ์ฌ ์ด๋ฅผ ์ฌ์ฉํ๋ ์ปจํธ๋กค๋ฌ์์ ๊ฒ์ฆ ํ ์ฌ์ฉํ๋๋ก ํ์ต๋๋ค.
java-janggi/src/main/java/controller/JanggiController.java
Lines 156 to 159 in eb25725
| public int toPoint() { | ||
| return type.point(); | ||
| } | ||
|
|
||
| public PieceType getType() { | ||
| return type; | ||
| } | ||
|
|
||
| public Side getSide() { | ||
| return side; | ||
| } | ||
|
|
There was a problem hiding this comment.
๊ณผ๊ฑฐ(์ฐํ
์ฝ ์
๊ณผ ์ )์ ๋ง์ํ์ toDbRow()๊ฐ์ ๋งคํ ๋ฉ์๋๋ฅผ ๋๋ฉ์ธ ์์ ๋๋ ๋ฐฉ์์ ๋ฐฐ์ ์๋๋ฐ, ํฌ๋ฃจ๋ค๊ณผ ์ด์ผ๊ธฐํ๋ค ๋ณด๋ 'ํธํ๊ธด ํ์ง๋ง ๋๋ฉ์ธ์ด DB๋ ๋ทฐ์ ์ข
์๋๋ ๋ฌธ์ ๊ฐ ์๊ธด๋ค'๋ก ๊ฒฐ๋ก ๋ด๋ ค ์ฌ์ฉํ์ง ์์์ต๋๋ค.
PieceMapper ์ค๊ฐ ๋ค๋ฆฌ๋ฅผ ๋๋๋ค๋ ๋ฐฉํฅ์ ์๊ฐํ์ง ๋ชปํ๊ณ , ๋๋ถ์ ์ ์ฉํด๋ดค์ต๋๋ค!
์ ์ฉ ๊ณผ์ ์์ '๋งคํผ๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ๊ฒฐ๊ตญ ๋๋ฉ์ธ์ getter๋ ์ด๋ ค์ผ ํ๋ค'๋ ์ ์ ํ์ธํ๊ณ , ๋งคํผ์ ์์๋ 'getter๋ฅผ ํธ์ถํ๋ ๊ณณ์ ๋งคํผ ํ ๊ณณ์ผ๋ก ์์ง'์ํค๋ ๊ฒ์ด๋ผ๊ณ ์ดํดํ์ต๋๋ค.
์ถ๊ฐ๋ก, PieceMapper๋ฅผ ์ฌ์ฉํ ๊ณณ์ด repository๋ก ํ์ ๋๋ค๊ณ ํ๋จํ์ฌ ํด๋์ค ์ ๊ทผ ์ ์ด์๋ฅผ package-private๋ก ์ค์ ํ์ต๋๋ค(ํ์ ๋ฉ์๋๋ค์ ๊ฒฝ์ฐ ํด๋์ค ์์ค์ ์ ๊ทผ ์ ์ด์๋ฅผ ๋ฐ๋ผ๊ฐ์ผ๋ก ์๊ณ ์์ง๋ง, ๋ฒ์๋ฅผ ํ์ ํ๋ค๋ ์๋ฏธ๋ฅผ ๊ฐ์กฐํ๊ธฐ ์ํด ๋ฉ์๋๋ค์ ์ ๊ทผ ์ ์ด์๋ค๋ public์ด ์๋ package-private๋ก ์ค์ ํ์ต๋๋ค).
java-janggi/src/main/java/repository/PieceMapper.java
Lines 8 to 29 in 1410cab
java-janggi/src/main/java/repository/JanggiGameRepository.java
Lines 159 to 167 in 1410cab
|
|
||
| public final class MemoryDBConnectionUtil { | ||
|
|
||
| private static final String JDBC_SQLITE_URL = "jdbc:sqlite::memory:?cache=shared"; |
There was a problem hiding this comment.
'๋ฆฌ๋ทฐ์ด๊ฐ clone ํ ๋ณ ๋ค๋ฅธ ์ค์ ์์ด ๋ฐ๋ก Application์ ์คํํ ์ ์๊ฒ ํจ'์ด ์ ๊ฐ ์ค์ํ๊ฒ ์๊ฐํ ๋ถ๋ถ์ ๋๋ค.
์ด๋ MySQL์ ๋ก์ปฌ ์ค์น๋ฅผ ์๊ตฌํ๊ฑฐ๋, Docker๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ๋์ปค์ ์ค์น๊ฐ ์๊ตฌ๋๊ธฐ ๋๋ฌธ์ ์ ํ์์ ๋ฐฐ์ ํ์ต๋๋ค.
(์ ๊ฐ ์ฐพ์ ๋ฐ๋ก๋ ๊ทธ๋ฌ๋๋ฐ, ๋ฐฉ๋ฒ์ด ์์์๋ ์กฐ์ฌ๊ฐ ๋ฏธ์ํด์ ๋ด๋ ค์ง ๊ฒฐ๋ก ์ด๋ผ๋ฉด ์ฃ์กํ๋ค๋ ๋ง์๋๋ฆฝ๋๋ค!!)
์ดํ H2์ SQLite๊ฐ ํ๋ณด๋ก ๋จ์๋๋ฐ, H2๋ ๊ณผ๊ฑฐ์ ๊ฐ๋จํ๊ฒ๋๋ง ์ฌ์ฉํ ๊ฒฝํ์ด ์์ด ์ด๋ฒ ๊ธฐํ์ ์๋ก์ด ์๋๋ฅผ ํ๊ณ ์ SQLite๋ฅผ ์ ํํ์ต๋๋ค.
src/main/java/dto/GameSummary.java
Outdated
|
|
||
| import java.util.Date; | ||
|
|
||
| public record GameSummary(long id, Date startedAt, String currentTurn) { |
There was a problem hiding this comment.
Date์ ๊ฒฝ์ฐ JDK 1.0๋ถํฐ ํฌํจ๋ ๊ฒ์ผ๋ก '๊ฐ๋ณ์ '์ด๋ผ๋ ํฐ ๋จ์ ์ ๊ฐ์ง๊ณ ์์์ ํ์ธํ์ต๋๋ค.
๋ํ java.util ํจํค์ง ํ์์ ์์นํด์๋๋ฐ, ์ค๋ผํด์์ "Contains the collections framework, legacy collection classes, event model, date and time facilities" ๋ผ๊ณ ์ค๋ช
ํ๋, ์๊ฐ์ ๋ค๋ฃจ๋ '๋ ๊ฑฐ์'ํ ๋ฐฉ๋ฒ์์ ํ์ธํ์ต๋๋ค.
์ดํ JDK 1.8์์ ๋ ์ง์ ์๊ฐ์ ์ ์ฉ์ผ๋ก ๋ค๋ฃจ๋ java.time ํจํค์ง๊ฐ ๋ฑ์ฅํ๊ณ , LocalDateTime์ด ์ฌ๊ธฐ์ ์ํ๊ฒ ๋ฉ๋๋ค.
๊ฐ์ฅ ํฐ ๋ณํ๋ก๋ '๋ถ๋ณ'์ด๋ผ๋ ๊ฒ์ด๊ณ , ์ด์ธ์ ๋ ์ง/์๊ฐ ๊ณ์ฐ์ ์ํ ํธ์ ๋ฉ์๋ ์ถ๊ฐ ๋ฑ์ด ๋์์์ ํ์ธํ์ต๋๋ค.
The main API for dates, times, instants, and durations.
...
All the classes are immutable and thread-safe.
๊ฒฐ๊ณผ์ ์ผ๋ก, ๋ค์์ฒ๋ผ LocalDateTime์ ์ฌ์ฉํ๋๋ก ๋ณ๊ฒฝํ์ต๋๋ค!
java-janggi/src/main/java/dto/GameSummary.java
Lines 5 to 6 in 43dcc80
java-janggi/src/main/java/repository/JanggiGameRepository.java
Lines 127 to 142 in 43dcc80
| public boolean isPalaceCenter() { | ||
| return (row == 2 || row == 9) | ||
| && file == 5; | ||
| } | ||
|
|
||
| public boolean isPalaceCorner() { | ||
| return (row == 1 || row == 3 || row == 8 || row == 10) | ||
| && (file == 4 || file == 6); | ||
| } |
There was a problem hiding this comment.
(PalaceMovement์ Intersection์์ ์ฌ์ฉ๋๋ ๋งค์ง๋๋ฒ ๊ด๋ จ)
๊ถ์ฑ๊ณผ ๊ด๋ จํ ํ๋จ ๋ฐ ๋งค์ง๋๋ฒ๋ฅผ Palace ๋ฉ์๋ ๋ฐ ์์๋ก ์ด๋ํ์ต๋๋ค!
java-janggi/src/main/java/domain/board/Palace.java
Lines 6 to 84 in 9328d22
There was a problem hiding this comment.
๊ธฐ์กด์๋ ๋ฐ์ดํฐ ์ ๊ทผ ๊ณ์ธต๊ณผ ๊ด๋ จ๋ ์์ธ๋ฅผ ๋ชจ๋ IllegalStateException์ผ๋ก ๊ฐ์ธ์ ๋์ก๋๋ฐ, ๋ฆฌํฉํฐ๋ง ๊ณผ์ ์์ ๊ตฌ๋ถ์ด ๊ฐ๋ฅํ ์ปค์คํ
์์ธ๋ก ๋ฐ๊ฟ์ผ ํ ํ์๊ฐ ์๋ค๊ณ ํ๋จํ์ต๋๋ค.
| public <T> T execute(TransactionCallback<T> action) { | ||
| Connection conn = null; | ||
| try { | ||
| conn = dataSource.getConnection(); | ||
| conn.setAutoCommit(false); | ||
|
|
||
| T doingResult = action.doInTransaction(conn); | ||
|
|
||
| conn.commit(); | ||
|
|
||
| return doingResult; | ||
| } catch (SQLException e) { | ||
| rollback(conn); | ||
| throw new DataAccessException(e); | ||
| } catch (RuntimeException e) { | ||
| rollback(conn); | ||
| throw e; | ||
| } finally { | ||
| close(conn); | ||
| } | ||
| } | ||
|
|
||
| private void rollback(Connection conn) { | ||
| if (conn == null) { | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| conn.rollback(); | ||
| } catch (SQLException e) { | ||
| LOGGER.log(Level.SEVERE, LOG_MESSAGE_FORMAT.formatted("๋กค๋ฐฑ"), e); | ||
| } | ||
| } | ||
|
|
||
| private void close(Connection conn) { | ||
| if (conn == null) { | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| conn.close(); | ||
| } catch (SQLException e) { | ||
| LOGGER.log(Level.SEVERE, LOG_MESSAGE_FORMAT.formatted("Connection ๋ฐ๋ฉ"), e); | ||
| } | ||
| } |
There was a problem hiding this comment.
๊ฒฐ๋ก : ๋กค๋ฐฑ๊ณผ ์์ ๋ฐ๋ฉ ๊ณผ์ ์์ ๋ฐ์ํ๋ ์์ธ๋ ์์ ๊ณ์ธต์ผ๋ก ์ ๋ฌ๋์ง ์์๋ ๋๋ค๊ณ ํ๋จํ์ฌ ๋ก๊ทธ๋ง ์ฐ๋๋ก ํ์ต๋๋ค.
๊ทผ๊ฑฐ ๋ฐ ์ํฉ ์ค๋ช :
- (line 26)
action.doInTransaction()์์ CRUD๋ฅผ ์คํํ์ ๋ ์์ธ๊ฐ ๋ฐ์ - (line 32) 1๋ฒ์ ์์ธ๋ฅผ catchํ๊ณ ,
rollback()์ ํธ์ถ - (line 48) ๋กค๋ฐฑ ๊ณผ์ ์์ ๋ ์์ธ๊ฐ ๋ฐ์
- (line 32) 3๋ฒ์ ์์ธ๊ฐ ๋ค์ ๋์ ธ์ง์ง๋ง, ์ด๋ฅผ catchํด์ค ๊ณณ์ด ๋ ์ด์ ์์
- ๋ฐ๋ผ์ line 33์ ์คํ๋์ง ์๊ธฐ ๋๋ฌธ์ 1๋ฒ์ ์์ธ๊ฐ ์์ ๊ณ์ธต์ผ๋ก ๋์ ธ์ง์ง ์๊ณ , ๋กค๋ฐฑ์ผ๋ก ์ธํ 3๋ฒ ์์ธ๋ง ๋์ ธ์ง.
์ด๋ '์์ ๊ณ์ธต์ผ๋ก ์ ๋ฌ๋์ด์ผ ํ ์ค์ํ ์์ธ'๋ ๊ทผ๋ณธ์ ์ธ 1๋ฒ ์์ธ์ธ๋ฐ, ์ด๋ฅผ ์์ตํ๋ ๊ณผ์ ์ ๋กค๋ฐฑ ์์ธ๊ฐ 1๋ฒ ๋์ ๋์ ธ์ง๋ ๋ฌธ์ ๊ฐ ์์์ ํ์ธํ์ต๋๋ค.
๋กค๋ฐฑ์ ๋ํ ์์ธ๊ฐ ๋์ ธ์ ธ๋ ๊ทผ๋ณธ์ ์ธ CRUD ์์ธ๊น์ง ๊ฐ์ด ๋ด์์ ๋์ง๋ ค๋ฉด ๋ค์์ฒ๋ผ ์ค๋ณต์ ์ธ catch block์ด ํ์ํ๋ฐ, ๋๋ฌด ๊ณผํ ๋์์ด๋ผ๊ณ ์๊ฐํ์ฌ ๋กค๋ฐฑ ์์ธ๋ ๋จ์ํ ๋ก๊ทธ๋ง ์ฐ์์ผ๋ก์จ CRUD ์์ธ๊ฐ ๋ฎ์ด์ง์ง ์๊ณ ์์ ๊ณ์ธต์ผ๋ก ๋์ ธ์ง ์ ์๋๋ก ํ์ต๋๋ค.
public <T> T execute(TransactionCallback<T> action) {
Connection conn = null;
try {
conn = dataSource.getConnection();
conn.setAutoCommit(false);
T doingResult = action.doInTransaction(conn);
conn.commit();
return doingResult;
} catch (SQLException e) {
// ๋กค๋ฐฑ์์ ๋์จ ์์ธ๋ฅผ ๋ค์ try-catch๋ก ์ก์์ ์ฒ๋ฆฌ
try {
rollback(conn);
} catch (DataAccessException exception) {
throw new DataAccessException(e);
}
throw new DataAccessException(e);
} catch (RuntimeException e) {
rollback(conn);
throw e;
} finally {
close(conn);
}
}There was a problem hiding this comment.
Date์ LocalDateTime ์ฐจ์ด๋ฅผ ์์๋ณด๋ฉด์ ์ฌ์ฉํ ์คํ ์ฝ๋์
๋๋ค.
There was a problem hiding this comment.
https://github.com/woowacourse/java-janggi/pull/325/changes#r3069609600
์์ ๋ค๋ฃฌ '์์ธ ๊ฐ๋ ค์ง' ๋ฌธ์ ๋ฅผ ํ ์คํธํ ์คํ ์ฝ๋์ ๋๋ค.
์๋ ํ์ธ์, ์ฃผ๋ ธ!
์ด๋ฒ์๋ ๋ฏธ๋ฆฌ ๊ฐ์ฌ๋๋ฆฝ๋๋ค~~!
์ฒดํฌ ๋ฆฌ์คํธ
Connection๊ณผPreparedStatement๋ ํ๋์ try-with-resources ๋ธ๋ก์ผ๋ก ์์์ ๋ฐ๋ฉํ ์ ์์์ง๋ง ํด๋น ๋ธ๋ก ๋ด์์ ์์ฑํด์ผ ๋๋ResultSet์ ๋ซ์ ๋ฐฉ๋ฒ์ด ์ถ๊ฐ๋ก ํ์ํ๊ณ , ์ด๋ฅผ ์ํด ๋ด๋ถ์์ try-with-resources๋ฅผ ์ค์ฒฉ ์ฌ์ฉํ์ต๋๋ค. (์๋์ ํด๋น ์ฝ๋)java-janggi/src/main/java/repository/JanggiGameRepository.java
Lines 56 to 79 in 0f7650a
test๋ฅผ ์คํํ์ ๋, ๋ชจ๋ ํ ์คํธ๊ฐ ์ ์์ ์ผ๋ก ํต๊ณผํ๋์?์ด๋ค ๋ถ๋ถ์ ์ง์คํ์ฌ ๋ฆฌ๋ทฐํด์ผ ํ ๊น์?
cycle1์ merge ์์ ์ ๋จ๊ฒจ์ฃผ์ ๋น ๊ธฐ๋ฌผ์ ๋งค๋ฒ ์์ฑ๋์ด์ผ ํ ๊น?์ ๋ํด ๋ค์์ฒ๋ผ ๋ฐ์ํ์ต๋๋ค!
java-janggi/src/main/java/domain/piece/AlivePieces.java
Lines 35 to 37 in da4b0e8
java-janggi/src/main/java/domain/piece/Piece.java
Lines 7 to 9 in da4b0e8