johanhaleby / occurrent

Unintrusive Event Sourcing Library for the JVM
https://occurrent.org
125 stars 16 forks source link

Add "functional utils" for Java #17

Closed johanhaleby closed 4 years ago

johanhaleby commented 4 years ago

Create utilities that allow doing this:

String gameId = ... // From a form parameter
int guess = .. // From a form parameter
int randomNumber = .. // From a form parameter
applicationService.execute(gameId, compose(partial2(NumberGuessingGame::startGame, gameId, randomNumber),  partial1(NumberGuessingGame::makeGuess, guess));

We probably need two different compose methods, one for (List<CloudEvent>) -> List<CloudEvent> and one for (Stream<CloudEvent>) -> Stream<CloudEvent> (maybe call them composeList and composeStream?). Implementation may look something like this:

class ComposeActions implements Function<List<CloudEvent>, List<CloudEvent>> {

    private final List<Function<List<CloudEvent>, List<CloudEvent>> fns;

    private ComposeActions(List<Function<List<CloudEvent>, List<CloudEvent>> fns) {
        this.fns = fns
    }

    public static Function<List<CloudEvent>, List<CloudEvent>> compose(..) {
        return new ComposeActions(..);
    }

    public List<CloudEvent> apply(List<CloudEvent> initialEvents) {
        return fns.foldLeft(State::new, (state, fn) -> {
var allEvent = new ArrayList<>(initialEvents);
allEvents.addAll(state.newEvents);
            var newEvents = fn.apply(allEvents);
            state.newEvents.addAll(newEvents);
            return state.newEvents;
        });
    }

    private static class State {
        List<CloudEvent> newEvents = new ArrayList<>();
    }
}

The partial methods should also be tailored for having "right application" (usually partial application is from the left side).

johanhaleby commented 4 years ago

Maybe put this in "util-application-service" and include generic AS there as well.

johanhaleby commented 4 years ago

Another function that would be good would be something that converts Function<Stream<T>, Stream<T>> functionThatCallsDomainModel into a Function<List<T>, List<T>> functionThatCallsDomainModel.