DevKim

[ Webtooniverse ] Refactor - 정적 팩토리 메서드 본문

Spring Project/Webtooniverse

[ Webtooniverse ] Refactor - 정적 팩토리 메서드

on_doing 2021. 8. 3. 14:51
728x90

[ 정적 팩토리란? ]

: 정적 팩토리 메서드란 객체 생성의 역할을 하는 클래스 메서드라는 의미로 요약해볼 수 있다.


[ 정적 팩토리 메서드는 왜 사용할까? ]

: 내가 코드를 짜면서 느낀 장점은 다음과 같다.

 

1. 이름을 가질 수 있다.

- 이건 과거에 김영한님의 JPA 강의를 들을 때의 실습 코드이다.

new로 Order를 생성하면 정확한 의미를 알 수 없다.

반대로 다음과 같이 createOrder이라는 이름을 가지면, 주문을 생성하는 메서드구나! 를 명시적으로 알 수 있다.

  /** 
  * 주문 생성 메서드
  * todo : 주문 회원, 배송 정보, 상품명을 입력하여 주문 생성
  */
  
  public static Order createOrder (Member
        member, Delivery delivery, OrderItem...orderItems){
            Order order = new Order();
            order.setMember(member);
            order.setDelivery(delivery);
            for (OrderItem item : orderItems) {
                order.addOrderItem(item);
            }
            order.setStatus(OderStatus.ORDER);
            order.setOrderDate(LocalDateTime.now());
            return order;
        }

 

2. 객체 생성을 캡슐화할 수 있다.

- 캡슐화는 데이터의 은닉을 말한다. 여기서는 생성자를 클래스의 메서드 안으로 숨기면서 내부 상태를 외부에 드러낼 필요없이 객체 생성 인터페이스 단순화 시킬 수 있다.

- 개인적으로 DTO와 Entity간에는 자유롭게 형 변환시에 유용하게 사용하고있다.

 

* 정적 팩토리 메서드 네이밍 컨벤션 *

  • valueOf, of : 여러개의 매개변수를 받아 객체 생성
  • from : 하나의 매개 변수를 받아 객체를 생성
  • getInstance, instance : 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음
  • newInstance, create : 매번 새로운 인스턴스를 생성
  • get[OtherType]: getInstance와 같으나 다른 타입의 인스턴스를 생성. 이전에 반환했던 것과 같을 수 있음.
  • new[Othrer Type]  : 다른 타입의 새로운 인스턴스를 생성.

 

- 그 외에도, 코드의 간결과, 호출할 때마다 새로운 객체를 생성 할 필요 없음, 하위 자료형 객체를 반환할 수 있음 등의 장점들이 있다.


[ Refactor ]

- 조금은 의도하고.. 막 짠 코드들이지만,, 하나씩 고쳐나가보자.

 

1. 내 리스트에 추가하는 기능 구현체 리팩토링

- 내 리스트에 해당 웹툰 정보를 저장하는 기능을 담당한다.

 

유의미한 메소드를 사용하여 MyList 객체를 생성하려했지만, 고치고 싶은 욕구가 드는 코드이다.

public void createMyList(User user, Long webtoonId)
    {
        Webtoon webtoon = webtoonRepository.findById(webtoonId).orElseThrow(
                () -> new IllegalArgumentException("해당 웹툰은 존재하지 않습니다.")
        );

        MyList myList = new MyList();
        myList.createMyList(user,webtoon);

        myListRepository.save(myList);
    }

위에 코드는 다음과 같이 변경함으로써 가독성이 좋아졌음을 느낄 수 있다.

MyList myList = MyList.of(user,webtoon);
myListRepository.save(myList);
public static MyList of(User user, Webtoon webtoon)
{
	return new MyList(user,webtoon);
}

2. 리뷰에 좋아요 누르는 기능 구현체

- 리뷰에 좋아요를 처음 누르는 경우, ReviewLike 테이블에 새로 들어온 정보를 추가해주어야한다.

 

현재 코드는 다음과 같다. 리팩토링을 해보자

if (reviewLike.getReviewStatus() == null) {
    //전체 카운트 +1
    findReview.plusLikeCount();

    //ReviewLike에 해당 유저와 리뷰 추가
    ReviewLike newReviewLike = ReviewLike.builder()
    		.review(findReview)
    		.user(user)
    		.reviewStatus(ReviewLikeStatus.LIKE)
    		.build();

    reviewLikeRepository.save(newReviewLike);
}

정적 팩토리 메서드를 생성해주고,

어차피 새로 생성되는 객체는 좋아요 상태가 LIKE이기 때문에 안에서 LIKE를 넣어주었다.

public static ReviewLike of(User user, Review review)
{
	return new ReviewLike(user,review,ReviewLikeStatus.LIKE);
}

위의 코드가 다음과 같이 간결해진 것을 알 수 있다.

if (reviewLike.getReviewStatus() == null) {
  //전체 카운트 +1
  findReview.plusLikeCount();

  //ReviewLike에 해당 유저와 리뷰 추가
  ReviewLike newReviewLike = ReviewLike.of(user,findReview);

  reviewLikeRepository.save(newReviewLike);
}

 

 

728x90
Comments