Search

Optionals 패키지를 활용해서 코드를 간결하게 만들어보자.

카테고리
꿀팁 🐝🌸
유형
코드가 절반으로 줄었어요!
Date
Tags
Java
1 more property
글을 읽기 전에 함수형 프로그래밍에 대해 알면 좋다.
각 도메인 로직을 조합하여 Application 로직을 만들다 보면 아래와 같은 코드가 많이 보인다.
스토어와 상품을 찾아 스토어에서 해당 상품을 삭제 하는 로직
@Transactional public void deleteProduct(final Long storeId,final Long productId) { // 스토어를 찾는다. final Store foundStore = storeService.findStoreById(storeId) .orElseThrow(StoreNotFoundException::new); // 상품을 찾는다. final Product product = productService.findProductById(productId) .orElseThrow(() -> new BusinessException(ErrorCode.PRODUCT_NAME_IS_EMPTY)); // 스토어에서 상품을 지운다. foundStore.deleteProduct(product); }
Java
복사
위 처럼 두 가지 모두 존재해야 실행할 수 있는 특정 상황에 사용할 수 있는 메서드가 있다.
public interface Optionals { public static boolean isAnyPresent(Optional<?>... optionals) { Assert.notNull(optionals, "Optionals must not be null"); return Arrays.stream(optionals).anyMatch(Optional::isPresent); } public static <T, S> void ifAllPresent(Optional<T> left, Optional<S> right, BiConsumer<T, S> consumer) { Assert.notNull(left, "Optional must not be null"); Assert.notNull(right, "Optional must not be null"); Assert.notNull(consumer, "Consumer must not be null"); mapIfAllPresent(left, right, (l, r) -> { consumer.accept(l, r); return null; }); } public static <T, S, R> Optional<R> mapIfAllPresent(Optional<T> left, Optional<S> right, BiFunction<T, S, R> function) { Assert.notNull(left, "Optional must not be null"); Assert.notNull(right, "Optional must not be null"); Assert.notNull(function, "BiFunction must not be null"); return left.flatMap(l -> right.map(r -> function.apply(l, r))); } }
Java
복사
Optionals 인터페이스에서 Optional을 조합하여 로직을 실행하는 메서드를 정적 메서드로 제공하고 있다.

ifAllPresent

Optional<T>, Optional<S> 타입의 매개변수를 받고 두 매개변수를 받아 처리하는 BiConsumer<T,S>도 받는다.
여기서 BiConsumer의 제너릭 타입은 ifAllPresent 메서드에서 첫번째와 두번 째 받은 Optional 타입의 제너릭 타입과 같은 타입이다.
다시 말해 매개변수로 받은 Optional 타입의 값 두개가 모두 존재한다면 BiConsumer를 실행한다.
1.
값 검증
Assert.notNull(left, "Optional must not be null"); Assert.notNull(right, "Optional must not be null");
Java
복사
2.
BiConsumer 실행
return left.flatMap(l -> right.map(r -> function.apply(l, r)));
Java
복사
존재 여부가 불확실한 두 변수가 둘다 존재할 때만 특정 로직을 실행하는 상황에서 이 메서드를 사용하면 간단한 처리가 가능하다.
// Store, Category 두개 다 존재하는 상황에서 카테고리를 삭제한다. return mapIfAllPresent( of(foundStore), categoryService.findCategory(foundStore, categoryName), Store::deleteCategory) .map(StoreResponse::from) .orElseThrow(NoSuchElementException::new); }
Java
복사
만약 리턴 값을 통해 다른 타입으로 매핑하는 상황이 아니라면 리턴 값이 필요없는 ifAllPresent() 메서드를 사용해도 좋다.