javafunctional-programmingvavr

What is the way to chain methods with different signatures describing a business process?


I have the following process I'd like to describe with chained methods returning Either.

The process receives a context object containing a WhateverInput and correlationId and processes these in the following steps:

The correlationId is there to mark which process the operation belongs to if the process fails.

What I tried is map and flatMap, but both of them expects a function where the input is the Either's Right and an Either as a return value. However my method signatures look like below due to that I don't want to put the correlation id into a field.


public class VavrPractice {

    public static void handle(Context context) {

        var result = Either.right(context)
            .map(validateInput(context.getWhateverEntityInput(), context.getCorrelationId())) // shows error
    }

    private static Either<ErrorResult, WhateverEntityInput> validateInput(WhateverEntityInput whateverEntityInput, UUID correlationId) {}

    private static Either<ErrorResult, WhateverEntity> mapToWhateverEntity(WhateverEntityInput whateverEntityInput, UUID correlationId) {}

    private static Either<ErrorResult, WhateverEntity> saveToDatabase(WhateverEntityInput whateverEntityInput, UUID correlationId) {}

    private static Either<ErrorResult, WhateverEntityResult> mapToWhateverEntityResult(WhateverEntity whateverEntity, UUID correlationId) {}
}

How to do this in a nice, best/good practices way? What I can think of is creating a Context object adding to it both the WhateverInput and correlationId and this Context will be the Right side of the Either and moving this object between methods. But, it feels a bit clunky, heavy.

I study functional programming in both Java and C# in the same time and the example above can be done in C# using Bind and I am looking for an equivalent for that or the solution how the Bind, what it seems like map or flatMap, can be done.

FYI, this exact question is asked in the vavr repo on GitHub.


Solution

  • If you fix your types a little you can do

        public static void handle(ContextX context) {
            UUID correlationId = context.getCorrelationId();
            var result = Either.<ErrorResult, WhateverEntityInput>right(context.getWhateverEntityInput())
                .flatMap(i -> validateInput(i, correlationId))
                .flatMap(i -> mapToWhateverEntity(i, correlationId))
                .flatMap(e -> saveToDatabase(e, correlationId))
                .flatMap(e -> mapToWhateverEntityResult(e, correlationId));
        }