Validation Workshop



Validation Workshop

0 0


validation-workshop-intro

A reveal.js lead-in to implementing Validation with Java8 lambdas

On Github benhyland / validation-workshop-intro

Validation Workshop

Why are we here?

  • practice our skills with Java 8 lambdas
  • improve our ability to recognise common functional patterns
  • implement a functional pattern as an exercise

What is functional programming?

As a definition:

  • programming with functions
  • referential transparency/equational reasoning

What is functional programming?

What do we mean to do in our system? Stuff like:

  • data transformations
  • use meaningful types
  • reduce scope of nasty bits
  • improve modularity, reuseablility, testability
  • local reasoning

Workshop goal

We will implement the Validation concept.

This term can be used for different things, even within functional programming. Let's find out what it means for us.

Something might be null!

SomeThing result = repository.getById(42);

if(result != null) {
    doSomeThing(result);
}
					

Something might be null!

Slightly nicer:

Optional<SomeThing> result = repository.findById(42);

result.ifPresent(this::doSomeThing);
					

Something might fail!

Why might it be null? Perhaps something can break.

try {
    SomeThing result = service.performDangerousActionForId(42);
    doSomeThing(result);
}
catch (ServiceException e) {
    handleError(e);
}
					

Something might fail!

Slightly nicer:

Either<ServiceException, SomeThing> result = service.tryDangerousActionForId(42);

result.ifLeft(this::handleError);
result.ifRight(this::doSomeThing);
					

But, what if multiple things might fail?

The remote agent or the service might throw an exception, for several hosts.

List<String> hosts = Arrays.asList("host1", "host2", "host3");
List<SomeOtherThing> results = new ArrayList<>();
List<Exception> errors = new ArrayList<>();

for (String host : hosts) {
    try {
        SomeThing firstResult = remoteAgent.lookupSomeThingOnHost(host);
        SomeOtherThing secondResult = service.useSomeThing(firstResult);
        results.add(secondResult);
    } catch (RemoteException | ServiceException e) {
        errors.add(e);
    }
}
if(errors.isEmpty()) {
    doSomeOtherThings(results);
}
					

Validation generalises this logic

It might look something like this:

List<String> hosts = Arrays.asList("host1", "host2", "host3");

List<Validation<Exception, SomeThing>> firstResults =
        Validation.mapInputs(hosts, remoteAgent::tryLookupSomeThingOnHost);

List<Validation<Exception, SomeOtherThing>> secondResults = 
        Validation.flatMapInputs(firstResults, service::tryUseSomeThing);

Validation<Exception, List<SomeOtherThing>> result = Validation.sequence(secondResults);

result.ifSuccess(this::doSomeOtherThings);
result.ifFailure(this::handleAllErrors);
					

Sum Types

aka disjoint unions

Optional, Either and Validation are all examples of sum types.

A sum type is a data type with several mutually exclusive representations:

  • Optional: Value is present or absent
  • Either: Value is of one type or the other
  • Validation: Either a list of error values, or a single success value

To the code!

  • we'll implement Validation in pairs or small groups.
  • swap who is typing every 5-10 minutes
  • take advice from the whole group
  • the primary goal is to get the tests passing
  • pause often to ensure the entire group understands what has been done so far

Have fun!

http://github.com/benhyland/validation-workshop