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

Chap.8 코드를 모듈화하라 #5

Open
Gilbert9172 opened this issue Oct 26, 2024 · 6 comments
Open

Chap.8 코드를 모듈화하라 #5

Gilbert9172 opened this issue Oct 26, 2024 · 6 comments
Assignees
Labels

Comments

@Gilbert9172
Copy link
Collaborator

Gilbert9172 commented Oct 26, 2024

[Chap8. 코드를 모듈화하라]를 읽고

  • 관련된 issue
  • 다른 의견
  • 잘못된 정보

등을 알려주세요!

@softmoca
Copy link
Collaborator

softmoca commented Nov 3, 2024

❐ 8.3 클래스 상속을 주의하라

저는 개인적으로 해당 주제에 과도하게 동의를 하고 있는 상황인것 같습니다.
미션을 쭉 진행하며 상속은 한번도 생각해 본적이 없고 늘 구성을 사용했는데 저희 미션 1,2 주차 중 상속을 적용하면 좋을 로직이 어떤것들이 있을까요 ?!

개인적으로 가독성 측면에서도 저는 HAS-A관계인 구성이더 좋다고 생각되는데 다른 분들의 의견이 궁금합니다 !

@softmoca
Copy link
Collaborator

softmoca commented Nov 3, 2024

❐ 8.4 클래스는 자신의 기능에만 집중해야 한다.

단일 책임 원칙(SRP)에 관한 주제라고 생각되는데 클래스 자신의 '기능'의 범위에 대해 어떻게 생각하시나요 ?
특히 유효성 검증의 책임은 늘 고민이 되고 있습니다.

유효성 검증의 책임은 검증의 성격과 컨텍스트에 따라 매번 달라진다고 생각하지만 저는 아래와 같이 큰 기준을 세워놓은 뒤 문맥에 따라 다시 한번 고려를 하는 편입니다.
이에 대해 어떻게 생각하시나요 ?

  • 도메인 규칙 → 엔티티 클래스 ex) 자동차 이름은 5자 이하
  • 입력값 검증 → View/DTO ex) null값 혹은 빈값 처리, 숫자 형식인지
  • 비즈니스 규칙 → 서비스 계층 또는 전용 Validator ex) 중복된 자동차 이름이 있는지

@hoonyworld
Copy link
Member

hoonyworld commented Nov 3, 2024

8.7.2 해결책: 추상화 계층에 적절한 예외를 만들라

혹시 스프링에서 Repository에 예외 처리를 두는 거에 대해 어떻게 생각하시나요?

@Gilbert9172
Copy link
Collaborator Author

❐ 8.3 클래스 상속을 주의하라

저는 개인적으로 해당 주제에 과도하게 동의를 하고 있는 상황인것 같습니다. 미션을 쭉 진행하며 상속은 한번도 생각해 본적이 없고 늘 구성을 사용했는데 저희 미션 1,2 주차 중 상속을 적용하면 좋을 로직이 어떤것들이 있을까요 ?!

개인적으로 가독성 측면에서도 저는 HAS-A관계인 구성이더 좋다고 생각되는데 다른 분들의 의견이 궁금합니다 !

우선 저는 2주차 과제 설계하면서 상속을 쓸지 말지 고민을 했습니다.
자동차 경줒에서는 RacingCar 말고도 다양한 타입의 Car 경주가 있을 것이라고 생각했기 때문입니다.

하지만 아래의 이유로 상속을 사용하지 않았습니다.

  • 상위 클래스의 메소드 노출 가능성
  • 추후 기능 추가에 대한 유지 보수성 저하
  • 과도한 설계

가능하다면 HAS-A 구성으로 설계하는 것이 저도 더 좋다고 생각합니다.

@Gilbert9172
Copy link
Collaborator Author

❐ 8.4 클래스는 자신의 기능에만 집중해야 한다.

