Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
# java-racingcar-precourse
# java-racingcar-precourse

헥사고날 아키텍처 연습\
일반적인 RESTful api 서버가 M, C를 담당하고 브라우저가 V를 담당하니 비슷하게 구성\
Proxy를 통해 스프링의 @RequestBody처럼 컨트롤러에 들어온 데이터를 알맞게 변환하면 좋겠지만 V에서 바로 변환

1. domain entity 작성
2. port, dto 작성
3. service 작성
4. adaptor 작성
5. view 작성
6. config 작성
7. application 작성
26 changes: 26 additions & 0 deletions src/main/java/katecam/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package katecam;

import katecam.racingcar.adapter.in.RacingCarController;
import katecam.config.AppConfig;

public class Application {
private static final RacingCarController racingCarController = AppConfig.getRacingCarController();
private static final RacingCarView racingCarView = new RacingCarView();

public static void main(String[] args) {
boolean valid = false;
while (!valid)
try{
racingCarController.initGame(racingCarView.getCarNames(), racingCarView.getNumberToAttempt());
racingCarView.display("\n실행 결과");
valid = true;
}catch (IllegalArgumentException e){
racingCarView.display(e.getMessage());
}
do{
racingCarController.playTurn();
racingCarView.display(racingCarController.getTurnResult());
}while(!racingCarController.isEnded());
racingCarView.display(racingCarController.getTotalResult());
}
}
37 changes: 37 additions & 0 deletions src/main/java/katecam/RacingCarView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package katecam;

import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Scanner;

