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

로빈 1단계 제출 #8

Open
wants to merge 79 commits into
base: robinjoon
Choose a base branch
from

Conversation

robinjoon
Copy link
Member

@robinjoon robinjoon commented May 2, 2024

robinjoon and others added 30 commits April 30, 2024 14:30
- 상태코드를 200 -> 201 변경
- Location 헤더 추가

Co-authored-by: zangsu <zangsu_@naver.com>
- 상태코드를 200 -> 201 변경
- Location 헤더 추가

Co-authored-by: zangsu <zangsu_@naver.com>
- 상태코드를 200 -> 204 변경

Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
- 어차피 자원이 존재하지 않는 것은 동일하므로 문제가 없다고 결정

Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
- 테마 이름, 설명, 썸네일 이미자가 비어 있을 경우 에러
- 중복된 이름의 테마 생성 요청시 에러

Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
- 이미 구현된 기능의 체크 리스트 누락된 것 작성

Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
Co-authored-by: zangsu <zangsu_@naver.com>
robinjoon and others added 18 commits May 2, 2024 11:50
작업 컴퓨터 변경을 위한 PR
- 이름이 비어있지 않아야 한다는 조건은 모든 도메인이 공통적으로 가질 가능성이 그렇지 않을 가능성보다 훨씬 높다고 판단함.
- 식별자가 null 인 경우 이 getId 메서드를 호출할 때 예외가 발생하는 것이 타당하다고 판단.
- 변수명을 변경하는 것 대신 메서드를 분리하는 것이 더 가독성이 향상된다고 판단
- Controller 는 서비스의 코드를 그대로 호출하므로 테스트 작성이 필요하지 않다고 판단
- 단, 기존의 잘 동작하는 테스트 코드를 삭제하지는 않음
… 생각이 듭니다." 삭제

- 각자 추구하는 방향이 달라 페어 프로그래밍이 끝난 후 각자 개선하는 것으로 합의
- 도메인으로 이동할 수 있는 책임을 이동
- 각자 추구하는 방향이 달라 페어 프로그래밍이 끝난 후 각자 개선하는 것으로 합의
- 4~6 단계 인증 인가가 들어갈 때 고민이 해소 될 것이라 판단
Copy link
Member

@hyxrxn hyxrxn left a comment

Choose a reason for hiding this comment

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

잘 읽었습니닷
다음 단계도 화이팅!

README.md Outdated
- [x] 중복된 이름의 테마 생성 요청시 에러
- [x] 예약이 있는 테마를 삭제 요청시 에러

- [ ] 사용자 예약 기능 추가
Copy link
Member

Choose a reason for hiding this comment

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

체크를 잊었나요....?!? ㅋㅋㅋㅋ

Copy link
Member Author

Choose a reason for hiding this comment

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

image ... 네

Comment on lines +14 to +15
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
Copy link
Member

Choose a reason for hiding this comment

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

저도 이런걸 추가하려다 말았는데... 로빈은 이 부분을 따로 만들어둔 이유가 뭔가요?

Copy link
Member Author

Choose a reason for hiding this comment

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

저도 이런걸 추가하려다 말았는데... 로빈은 이 부분을 따로 만들어둔 이유가 뭔가요?

  1. 응답이나 요청의 시간 포맷이 API 마다 다른 경우는 거의 없다고 판단.

    • 따라서 전역적으로 시간 포맷을 결정해야 한다고 생각했음.
    • 만약, 특정 API에서 시간 포맷이 달라진다면 그곳에서만 추가적인 설정이 가능하기 때문에 대응이 가능함.
  2. 예외를 잡을 수 있음

    • Spring에서 핸들러의 메서드 파라미터를 역직렬화하는 과정에서 오류가 있다면 지정된 예외를 던짐.
    • 그리고 그 예외는 ControllerAdvice 에서 잡을 수 있음.
    • 따라서 잘못된 포맷이 입력되었을 경우의 예외 처리를 할 수 있음.

import roomescape.service.AvailableTimeService;

@RestController
@RequestMapping("/availableTimes")
Copy link
Member

Choose a reason for hiding this comment

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

새로 컨트롤러를 만들었네요...!
저는 시간 목록을 준다는 의미에서 /times에서 관리하도록 두었는데요,
이렇게 나누면 좋은 점이 뭔가요?

Copy link
Member Author

Choose a reason for hiding this comment

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

새로 컨트롤러를 만들었네요...! 저는 시간 목록을 준다는 의미에서 /times에서 관리하도록 두었는데요, 이렇게 나누면 좋은 점이 뭔가요?

좋은 점이라기 보단, 기존의 방탈출 시작 시간 자원과 이 API가 제공해야하는 자원이 전혀 다른 자원이라고 생각했습니다. 왜냐면 이 API가 제공하는 자원은 "예약" 이라는 행위의 영향을 받기 때문입니다.

그런데 이 결정이 일반적인 URI 설계는 아닌 것 같아서 확인해보는 중입니다.

Comment on lines +29 to +30
return ResponseEntity.created(URI.create("/reservations/" + saved.id()))
.body(saved);
Copy link
Member

Choose a reason for hiding this comment

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

지금은 바디만 필요한 상태인데 URI까지 담아서 리턴하는 이유가 있을까요?