단일 책임 원칙(SRP)에 관한 주제라고 생각되는데 클래스 자신의 '기능'의 범위에 대해 어떻게 생각하시나요 ? 특히 유효성 검증의 책임은 늘 고민이 되고 있습니다.

유효성 검증의 책임은 검증의 성격과 컨텍스트에 따라 매번 달라진다고 생각하지만 저는 아래와 같이 큰 기준을 세워놓은 뒤 문맥에 따라 다시 한번 고려를 하는 편입니다. 이에 대해 어떻게 생각하시나요 ?

  • 도메인 규칙 → 엔티티 클래스 ex) 자동차 이름은 5자 이하
  • 입력값 검증 → View/DTO ex) null값 혹은 빈값 처리, 숫자 형식인지
  • 비즈니스 규칙 → 서비스 계층 또는 전용 Validator ex) 중복된 자동차 이름이 있는지

저는 아래와 같은 컨벤션으로 작업을 하고 있습니다.

  • 도메인 규칙 → 엔티티 클래스
  • 입력값 검증 → 별도의 Validator 패키지
  • 비즈니스 규칙 → 서비스 계층 또는 엔티티 클래스

그러나 프로젝트의 규모, 요구 사항의 변경과 같은 외부 요인에 의해 충분히 변경될 가능성이 있다고 생각합니다!

@Gilbert9172
Copy link
Collaborator Author

8.7.2 해결책: 추상화 계층에 적절한 예외를 만들라

혹시 스프링에서 Repository에 예외 처리를 두는 거에 대해 어떻게 생각하시나요?

우선 Service layer든 Repository layer든 어디에서 처리해야 한다는 정답은 없다고 생각합니다.
하지만 저는 Service layer에 정의하는 것을 지향해야 하지 않을까 생각합니다.

  1. JPA 메서드의 응답 값의 대부분이 Optional인 것으로 알고 있습니다.

JPA를 사용하는 환경이라면 Optional을 좀 더 활용하여 작업하는 것이 일관성있는 프로젝트를 유지할 수 있다고 생각했습니다.

  1. QueryDsl을 사용하는 경우

만약 Repository에서 아래와 같이 Exception을 터트린다면,
쿼리를 통해 데이터를 조회하고 예외 처리까지 해주는 역할 총 2가지를 하고 있다고 생각합니다.


Repository layer에서 예외를 던지는 경우의 sample code

@Transactional(readOnly = true)
public Member findByXxx(MemberId memberId) {
    Member member = queryFactory
            .selectFrom(member)
            .leftJoin(...).on(...)
            .where(...)
            .fetchOne();
    if (isNull(member)) {
        throw new MemberNotFoundException();
    }
    return member;
}

그럼 위 로직을 호출하는 호출부는 아래와 같이 작성할 수 있을 것입니다.

public void sampleMethod(...) {
	Member member = memberRepository.findByXxx(memberId);
	//...
}

이 경우 호출부에서는 findByXxx()의 예외를 모르게 할 수 있다는 장점이 있을 것 같습니다.



Service layer에서 예외를 던지는 경우의 sample code

@Transactional(readOnly = true)
public Optional<Member> findByXxx(MemberId memberId) {
    Member member = queryFactory
            .selectFrom(member)
            .leftJoin(...).on(...)
            .where(...)
            .fetchOne();
    return Optional.ofNullable(member);
}

그럼 위 로직을 호출하는 호출부는 아래와 같이 작성할 수 있을 것입니다.

public void sampleMethod(...) {
    Member member = memberRepository.findByXxx(...)
                            .orElseThrow(MemberNotFoundException::new);
}

이 경우 repository는 DB에서 데이터를 fetch해오는 한 가지 역할만 하고,
호출부에서 예외를 처리하는 방식으로 작업할 수 있다고 생각합니다.

비록 호출부가 findByXxx()의 예외를 직접적으로 알게되지만, service 코드를 읽으면서
코드의 문맥을 파악할 수 있다는 장점을 가질 수 있다고 생각됩니다!

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

No branches or pull requests

3 participants