public class RacingCarView {
private final Scanner scanner;
public RacingCarView() {
this.scanner = new Scanner(System.in);
}

public List<String> getCarNames(){
display("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
return Arrays.stream(scanner.nextLine().split(","))
.map(String::trim)
.toList();
}

public int getNumberToAttempt(){
display("시도할 회수는 몇회인가요?");
int numberToAttempt;
try{
numberToAttempt = scanner.nextInt();
}catch (InputMismatchException e){
throw new IllegalArgumentException("숫자를 입력하세요");
}finally {
scanner.nextLine();
}
return numberToAttempt;
}

public void display(String string){
System.out.println(string);
}
}
39 changes: 39 additions & 0 deletions src/main/java/katecam/config/AppConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package katecam.config;

import katecam.racingcar.adapter.in.RacingCarController;
import katecam.racingcar.adapter.out.InMemoryGameAdaptor;
import katecam.racingcar.application.port.in.command.GameInitializationUseCase;
import katecam.racingcar.application.port.in.command.GameTurnPlayUseCase;
import katecam.racingcar.application.port.in.query.GameStatusQuery;
import katecam.racingcar.application.port.out.GameRecordPort;
import katecam.racingcar.application.port.out.GameLoadPort;
import katecam.racingcar.application.service.GameInitializationService;
import katecam.racingcar.application.service.GameTurnPlayService;
import katecam.racingcar.application.service.GameStatusQueryService;

public class AppConfig {
private static GameLoadPort gameLoadPort;
private static GameRecordPort gameRecordPort;
private static GameInitializationUseCase gameInitializationUseCase;
private static GameTurnPlayUseCase gameTurnPlayUseCase;
private static GameStatusQuery gameStatusQuery;
private static RacingCarController racingCarController;

static {
InMemoryGameAdaptor inMemoryGameAdaptor = new InMemoryGameAdaptor();
gameRecordPort = inMemoryGameAdaptor;
gameLoadPort = inMemoryGameAdaptor;
gameInitializationUseCase = new GameInitializationService(gameRecordPort);
gameTurnPlayUseCase = new GameTurnPlayService(gameLoadPort);
gameStatusQuery = new GameStatusQueryService(gameLoadPort);
racingCarController = new RacingCarController(
gameInitializationUseCase,
gameTurnPlayUseCase,
gameStatusQuery
);
}

public static RacingCarController getRacingCarController() {
return racingCarController;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package katecam.racingcar.adapter.in;

import java.util.List;
import katecam.racingcar.application.dto.command.GameInitializationReq;
import katecam.racingcar.application.port.in.command.GameInitializationUseCase;
import katecam.racingcar.application.port.in.command.GameTurnPlayUseCase;
import katecam.racingcar.application.port.in.query.GameStatusQuery;

public class RacingCarController {
private final GameInitializationUseCase gameInitializationUseCase;
private final GameTurnPlayUseCase gameTurnPlayUseCase;
private final GameStatusQuery gameStatusQuery;

public RacingCarController(GameInitializationUseCase gameInitializationUseCase,
GameTurnPlayUseCase gameTurnPlayUseCase, GameStatusQuery gameStatusQuery) {
this.gameInitializationUseCase = gameInitializationUseCase;
this.gameTurnPlayUseCase = gameTurnPlayUseCase;
this.gameStatusQuery = gameStatusQuery;
}

public void initGame(List<String> carNames, int numberToAttempt){
gameInitializationUseCase.initialize(new GameInitializationReq(carNames, numberToAttempt));
}
public void playTurn(){
gameTurnPlayUseCase.playTurn();
}
public boolean isEnded(){
return gameStatusQuery.isEnded();
}
public String getTurnResult(){
return gameStatusQuery.getTurnResult().toString();
}
public String getTotalResult(){
return gameStatusQuery.getTotalResult().toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package katecam.racingcar.adapter.out;

import katecam.racingcar.application.port.out.GameRecordPort;
import katecam.racingcar.application.port.out.GameLoadPort;
import katecam.racingcar.domain.Game;

public class InMemoryGameAdaptor implements GameRecordPort, GameLoadPort {
private Game game;
@Override
public void save(Game game) {
if (this.game != null)
throw new IllegalStateException("저장된 게임 있음");
this.game = game;
}

@Override
public Game getOrThrow() {
if (this.game == null)
throw new IllegalStateException("저장된 게임 없음");
return this.game;
}

@Override
public void delete(){
this.game = null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package katecam.racingcar.application.dto.command;

import java.util.List;

public record GameInitializationReq(
List<String> carNames,
int numberToAttempt
) {

public GameInitializationReq{
if (carNames == null || carNames.isEmpty())
throw new IllegalArgumentException("리스트 비었음");

carNames.forEach(name-> {
if (name == null || name.length() < 5)
throw new IllegalArgumentException("5자리 이상 입력");
});

if (numberToAttempt <= 0)
throw new IllegalArgumentException("올바른 시도 횟수 입력");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package katecam.racingcar.application.dto.query;

public record CarPositionRes(String carName, int position) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package katecam.racingcar.application.dto.query;

import java.util.List;

public record GameTotalResultRes(List<String> winners) {

@Override
public String toString() {
return "최종 우승자 : " + String.join(", ", winners);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package katecam.racingcar.application.dto.query;

import java.util.List;

public record GameTurnResultRes(List<CarPositionRes> carPositions) {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
this.carPositions.forEach(carPosition ->
sb.append(carPosition.carName())
.append(" : ")
.append("-".repeat(carPosition.position()))
.append("\n")
);
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package katecam.racingcar.application.port.in.command;

import katecam.racingcar.application.dto.command.GameInitializationReq;

public interface GameInitializationUseCase {
void initialize(GameInitializationReq req);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package katecam.racingcar.application.port.in.command;

public interface GameTurnPlayUseCase {
void playTurn();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package katecam.racingcar.application.port.in.query;

import katecam.racingcar.application.dto.query.GameTotalResultRes;
import katecam.racingcar.application.dto.query.GameTurnResultRes;

public interface GameStatusQuery {
boolean isEnded();
GameTurnResultRes getTurnResult();
GameTotalResultRes getTotalResult();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package katecam.racingcar.application.port.out;

import katecam.racingcar.domain.Game;

public interface GameLoadPort {
Game getOrThrow();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package katecam.racingcar.application.port.out;

import katecam.racingcar.domain.Game;

public interface GameRecordPort {
void save(Game game);
void delete();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package katecam.racingcar.application.service;

import katecam.racingcar.application.dto.command.GameInitializationReq;
import katecam.racingcar.application.port.in.command.GameInitializationUseCase;
import katecam.racingcar.application.port.out.GameRecordPort;
import katecam.racingcar.domain.Game;

public class GameInitializationService implements GameInitializationUseCase {
private final GameRecordPort gameRecordPort;

public GameInitializationService(GameRecordPort gameRecordPort) {
this.gameRecordPort = gameRecordPort;
}

@Override
public void initialize(GameInitializationReq req) {
Game game = new Game(req.carNames(), req.numberToAttempt());
gameRecordPort.save(game);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package katecam.racingcar.application.service;


import java.util.List;
import katecam.racingcar.application.dto.query.CarPositionRes;
import katecam.racingcar.application.dto.query.GameTotalResultRes;
import katecam.racingcar.application.dto.query.GameTurnResultRes;
import katecam.racingcar.application.port.in.query.GameStatusQuery;
import katecam.racingcar.application.port.out.GameLoadPort;
import katecam.racingcar.domain.Car;
import katecam.racingcar.domain.Game;

public class GameStatusQueryService implements GameStatusQuery {
private final GameLoadPort gameLoadPort;

public GameStatusQueryService(GameLoadPort gameLoadPort) {
this.gameLoadPort = gameLoadPort;
}

@Override
public boolean isEnded() {
Game game = gameLoadPort.getOrThrow();
return game.isEnded();
}

@Override
public GameTurnResultRes getTurnResult() {
Game game = gameLoadPort.getOrThrow();
List<CarPositionRes> carPositions= game.getCars().stream()
.map(car->new CarPositionRes(car.getName(), car.getPosition()))
.toList();
return new GameTurnResultRes(carPositions);
}

@Override
public GameTotalResultRes getTotalResult() {
Game game = gameLoadPort.getOrThrow();
List<String> winnerNames = game.getWinners().stream()
.map(Car::getName)
.toList();
return new GameTotalResultRes(winnerNames);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package katecam.racingcar.application.service;

import katecam.racingcar.application.port.in.command.GameTurnPlayUseCase;
import katecam.racingcar.application.port.out.GameLoadPort;
import katecam.racingcar.domain.Game;

public class GameTurnPlayService implements GameTurnPlayUseCase {
private final GameLoadPort gameLoadPort;

public GameTurnPlayService(GameLoadPort gameLoadPort) {
this.gameLoadPort = gameLoadPort;
}

@Override
public void playTurn() {
Game game = gameLoadPort.getOrThrow();
game.playTurn();
}
}
Loading