• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

setter 대신 Builder를 사용하여 구성했는데 꼬임에 대해서

23.06.13 20:01 작성 조회수 610

2

setter 사용을 지양하기 위해
setter를 사용하지 않고 Builder 패턴으로 구현하여 코드를 작성하던중 OrderService의 order() 메서드를 테스트 하는데 NullPointerException이 발생했습니다.

어디서부터 꼬인지를 모르겠어서
어디부터 물어봐야할지를 모르겠네요...

그래서 이후 강의에서는 setter를 사용하지않고
정석대로 생성자를 이용하는 방식을 사용하는 강의가 있는지 궁금합니다.

답변 1

답변을 작성해보세요.

0

OMG님의 프로필

OMG

2023.06.13

안녕하세요. HH님, 공식 서포터즈 OMG입니다.

코드를 봐야 알겠지만 제 생각으로는 모든 필드를 가진 생성자에 빌더 패턴을 적용하거나 lombok @Builder를 붙이셨거나, 엔티티 바로 위에 @Builder 를 다신 것 같습니다. 그럴 경우 builder 로 생성할 때 없는 값은 null로 입력되기 때문에 발생한 문제로 보입니다. 빌더를 사용하실 거라면 collection은 빼고 생성자를 만드신 후 해당 생성자에 빌더 패턴을 적용하시면 해당 문제는 해결되실 것 같습니다~  
추가로 lombok 의 @Builder 를 사용 중이시라면 @Builder.default 를 찾아보시면 해당 어노테이션 사용 시 기본 값을 설정할 수 있습니다. 검색해보시고 적용해보시는 것도 좋을 것 같습니다. 

영한님의 모든 강의의 코딩 스타일은 본 강의와 큰 차이는 없습니다.

감사합니다.

HH님의 프로필

HH

질문자

2023.06.14

답변 감사합니다.
생성자에 @Builder를 붙여 빌더패턴을 적용했는데
말씀하신대로 생성자에 연관관계에 해당하는 엔티티의 Collection을 넣었습니다.
해결 방법으로 생성자에 Collection을 빼라고 하셨는데 여기서 질문이 있습니다.

### 추가 질문

  1. 엔티티의 생성자에 빌더 패턴을 적용할 때는 컬렉션을 제외한 필드만 넣어서 작성하고,

연관관계 편의 메서드 대신 아래의 코드 처럼 생성자에서 값을 주입하는 방식은 상관없을까요?

    @Builder
    public Order(Member member, Delivery delivery, LocalDateTime orderDate,
                 OrderStatus status) {
        this.member = member;
        this.delivery = delivery;
        this.orderDate = orderDate;
        this.status = status;
        if (member != null) {
            member.getOrders().add(this);
        }
        if (delivery != null) {
            Delivery.builder()
                    .order(this)
                    .build();
        }
    }
  1. 정석적인 코드 스타일을 따른다면 연관관계 편의 메서드는 연관관계 주인에 해당되는 엔티티에 작성을 하는 것이 맞나요 ??

    강의에서 하는 방식대로 Order 클래스에 모든 연관관계 편의 메서드를 작성하는 과정에서
    "다"에 해당되는 OrderItems엔티티에 값을 넣어야 하는데 아래의 코드에 해당하는 부분에 대해 어떻게 작성을 해야하는지 모르겠어서 질문해봅니다.

    public void addOrderItem(OrderItem orderItem) {
        orderItems.add(orderItem);
        orderItem.setOrder(this) // <-- 이부분을 setter를 사용하지 않고 빌더패턴을 사용한다면 어떻게 해야하는지?? 
    }

 

  1. 빌더 패턴을 사용하여 주문 생성 메서드 createOrder()를 작성하는 게 아래의 방식으로 작성하는게 맞나요??

    public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems) {
        Order order = Order.builder()
                .member(member)
                .delivery(delivery)
                .status(OrderStatus.ORDER)
                .orderDate(LocalDateTime.now())
                .build();
        for (OrderItem orderItem : orderItems) {
            order.orderItems.add(orderItem);
        }
        return order;
    }

안녕하세요. HH님

질문을 잘 정리해주셔서 번호에 맞추어 간단히 답변을 드리겠습니다.

  1. 네 괜찮습니다.

  2. 양방향 연관관계를 구성할 때 빌더 패턴으로 완전히 구성하지 못하는 경우가 있습니다. 이런 경우에는 setter를 추가해주셔야 합니다.

  3. 네 이렇게 사용하셔도 됩니다.

감사합니다.