-
Notifications
You must be signed in to change notification settings - Fork 171
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
[2기-유민환] SpringBoot Part2 Weekly Mission 제출입니다. #272
[2기-유민환] SpringBoot Part2 Weekly Mission 제출입니다. #272
Conversation
400ab97
to
c40ec73
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
과제하느라 고생 많으셨어요~
오래 고민한만큼 잘 짜주셔서 생각보다 코멘트 달 부분이 많이 없었네요
-
Wallet이 Entity로써 가지는 역할이 생긴다면 새로운 테이블로 가지는게 좋겠죠? 그러나 지금은 단순히 VoucherList를 저장하는 용도라고 한다면 지금 당장은 Wallet의 테이블을 생성할 필요는 없을것 같습니다.
그러나 User가 가지는 Wallet이 여러개가 생길수 있게 되고 이런식으로 확장을 생각해볼 순 있을것 같네요 -
DB와 매핑 되더라도 불변을 유지할 수 있다고 생각합니다. 애초에 모든 필드가 객체 생성일때만 값이 들어가도록 허용하게 만드는게 제일 좋겠죠? 그리고 예를 들면 어떤 비즈니스 로직에 의해서 바뀔 수 있는 필드, 예를 들면 assign�Customer 같은 건 허용하더라도 저런 식으로 set 대신 적절한 이름을 두는게 좋은것 같아요
-
아니요 Entity도 불변으로 유지하는게 좋습니다.
-
VO 내부에 각 필드로써 사용할 만한 값이 있다면 객체로 반환하는게 좋겠죠. 예를 들면 Name 객체에서 FirstName, LastName으로 구분짓는다면요.. 그런데 만약 단순히 필드 하나에 원시 타입이라면 그 원시타입으로 불러와도 될것 같네요
-
저는 개인적으로 VO가 도메인에 사용된다면 그 VO도 최대한 노출을 지양하는 편입니다. 그러나 중복이 많이 생긴다면 VO정도는 공유해도 괜찮을것 같아요
-
넵넵 안그러면 검증할 방법이 쉽지 않을것 같은데요
-
구현체가 하나로 확정적이면 굳이 Interface를 생성할 필요는 없을 것 같습니다.
-
어떻게 보면 Validation도 도메인 로직인셈이죠 또 예를 들면, Voucher 클래스에 discount method를 두고 그 VoucherService에서 discount를 할수도 있겠지만, 도메인 내부에서 계산을 하는식으로 하는 방법도 도메인 로직을 이용하는 방법일 수 있겠네요
-
Mockito 잘 사용해 주셨는데 테스트 코드에 @nested가 너무 많아서 오히려 가독성이 떨어지는 면도 있는 것 같아요. 단순히 메소드 하나를 테스트 할거면 굳이 Nested를 안붙이고 테스트 메소드 하나로 해결하는 방법이 더 간단할 수도 있습니다.
public Customer findByEmail(Email email) { | ||
return findCustomer(email); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
리팩터링을 하면서 나온 실수인 것 같습니다.
삭제하도록 하겠습니다!!
username: root | ||
password: root1234! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
password는 노출안되도록 주의해주세요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
노출안되도록 습관화하는 자세를 가져야 겠습니다.
실무에서는 어떻게 설정파일을 관리하는 편인가요?? 🤔
private final LocalDateTime createdTime; | ||
private Name name; | ||
private Email email; | ||
private LocalDateTime lastLoginTime; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lastLoginAt 보다는 updatedAt같은 표현이 좋아보입니다.
login의 개념이 여기에는 잘 없는듯해서
FIXED_AMOUNT(1, FixedAmountVoucher::new), | ||
PERCENT_DISCOUNT(2, PercentDiscountVoucher::new); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 Enum Type에 클래스를 넣어서 생성하게 해도 좋네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enum은 정말 무궁무진한 것 같습니다!!
import org.junit.jupiter.params.provider.CsvSource; | ||
|
||
class PercentDiscountVoucherTest { | ||
@DisplayName("정해진 할인퍼센트로 할인한다.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DisplayName("정해진 할인퍼센트로 할인한다.") | |
@DisplayName("정해진 할인퍼센트로 할인한다.") |
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
class VoucherTypeTest { | ||
@DisplayName("command를 통해 해당하는 VoucherType을 반환한다.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DisplayName("command를 통해 해당하는 VoucherType을 반환한다.") | |
@DisplayName("command를 통해 해당하는 VoucherType을 반환한다.") |
} | ||
} | ||
|
||
@Nested |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
테스트 코드에 @nested가 너무 많아서 오히려 관리하기 힘들어지는 것 같아요
테스트 대상이 하나면 하나의 메소드안에서 해결하는것도 좋은것 같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
예외 사항이 많아서 BDD 방식을 연습해보았는 데 너무 과했군요 😅
안녕하세요 아만드 멘토님!!!
이번 미션에서는 피드백 적용과 최대한 MVC패턴에 맞게 구현하려고 해보았습니다. Part1에 비해 설계나 구현이 바뀐 것이 많아서 깔끔한 코드를 유지 못한 것 같습니다 😂 피드백 적용하면서 하나씩 고쳐 나가겠습니다!
이번 리뷰도 잘 부탁드립니다!! 😄
📌 과제 설명
Hamcrest
대신AssertJ
를 사용하였습니다.resources
폴더 아래 sql파일에 있습니다.MemoryVoucherRepository
,FileVoucherRepository
등)에는 추가된 기능을 구현하지 않았습니다.👩💻 요구 사항과 구현 내용
✅ 피드백 반영사항
@Value
를 통해 파일 경로를 가져오도록 하였습니다.✅ PR 포인트 & 궁금한 점
테이블 설계시 wallet 테이블을 새로 생성하는 것이 아닌 voucher테이블에서 customer에 대한 정보를 가지고 있는 것이 맞다고 생각하였습니다. 어떤 설계가 더 좋은 설계인가요?
객체의 경우 되도록
불변
을 유지하고getter
와setter
를 사용하지 않는 것이 좋다고 알고 있습니다. 하지만 이번 미션의 경우getter
와setter
사용이 불가피 하고 그로 인해 불변을 유지하지 못하게 되었습니다. DB와 매핑되기 위해서 어쩔 수 없는 부분일까요?추가적으로 도메인 모델은 불변을 유지하는 것이 좋다고 알고 있는 데 이는 VO에 해당하고 Entity에는 해당되지 않는 말일까요?
이번 미션을 하면서 VO를 사용해보았습니다. 하지만 customer에서 name을 원시값으로 꺼내기 위해 아래와 같이 구현하였는 데 이것보단 VO 객체를 주는 것이 더 맞는 방향일까요?
도메인이 View에 노출되면 안 좋은 것으로 알고 있습니다. 그렇다면 View에서 VO로 입력받아 가져오는 것도 지양해야 할까요?
Repository 단위 테스트의 경우 검증하는 용도로 다른 메서드를 사용해도 되나요? 예를 들어
save
를 테스트한다고 하면findAll
로 검증하는 식으로요!현재는 Service 구현체가 하나라서 인터페이스를 별도로 생성하지 않았는 데 인터페이스를 생성하는 것이 좋을까요?
현재는 Service 단에서 CRUD 로직만 처리하고 있어 도메인 로직을 어떻게 사용하고 활용하는 지 감이 안오는 것 같습니다. 팀 미팅시간에 어떻게 도메인 로직이 이루어지고 저장되어지는 지 설명해주실 수 있을까요?
저번 피드백에서 말씀하신 것처럼 Mockito를 사용해봤는 데 알맞게 사용한 지 확신이 안가네요 ㅎㅎ 고쳐야 할 부분이 있을까요?
오래한 만큼 질문이 많아진 것 같습니다. 😂
순수 자바로만 구현하다가 DB, Spring으로 넘어오니 깔끔하게 구현이 안되는 것 같네요.
피드백 받으면서 고쳐나가도록 하겠습니다.
나머지 미비한 점이나 고쳐야 할점 말씀해주시면 감사하겠습니다!!!