@ResponseStatus(HttpStatus.CREATED) 를 사용하면 ResponseEntity 없이도 201을 넘길 수 있답니닷...!
저는 이번에 알아서 이걸 사용해봤는데... 로빈은 알고 있지만 안썼을 수도 있겠다 싶어서 궁금하네용

Copy link
Member Author

Choose a reason for hiding this comment

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

지금은 바디만 필요한 상태인데 URI까지 담아서 리턴하는 이유가 있을까요?

@ResponseStatus(HttpStatus.CREATED) 를 사용하면 ResponseEntity 없이도 201을 넘길 수 있답니닷...! 저는 이번에 알아서 이걸 사용해봤는데... 로빈은 알고 있지만 안썼을 수도 있겠다 싶어서 궁금하네용

현재 테스트코드에 반영되었는지는 모르겠지만(워낙 시간이 없었어서...) Controller의 단위 테스트에서 상태코드를 검증할 수 있다는 장점도 있고, 가독성도 나쁘지 않아서 이렇게 했습니다.

Comment on lines +34 to +36
public List<ThemeResponse> findAndOrderByPopularity(@RequestParam LocalDate start,
@RequestParam LocalDate end,
@RequestParam int count) {
Copy link
Member

Choose a reason for hiding this comment

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

오오 세개를 다 받아서 했군요!
오늘 수업 때 잠깐 생각했지만... 변경에 정말 용이한 코드인 것 같네요!

}

public ReservationResponse save(ReservationRequest reservationRequest) {
Reservation saved = reservationRepository.save(reservationRequest);
Copy link
Member

Choose a reason for hiding this comment

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

저는 로직이 추가되지 않았더라도 레파지토리에 이 dto가 그대로 가면 안된다고 생각했는데, 첫 미션에서는 request를 그대로 보냈었네요
이유가 있나요?

Copy link
Member Author

Choose a reason for hiding this comment

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

저는 로직이 추가되지 않았더라도 레파지토리에 이 dto가 그대로 가면 안된다고 생각했는데, 첫 미션에서는 request를 그대로 보냈었네요 이유가 있나요?

woowacourse/spring-roomescape-admin#155 (comment) 이전 미션 리뷰어도 동일한 질문을 주셨는데요, 답변 참고해 주시면 될 것 같아요!

Copy link
Member

Choose a reason for hiding this comment

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

오오.... 저는 모 크루와 이야기해본 결과 아직 입력이 되지 않은 정보는 당연히 null이면 된다! 라는 결론을 얻었답니다
그래서

    public Reservation toReservation() {
        return new Reservation(
                null,
                new Name(name),
                new Theme(themeId, null, null, null),
                new ReservationDate(date),
                new ReservationTime(timeId, (LocalTime) null));
    }

이런 코드도 있어요.... ㅋㅋㅋㅋㅋㅋ
그냥 이런 생각도 있다는....!!!

KeyHolder keyHolder = new GeneratedKeyHolder();
save(reservation, keyHolder);
save(beforeSaved, keyHolder);
Copy link
Member

Choose a reason for hiding this comment

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

이 메서드는 그냥 길어서 뺀건가요???

Copy link
Member Author

Choose a reason for hiding this comment

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

이 메서드는 그냥 길어서 뺀건가요???

네. 메서드가 길어지는데, 읽기 좋은 단위로 분리할 수 있을 것 같아서 분리했습니다.


@Override
public List<Theme> findAll() {
return jdbcTemplate.query("select ID, NAME, DESCRIPTION, THUMBNAIL from THEME", themeRowMapper);
Copy link
Member

Choose a reason for hiding this comment

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

이 쿼리문 대소문자가 좀 특이하네요......?!

Copy link
Member Author

Choose a reason for hiding this comment

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

이 쿼리문 대소문자가 좀 특이하네요......?!

인텔리제이 자동 생성 기능을 사용하기 위해서는 스키마를 등록해줘야 하는데, 중간에 그 작업을 해서 이전에 제가 작성한 코드와 인텔리제이가 자동 생성한 쿼리가 섞여서 이렇게 되었어요.

다음 PR에서 바꾸려구요

Comment on lines 25 to 32
//todo : 메서드 개선
public List<AvailableTimeResponse> findByThemeAndDate(LocalDate date, long themeId) {
Set<Long> alreadyReservedTimeIds = reservationRepository.findAll().stream()
.filter(reservation -> reservation.isDateOf(date))
.filter(reservation -> reservation.isThemeOf(themeId))
.map(Reservation::getReservationTime)
.map(ReservationTime::getId)
.collect(Collectors.toSet());
Copy link
Member

Choose a reason for hiding this comment

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

예약을 db에서 전부 가져오는 것부터가... 문제이지 않을지...........

Copy link
Member Author

Choose a reason for hiding this comment

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

예약을 db에서 전부 가져오는 것부터가... 문제이지 않을지...........

맞아요. 원래대로면 절대 이렇게 안할텐데 이번 미션에 다른 중요한 일들이랑 겹치는 바람에 시간이 없어서 이렇게 되었어요. ㅠㅠ


import java.time.LocalTime;

public record AvailableTimeResponse(long id, LocalTime startAt, boolean isBooked) {
Copy link
Member

Choose a reason for hiding this comment

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

저는 time 도메인에 booked를 추가했는데 이 방법이 더 좋아보이네요!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants