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

[Code Review] 위즈 code review #17

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

[Code Review] 위즈 code review #17

wants to merge 7 commits into from

Conversation

leeseulgi0208
Copy link
Contributor

No description provided.

@leeseulgi0208 leeseulgi0208 self-assigned this Dec 8, 2024
@leeseulgi0208 leeseulgi0208 linked an issue Dec 8, 2024 that may be closed by this pull request
Copy link
Collaborator

Choose a reason for hiding this comment

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

워크북에서는 클래스 단에 @AllArgsConstructor@builder를 같이 사용하였는데, 저는 엔티티 단에 @AllArgsConstructor 적용하는 것을 지양하는 편입니다
그 이유는 다음과 같습니다!

첫번째로, Agreement 클래스 단에 @builder@AllArgsConstructor를 붙이면 외부에서(Controller, Service 계층 등) PK인 id값까지 세팅할 수 있도록 노출됩니다!
PK값은 Auto Increment 전략을 사용한다면 기본적으로 JPA가 그 값을 관리해주는데, 모든 필드에 대한 생성자가 오픈된다면 불변성을 만족하지 못하게 되고, 제일 중요한 데이터 무결성이 깨져버릴 수 있습니다.

두번째로,@AllArgsConstructor를 사용하는 경우 해당 객체를 생성할 때 파라미터의 순서가 실수로 변경되어도 컴파일 에러가 발생하지 않고, 추후 인지하지 못한 치명적인 버그가 발생할 수 있는 여지가 됩니다.
(참조: https://www.inflearn.com/questions/1179578/%ED%98%B9%EC%8B%9C-allargsconstructor-%EB%A5%BC-%EC%A7%80%EC%96%91%ED%95%98%EC%8B%9C%EB%8A%94-%EC%9D%B4%EC%9C%A0%EA%B0%80-%EB%B9%8C%EB%8D%94-%ED%8C%A8%ED%84%B4%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%A8%EC%9D%B8%EA%B0%80%EC%9A%94,
https://obv-cloud.com/35)

그래서 결론적으로는, 클래스단에 붙어있는 @builder@AllArgsConstructor를 제거하고 아래 코드와 같이 id를 제외한 필드만 세팅하는 생성자에 @builder를 붙여주는게 좋을 것 같아요!

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Agreement extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 20)
    private String title;

    @Column(columnDefinition = "TEXT")
    private String description;

    @Column(nullable = false)
    private Boolean optional;

    @OneToMany(mappedBy = "agreement", cascade = CascadeType.ALL)
    private List<UserAgree> userAgreeList = new ArrayList<>();

    @Builder
    public Agreement(String title, String description, Boolean optional) {
        this.title = title;
        this.description = description;
        this.optional = optional;
    }
}

다른 클래스들도 이런식으로 수정해주시면 더 견고한 설계가 될 것 같습니다!

그리고 추가로 Lombok 사용법들에 관하여 구글링하면 잘 정리되어있는 글들이 많이 나오는데, 참고해보시면 좋을 것 같아요!
레퍼런스 하나 첨부하겠습니다!

https://velog.io/@wonizizi99/Spring-%EC%98%AC%EB%B0%94%EB%A5%B8-Lombok-%EC%82%AC%EC%9A%A9%EB%B2%95DtotoEntity-Builder

@Override
@Transactional
public void addReview(ReviewRequestDTO request) {
Store store = storeRepository.findById(request.getStoreId())
Copy link
Collaborator

Choose a reason for hiding this comment

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

StoreQueryServiceImpl에 Store 엔티티를 PK로 조회하는 메서드를 만들어서 storeService.findByStoreId(request.getStoreId())와 같이 참조하는 건 어떨까요? 그 방법이 재사용성 측면에서나, 계층간 참조의 간결성 면에서나 더 좋을 것 같아요!
그러면 각 도메인의 비즈니스 로직 계층에서만 영속성 계층을 참조하는 깔끔한 아키텍처가 만들어질 것 같습니다!
다른 도메인들도 그렇게 수정해보면 좋을 것 같아요!

-> 이미 StoreQueryService 인터페이스에서 findStore 메서드를 정의해놓으셨는데 해당 메서드를 활용하면 될 것 같습니다!

@Retention(RetentionPolicy.RUNTIME)
public @interface MissionAlreadyChallenging {

String message() default "The mission is already being challenged.";
Copy link
Collaborator

Choose a reason for hiding this comment

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

검증 관련 메시지는 한글이나 영어중 하나로 통일해주면 좋을 것 같아요!

@RequiredArgsConstructor
public class MissionAlreadyChallengingValidator implements ConstraintValidator<MissionAlreadyChallenging, Long> {

private final UserMissionRepository userMissionRepository;
Copy link
Collaborator

Choose a reason for hiding this comment

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

validator에서 영속성 계층을 직접적으로 참조하기 보다는 비즈니스 로직 계층을 참조하는게 좋을 것 같습니다!
서로 다른 도메인의 영속성 계층으로 마구 접근이 가능하다면 예기치 않은 데이터의 수정을 일으키고 데이터 무결성을 깨뜨리는 일이 더 많아질 수 있기 때문입니다!


private final StoreCommandService storeCommandService;

@PostMapping("/")
Copy link
Collaborator

Choose a reason for hiding this comment

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

"/" 은 빼도 무방합니다!

@NotBlank(message = "Review content cannot be empty.")
private String content;

@NotNull(message = "Star rating is required.")
Copy link
Collaborator

Choose a reason for hiding this comment

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

가독성 면에서 변수에 애노테이션들을 붙이는게 좋아보여요!

Copy link
Collaborator

@strongmhk strongmhk left a comment

Choose a reason for hiding this comment

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

고생하셨습니다 👏

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.

[feat] wis - week9
2 participants