Skip to content
Merged
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
25 changes: 4 additions & 21 deletions be/src/main/java/todolist/controller/CardController.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
package todolist.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import todolist.domain.event.Action;
import todolist.dto.card.RequestCardDto;
import todolist.dto.card.ResponseCardDto;
import todolist.dto.card.ResponseCardsDto;
import todolist.dto.event.RequestEventDto;
import todolist.service.CardService;
import todolist.service.EventService;

@RestController
public class CardController {

private final CardService cardService;
private final EventService eventService;

@Autowired
public CardController(CardService cardService, EventService eventService) {
public CardController(CardService cardService) {
this.cardService = cardService;
this.eventService = eventService;
}

@GetMapping("/todos")
Expand All @@ -29,26 +22,16 @@ public ResponseCardsDto getTodo() {

@PostMapping("/todo")
public ResponseCardDto add(@RequestBody RequestCardDto requestCardDto) {
ResponseCardDto responseCardDto = cardService.addCard(requestCardDto);
eventService.addEvent(new RequestEventDto(responseCardDto), Action.ADD);
return responseCardDto;
return cardService.addCard(requestCardDto);

Choose a reason for hiding this comment

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

서비스 객체로 책임과 역할을 분리시켜, 컨트롤러는 거들 뿐이라는 사실을 상기했습니다. 👍

}

@PutMapping("/todo/{id}")
public void update(@PathVariable Long id, @RequestBody RequestCardDto requestCardDto) {
String prevSection = cardService.getPrevSection(id);
ResponseCardDto responseCardDto = cardService.updateCard(id, requestCardDto);

if (prevSection.equals(responseCardDto.getSection())) {
eventService.addEvent(new RequestEventDto(responseCardDto), Action.UPDATE);
} else {
eventService.addEvent(new RequestEventDto(prevSection, responseCardDto), Action.MOVE);
}
cardService.updateCard(id, requestCardDto);

Choose a reason for hiding this comment

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

와 눈물이 나는 변화로군요 💯

}

@DeleteMapping("/todo/{id}")
public void delete(@PathVariable Long id) {
ResponseCardDto responseCardDto = cardService.deleteCard(id);
eventService.addEvent(new RequestEventDto(responseCardDto), Action.REMOVE);
cardService.deleteCard(id);
}
}
5 changes: 1 addition & 4 deletions be/src/main/java/todolist/controller/EventController.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package todolist.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import todolist.domain.event.Event;
import todolist.dto.event.ResponseEventDto;
import todolist.service.EventService;

import java.util.List;
Expand All @@ -14,13 +12,12 @@ public class EventController {

private final EventService eventService;

@Autowired
public EventController(EventService eventService) {
this.eventService = eventService;
}

@GetMapping("/events")
public List<ResponseEventDto> getEvents() {
public List<Event> getEvents() {

Choose a reason for hiding this comment

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

이번에는 도메인 객체를 직접 넘겼지만, 결국 DTO 세트를 담아서 넘겨야 하는 시간이 올 것입니다.
누가 왜 그렇게 구현했나요, 무슨 차이가 있나요 라고 면접에서 물어본다면 대답하실 수 있기를 바랍니다.

return eventService.getEventList();
}
}
4 changes: 4 additions & 0 deletions be/src/main/java/todolist/domain/card/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public ResponseCardDto toResponseCardDto() {
return responseCardDto;
}

public boolean isSectionUpdated(String prevSection) {
return prevSection == section;
}

@Override
public String toString() {
return "Card{" +
Expand Down
43 changes: 43 additions & 0 deletions be/src/main/java/todolist/domain/card/Section.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package todolist.domain.card;

import java.util.*;

public enum Section {
TODO("해야할 일"),
DOING("하고 있는 일"),
DONE("완료된 일");


private String sectionTitle;

Section(String sectionTitle) {
this.sectionTitle = sectionTitle;
}

public String getSectionTitle() {
return sectionTitle;
}

public static Map<String, List<Card>> categorizeCards(List<Card> cardlist) {

Map<String, List<Card>> result = new HashMap<>() {{
put(TODO.sectionTitle, new ArrayList<>());
put(DOING.sectionTitle, new ArrayList<>());
put(DONE.sectionTitle, new ArrayList<>());
}};

for (Card card : cardlist) {
String section = card.getSection();
List<Card> responseSection = result.get(findSection(section).sectionTitle);
responseSection.add(card);
}
return result;

Choose a reason for hiding this comment

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

result 도 별도의 object로 wrapping하는 것에 대해서는 어떻게 생각하시나요?

Copy link
Author

Choose a reason for hiding this comment

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

@jypthemiracle 해당 메서드는 요청에 대한 응답값으로 넘겨줄 Map객체를 반환하는 메서드입니다. 하지만 서비스에서 해당 맵객체를 ResponseCardsDto로_ Wrapping하는데 굳이 또 감쌀 필요가 있는지 잘 모르겠습니다!
혹시 제가 놓친 이유가 있다면 알려주시면 감사하겠습니다!

}

private static Section findSection(String sectionTitle) {

Choose a reason for hiding this comment

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

enum에 직접 비즈니스 로직을 넣어준 점 아주 좋습니다 👍

return Arrays.stream(Section.values())
.filter(s -> s.getSectionTitle().equals(sectionTitle))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException());
}
}
8 changes: 4 additions & 4 deletions be/src/main/java/todolist/domain/event/Action.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import java.util.function.BiFunction;

public enum Action {
ADD((dto, action) -> new Event(dto.getTitle(), dto.getCurrentSection(), action)),
MOVE((dto, action) -> new Event(dto.getTitle(),dto.getPrevSection(), dto.getCurrentSection(), action)),
UPDATE((dto, action) -> new Event(dto.getTitle(), dto.getCurrentSection(), action)),
REMOVE((dto, action) -> new Event(dto.getTitle(), dto.getCurrentSection(), action));
ADD((dto, action) -> new Event(dto, action)),
MOVE((dto, action) -> new Event(dto, action)),
UPDATE((dto, action) -> new Event(dto, action)),
REMOVE((dto, action) -> new Event(dto, action));

Choose a reason for hiding this comment

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

훨씬 깔끔하죠? 💯



private BiFunction<RequestEventDto, Action, Event> eventFunction;
Expand Down
16 changes: 3 additions & 13 deletions be/src/main/java/todolist/domain/event/Event.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package todolist.domain.event;

import todolist.dto.event.ResponseEventDto;
import todolist.dto.event.RequestEventDto;

import java.time.LocalDateTime;

Expand All @@ -12,13 +12,8 @@ public class Event {
private Action action;
private LocalDateTime createdAt;


public Event(String cardTitle, String currentSection, Action action) {
this(cardTitle, "", currentSection, action);
}

public Event(String cardTitle, String prevSection, String currentSection, Action action) {
this(-1L, cardTitle, prevSection, currentSection, action, null);
public Event(RequestEventDto dto, Action action) {
this(-1L, dto.getTitle(), dto.getPrevSection(), dto.getCurrentSection(), action, null);
}

public Event(Long id, String cardTitle, String prevSection, String currentSection, Action action, LocalDateTime createdAt) {
Expand Down Expand Up @@ -49,9 +44,4 @@ public String getCurrentSection() {
public Action getAction() {
return action;
}

public ResponseEventDto toResponseEventDto() {
return new ResponseEventDto(id, cardTitle, prevSection, currentSection, action, createdAt);
}

}
2 changes: 0 additions & 2 deletions be/src/main/java/todolist/dto/card/RequestCardDto.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package todolist.dto.card;

import lombok.Getter;
import lombok.Setter;
import todolist.domain.card.Card;

public class RequestCardDto {
Expand Down
20 changes: 4 additions & 16 deletions be/src/main/java/todolist/dto/card/ResponseCardsDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,19 @@

import todolist.domain.card.Card;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ResponseCardsDto {

private Map<String, List<ResponseCardDto>> cards;
private Map<String, List<Card>> cards;

Choose a reason for hiding this comment

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

Card를 mapping하는 object를 별도로 wrapping해서 만들 수는 없을까요?


public ResponseCardsDto() {
cards = new HashMap<>();
cards.put("해야할 일", new ArrayList<>());
cards.put("하고 있는 일", new ArrayList<>());
cards.put("완료된 일", new ArrayList<>());
public ResponseCardsDto(Map<String, List<Card>> cards) {
this.cards = cards;
}

public Map<String, List<ResponseCardDto>> getCards() {
public Map<String, List<Card>> getCards() {
return cards;
}

public void categorizeCards(List<Card> cardlist) {
for (Card card : cardlist) {
String section = card.getSection();
List<ResponseCardDto> responseSection = cards.get(section);
responseSection.add(card.toResponseCardDto());
}
}
}
12 changes: 6 additions & 6 deletions be/src/main/java/todolist/dto/event/RequestEventDto.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package todolist.dto.event;

import todolist.dto.card.ResponseCardDto;
import todolist.domain.card.Card;

public class RequestEventDto {
private String title;
private String prevSection;
private String currentSection;


public RequestEventDto(ResponseCardDto responseCardDto) {
this("", responseCardDto);
public RequestEventDto(Card card) {
this("", card);
}

public RequestEventDto(String prevSection, ResponseCardDto responseCardDto) {
this.title = responseCardDto.getTitle();
public RequestEventDto(String prevSection, Card card) {
this.title = card.getTitle();
this.prevSection = prevSection;
this.currentSection = responseCardDto.getSection();
this.currentSection = card.getSection();
}

public String getTitle() {
Expand Down
48 changes: 0 additions & 48 deletions be/src/main/java/todolist/dto/event/ResponseEventDto.java

This file was deleted.

39 changes: 26 additions & 13 deletions be/src/main/java/todolist/service/CardService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,65 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import todolist.domain.card.Card;
import todolist.domain.card.Section;
import todolist.domain.event.Action;
import todolist.dto.card.RequestCardDto;
import todolist.dto.card.ResponseCardDto;
import todolist.dto.card.ResponseCardsDto;
import todolist.dto.event.RequestEventDto;
import todolist.repository.CardRepository;

import java.util.*;
import java.util.List;

@Service
public class CardService {

private final EventService eventService;
private final CardRepository<Card> repository;

@Autowired
public CardService(CardRepository<Card> repository) {
public CardService(EventService eventService, CardRepository<Card> repository) {
this.eventService = eventService;
this.repository = repository;
}

public ResponseCardsDto getCards() {
List<Card> cards = repository.findAll();

ResponseCardsDto responseCardsDto = new ResponseCardsDto();
responseCardsDto.categorizeCards(cards);
return responseCardsDto;
return new ResponseCardsDto(Section.categorizeCards(cards));
}

@Transactional
public ResponseCardDto addCard(RequestCardDto requestCardDto) {
Card card = repository.save(requestCardDto.toCard());
eventService.addEvent(new RequestEventDto(card), Action.ADD);
return card.toResponseCardDto();
}

@Transactional

Choose a reason for hiding this comment

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

이번 프로젝트의 마지막 숙제입니다.
@Transactional 의 쓰임과 작동 방식을 조사해서 자신만의 언어로 정리해주세요.

public ResponseCardDto updateCard(Long id, RequestCardDto requestCardDto) {
Card card = repository.findById(id);
String prevSection = card.getSection();

card.update(requestCardDto);
repository.update(card);

if (card.isSectionUpdated(prevSection)) {
eventService.addEvent(new RequestEventDto(card), Action.UPDATE);
return card.toResponseCardDto();
}

eventService.addEvent(new RequestEventDto(prevSection, card), Action.MOVE);
return card.toResponseCardDto();
}

@Transactional
public ResponseCardDto deleteCard(Long id) {
Card card = repository.findById(id);
repository.delete(id);
return card.toResponseCardDto();
}

public String getPrevSection(Long id) {
Card card = repository.findById(id);
return card.getSection();
eventService.addEvent(new RequestEventDto(card), Action.REMOVE);

return card.toResponseCardDto();
}
}
Loading