-
Notifications
You must be signed in to change notification settings - Fork 0
Driving Adapter 와 UseCase 구현 #24
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
Changes from all commits
2d39bb0
c80cd1f
5a93160
bca5627
2419069
cba79ca
747209f
9f8c1be
1d9c470
b6ef149
ed3750d
d2857ab
46362b7
96756de
0c4f906
81ae62d
5c07f42
bf819d6
6b14a72
e96cabe
2fe1b9c
44ae379
8d14bc6
85f4519
cc9f2be
2869742
a26fbfe
1ff1de5
19f9eeb
4df2745
a44c539
9675332
6482568
16be7a4
2fe8e09
b36855a
2c70e28
0291bea
93e03e5
14fad58
1195926
7e1f509
7e2f07a
665d31b
7f8057b
3fbc6df
4f1df36
68ae6d0
bda07b6
1a1d538
d549d9b
aeba058
2919162
9356e69
8fda352
5ade3f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package me.nettee.board.adapter.driving.web; | ||
|
||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import me.nettee.board.adapter.driving.web.dto.BoardCommandDto.BoardCommandResponse; | ||
import me.nettee.board.adapter.driving.web.dto.BoardCommandDto.BoardCreateCommand; | ||
import me.nettee.board.adapter.driving.web.dto.BoardCommandDto.BoardUpdateCommand; | ||
import me.nettee.board.adapter.driving.web.mapper.BoardDtoMapper; | ||
import me.nettee.board.application.usecase.BoardCreateUseCase; | ||
import me.nettee.board.application.usecase.BoardDeleteUseCase; | ||
import me.nettee.board.application.usecase.BoardUpdateUseCase; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@RestController | ||
@RequestMapping("/api/v1/boards") | ||
@RequiredArgsConstructor | ||
public class BoardCommandApi { | ||
|
||
private final BoardCreateUseCase boardCreateUseCase; | ||
private final BoardUpdateUseCase boardUpdateUseCase; | ||
private final BoardDeleteUseCase boardDeleteUseCase; | ||
private final BoardDtoMapper boardDtoMapper; | ||
|
||
@PostMapping | ||
@ResponseStatus(HttpStatus.CREATED) | ||
public BoardCommandResponse createBoard(@RequestBody @Valid BoardCreateCommand boardCreateCommand) { | ||
// Map to Domain | ||
var board = boardDtoMapper.toDomain(boardCreateCommand); | ||
|
||
return BoardCommandResponse.builder() | ||
.board(boardCreateUseCase.createBoard(board)) | ||
.build(); | ||
} | ||
|
||
@PatchMapping("/{id}") | ||
@ResponseStatus(HttpStatus.OK) | ||
public BoardCommandResponse updateBoard(@PathVariable("id") Long id, | ||
@Valid @RequestBody BoardUpdateCommand boardUpdateCommand) { | ||
// Map to Domain | ||
var board = boardDtoMapper.toDomain(id, boardUpdateCommand); | ||
|
||
return BoardCommandResponse.builder() | ||
.board(boardUpdateUseCase.updateBoard(board)) | ||
.build(); | ||
} | ||
|
||
@DeleteMapping("/{id}") | ||
@ResponseStatus(HttpStatus.NO_CONTENT) | ||
public void deleteBoard(@PathVariable("id") Long id) { | ||
boardDeleteUseCase.deleteBoard(id); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package me.nettee.board.adapter.driving.web; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import me.nettee.board.adapter.driving.web.dto.BoardQueryDto.BoardDetailResponse; | ||
import me.nettee.board.adapter.driving.web.mapper.BoardDtoMapper; | ||
import me.nettee.board.application.domain.type.BoardStatus; | ||
import me.nettee.board.application.model.BoardReadSummaryModel; | ||
import me.nettee.board.application.usecase.BoardReadByStatusesUseCase; | ||
import me.nettee.board.application.usecase.BoardReadUseCase; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import java.util.Set; | ||
|
||
@RestController | ||
@RequestMapping("/api/v1/boards") | ||
@RequiredArgsConstructor | ||
public class BoardQueryApi { | ||
private final BoardReadUseCase boardReadUseCase; | ||
private final BoardReadByStatusesUseCase boardReadByStatusesUseCase; | ||
|
||
private final BoardDtoMapper boardDtoMapper; | ||
|
||
@GetMapping("/{boardId}") | ||
public BoardDetailResponse getBoard(@PathVariable("boardId") long boardId) { | ||
var board = boardReadUseCase.getBoard(boardId); | ||
|
||
return boardDtoMapper.toDtoDetail(board); | ||
} | ||
|
||
@GetMapping | ||
public Page<BoardReadSummaryModel> getBoardsByStatuses(@RequestParam Set<BoardStatus> statuses, Pageable pageable) { | ||
return boardReadByStatusesUseCase.findByStatuses(statuses, pageable); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package me.nettee.board.adapter.driving.web.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonRootName; | ||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Size; | ||
import lombok.Builder; | ||
import me.nettee.board.application.domain.Board; | ||
|
||
public final class BoardCommandDto { | ||
|
||
private BoardCommandDto() { | ||
} | ||
|
||
public record BoardCreateCommand( | ||
@NotBlank(message = "제목을 입력하십시오.") | ||
@Size(min = 3, message = "제목은 세 글자 이상 입력하세요.") | ||
String title, | ||
@NotBlank(message = "본문을 입력하십시오") | ||
@Size(min = 3, message = "제목은 세 글자 이상 입력하세요.") | ||
String content | ||
) { | ||
} | ||
|
||
public record BoardUpdateCommand( | ||
@NotBlank(message = "제목을 입력하십시오.") | ||
@Size(min = 3, message = "제목은 세 글자 이상 입력하세요.") | ||
String title, | ||
@NotBlank(message = "본문을 입력하십시오") | ||
@Size(min = 3, message = "제목은 세 글자 이상 입력하세요.") | ||
String content | ||
) { | ||
} | ||
Comment on lines
+14
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💊 테스트 편의성을 위해 요청 DTO에도
|
||
|
||
@Builder | ||
@JsonRootName("board") | ||
public record BoardCommandResponse( | ||
Board board | ||
) { | ||
} | ||
Comment on lines
+34
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. ❗️ 애플리케이션·도메인 계층의 작업자들과 논의하여 ReadModel 등의 설계가 필요해 보입니다.BoardSummaryResponse도 필요하다면 생성할 수 있습니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package me.nettee.board.adapter.driving.web.dto; | ||
|
||
import com.fasterxml.jackson.annotation.JsonRootName; | ||
import lombok.Builder; | ||
import me.nettee.board.application.domain.type.BoardStatus; | ||
import me.nettee.board.application.model.BoardReadDetailModel; | ||
import me.nettee.board.application.model.BoardReadSummaryModel; | ||
|
||
import java.time.Instant; | ||
|
||
public final class BoardQueryDto { | ||
private BoardQueryDto() {} | ||
|
||
@Builder | ||
public record BoardDetailResponse( | ||
BoardReadDetailModel board | ||
){} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package me.nettee.board.adapter.driving.web.mapper; | ||
|
||
import me.nettee.board.adapter.driving.web.dto.BoardCommandDto.BoardCreateCommand; | ||
import me.nettee.board.adapter.driving.web.dto.BoardCommandDto.BoardUpdateCommand; | ||
import me.nettee.board.adapter.driving.web.dto.BoardQueryDto.BoardDetailResponse; | ||
import me.nettee.board.application.domain.Board; | ||
import me.nettee.board.application.model.BoardReadDetailModel; | ||
import org.mapstruct.Mapper; | ||
|
||
@Mapper(componentModel = "spring") | ||
public interface BoardDtoMapper { | ||
|
||
Board toDomain(BoardCreateCommand command); | ||
|
||
Board toDomain(Long id, BoardUpdateCommand command); | ||
|
||
BoardDetailResponse toDtoDetail(BoardReadDetailModel board); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package me.nettee.board.application.model; | ||
|
||
import java.time.Instant; | ||
import me.nettee.board.application.domain.type.BoardStatus; | ||
|
||
public record BoardReadDetailModel( | ||
Long id, | ||
String title, | ||
String content, | ||
BoardStatus status, | ||
Instant createdAt, | ||
Instant updatedAt, | ||
Instant deletedAt | ||
) {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package me.nettee.board.application.model; | ||
|
||
import java.time.Instant; | ||
|
||
public record BoardReadSummaryModel( | ||
Long id, | ||
String title, | ||
String content, | ||
Instant createdAt, | ||
Instant updatedAt | ||
){} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
package me.nettee.board.application.port; | ||
|
||
import java.util.Optional; | ||
import me.nettee.board.application.domain.Board; | ||
|
||
public interface BoardCommandPort { | ||
|
||
Optional<Board> findById(Long id); | ||
|
||
Board create(Board board); | ||
|
||
Board update(Board board); | ||
|
||
void delete(Long id); | ||
|
||
void delete(Board id); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,17 @@ | ||
package me.nettee.board.application.port; | ||
|
||
import me.nettee.board.application.domain.Board; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import me.nettee.board.application.domain.type.BoardStatus; | ||
import me.nettee.board.application.model.BoardReadDetailModel; | ||
import me.nettee.board.application.model.BoardReadSummaryModel; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
import java.util.Optional; | ||
|
||
public interface BoardQueryPort { | ||
|
||
Page<Board> findAll(Pageable pageable); | ||
Optional<BoardReadDetailModel> findById(Long id); | ||
|
||
Optional<Board> findById(Long id); | ||
Page<BoardReadSummaryModel> findByStatusesList(Pageable pageable, Set<BoardStatus> statuses); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package me.nettee.board.application.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import me.nettee.board.application.domain.Board; | ||
import me.nettee.board.application.model.BoardReadDetailModel; | ||
import me.nettee.board.application.port.BoardCommandPort; | ||
import me.nettee.board.application.port.BoardQueryPort; | ||
import me.nettee.board.application.usecase.BoardCreateUseCase; | ||
import me.nettee.board.application.usecase.BoardDeleteUseCase; | ||
import me.nettee.board.application.usecase.BoardUpdateUseCase; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class BoardCommandService implements BoardCreateUseCase, BoardUpdateUseCase, BoardDeleteUseCase { | ||
|
||
private final BoardCommandPort boardCommandPort; | ||
|
||
public Board createBoard(Board board) { | ||
return boardCommandPort.create(board); | ||
} | ||
|
||
public Board updateBoard(Board board) { | ||
return boardCommandPort.update(board); | ||
} | ||
|
||
public void deleteBoard(Long id) { | ||
Board board = boardCommandPort.findById(id).orElseThrow( | ||
() -> new IllegalArgumentException("게시글을 찾을 수 없습니다.")); | ||
|
||
board.softDelete(); | ||
|
||
boardCommandPort.delete(board); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package me.nettee.board.application.service; | ||
|
||
import java.util.Set; | ||
import lombok.RequiredArgsConstructor; | ||
import me.nettee.board.application.domain.type.BoardStatus; | ||
import me.nettee.board.application.model.BoardReadDetailModel; | ||
import me.nettee.board.application.model.BoardReadSummaryModel; | ||
import me.nettee.board.application.port.BoardQueryPort; | ||
import me.nettee.board.application.usecase.BoardReadByStatusesUseCase; | ||
import me.nettee.board.application.usecase.BoardReadUseCase; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class BoardQueryService implements BoardReadUseCase, BoardReadByStatusesUseCase { | ||
|
||
private final BoardQueryPort boardQueryPort; | ||
|
||
@Override | ||
public BoardReadDetailModel getBoard(Long id) { | ||
return boardQueryPort.findById(id).orElseThrow( | ||
() -> new IllegalArgumentException("게시글을 찾을 수 없습니다.")); | ||
} | ||
|
||
@Override | ||
public Page<BoardReadSummaryModel> findByStatuses(Set<BoardStatus> statuses, Pageable pageable) { | ||
return boardQueryPort.findByStatusesList(pageable, statuses); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,5 @@ | |
public interface BoardCreateUseCase { | ||
|
||
Board createBoard(Board board); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ | |
public interface BoardDeleteUseCase { | ||
|
||
void deleteBoard(Long id); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package me.nettee.board.application.usecase; | ||
|
||
import java.util.Set; | ||
import me.nettee.board.application.domain.type.BoardStatus; | ||
import me.nettee.board.application.model.BoardReadSummaryModel; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
|
||
public interface BoardReadByStatusesUseCase { | ||
|
||
Page<BoardReadSummaryModel> findByStatuses(Set<BoardStatus> statuses, Pageable pageable); | ||
|
||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,9 @@ | ||
package me.nettee.board.application.usecase; | ||
|
||
import me.nettee.board.application.domain.Board; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import me.nettee.board.application.model.BoardReadDetailModel; | ||
|
||
public interface BoardReadUseCase { | ||
|
||
Board getBoard(Long id); | ||
BoardReadDetailModel getBoard(Long id); | ||
|
||
Page<Board> findGeneralBy(Pageable pageable); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ | |
public interface BoardUpdateUseCase { | ||
|
||
Board updateBoard(Board board); | ||
|
||
} |
Uh oh!
There was an error while loading. Please reload this page.