Skip to content

A fluent library to combine two optionals and operate on them.

Notifications You must be signed in to change notification settings

atakanserin/OptionalCombiner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 

Repository files navigation

It can be the case that code components can return more than one Optionals to be processed together. Code can easily get too nested with if else statements or using Optional.flatMap to combine two Optionals. This library is meant to improve the readability by providing a fluent API on operating with two Optionals at the same time.

There are many attemps to implement alike libraries such as Guava BiOptional library or QuarterBukkit BiOptional. However they do not have factory methods with Optionals as parameters. They just take in nonOptional values which makes the use case different compared to CombinedOptionals.

The closest implementation to this library is Tomas Linkowski's answer here on: https://stackoverflow.com/questions/51847513/calling-different-methods-based-on-values-of-two-optionals. But this library, OptionalCombiner, implements important ideas like combined reduction to Optional class and combined filtering. OptionalCombiner also has some utilities for transofrming the computation to CompletableFutures.

Sample Usage:

Optional<Integer> creditScoreSourceA = sourceAService.fetchCreditScore();
Optional<Integer> creditScoreSourceB = sourceBService.fetchCreditScore();

OptionalCombiner.of(creditScoreSourceA, creditScoreSourceB)
        .filterLeft(Util::isValidCreditScore)
        .filterRight(Util::isValidCreditScore)
        .mapLeft(Util::adjustCreditScore)
        .mapRight(Util::adjustCreditScore)
        .reduce(Util::combineCreditScores)
        .ifPresentOrElse(
                score -> mqttService.fireSuccessEvent(score),
                () -> mqttService.fireFailureEvent(INCOMPLETE_CREDIT_SOURCES));

Same code is usually written using nested if elses which clutters and nests the code in my opinion:

Optional<Integer> creditScoreSourceA = sourceAService.fetchCreditScore();
Optional<Integer> creditScoreSourceB = sourceBService.fetchCreditScore();

if (creditScoreSourceA.isPresent() && creditScoreSourceB.isPresent()) {
    Integer scoreA = creditScoreSourceA.get();
    Integer scoreB = creditScoreSourceB.get();
    
    if (Util.isValidCreditScore(scoreA) && Util.isValidCreditScore(scoreB)) {
        Integer adjustedScoreA = Util.adjustCreditScore(scoreA);
        Integer adjustedScoreB = Util.adjustCreditScore(scoreB);
        
        Integer combinedScore = Util.combineCreditScores(adjustedScoreA, adjustedScoreB);
        mqttService.fireSuccessEvent(combinedScore);
    } else {
        mqttService.fireFailureEvent(INCOMPLETE_CREDIT_SOURCES);
    }
} else {
    mqttService.fireFailureEvent(INCOMPLETE_CREDIT_SOURCES);
}

Optional flatMap method can be used to combine Optionals also. Better readability compared to if else style, but still not on par with OptionalCombiner in my opinion.

Optional<Integer> creditScoreSourceA = sourceAService.fetchCreditScore();
Optional<Integer> creditScoreSourceB = sourceBService.fetchCreditScore();

creditScoreSourceA
    .filter(Util::isValidCreditScore)
    .map(Util::adjustCreditScore)
    .flatMap(adjustedScoreA -> 
        creditScoreSourceB
            .filter(Util::isValidCreditScore)
            .map(Util::adjustCreditScore)
            .map(adjustedScoreB -> Util.combineCreditScores(adjustedScoreA, adjustedScoreB))
    )
    .ifPresentOrElse(
        combinedScore -> mqttService.fireSuccessEvent(combinedScore),
        () -> mqttService.fireFailureEvent(INCOMPLETE_CREDIT_SOURCES)
    );

About

A fluent library to combine two optionals and operate on them.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages