Package-level declarations

This package provides classes for return values from message-handling methods.

Overview

Although tuples are considered harmful in general, they are useful for describing types of several messages returned by a method. Consider the following example.

The return value of the below method does not say much about the number and types of returned event messages. We just know that there may be more than one of them.

@Assign
    List<EventMessage> on(CreateTask cmd) { ... }
The below declaration gives both the number and types of the returned events:
@Assign
    Pair<TaskCreated, Optional<TaskAssigned>> on(CreateTask cmd) { ... }

Why do we suggest returning a tuple (a Pair in the example above) instead of creating a message type which would aggregate those of interest as our colleagues from the Guava team suggest?

Messages returned from a handling method are loosely coupled. They may not be created together all the time. The example above tells that TaskAssigned may not happen upon the creation of the task. It's possible that a task can be assigned sometime later. In this case combining returned messages does not reflect the domain language. Returning a tuple tells a part of the story in terms of the domain language right in the method signature. Details of this story are obtained from the method body.

It should be re-iterated that the purpose of this package is limited to the scenarios of handling messages. Programmers are strongly discouraged from using this package for other purposes.

Two groups of classes

This package provides two groups of classes:
  1. Tuple classes are for returning more than one message.
  2. Alternatives -- classes derived from Either -- are for returning only one message belonging the known set of types.

Generic Parameters

Classes provided by this package can support up to 5 generic parameters. These parameters are named from <A> through <E>. Types that can be passed to these parameters are described in the sections below.

Tuples

The following tuple classes are provided:

The first generic parameter <A> must always be a specific Message class.

Tuple classes allow Optional starting from the second generic argument. The example below shows the method which always returns the TaskCreated event, and returns the TaskAssigned event only if the CreateTask command instructs to assign the task to a person.

@Assign
    Pair<TaskCreated, Optional<TaskAssigned>> on(CreateTask cmd) { ... }

Alternatives

In some cases it is needed to return one message from a limited set of possible options. For example, the following method issues a command MoveToTrash if no work was reported on the task, and CancelTask if some work has been already logged.

@Command
    EitherOf2<MoveToTrash, CancelTask> handle(RemoveTask cmd) { ... }

In order to define alternatively returned values, please use the following classes:

Generic parameters for alternatives accept only Message classes.

We believe that a list of alternatives longer than five is hard to understand. If you face a such a need, consider splitting incoming message into two or more independent ones so that their outcome is more obvious.

Using Tuples with Alternatives

A Pair can be defined with the second parameter being one of the Either subclasses, and created using Pair.withEither().

Types

Link copied to clipboard
public abstract class Either implements Iterable<T>, Serializable
Abstract base for values that can be one of the possible types.
Link copied to clipboard
public final class EitherOf2<A extends Message, B extends Message> extends Either implements Element.AValue<T>, Element.BValue<T>
A value which can be one of two possible types.
Link copied to clipboard
public final class EitherOf3<A extends Message, B extends Message, C extends Message> extends Either implements Element.AValue<T>, Element.BValue<T>, Element.CValue<T>
A value which can be one of three possible types.
Link copied to clipboard
public final class EitherOf4<A extends Message, B extends Message, C extends Message, D extends Message> extends Either implements Element.AValue<T>, Element.BValue<T>, Element.CValue<T>, Element.DValue<T>
A value which can be one of four possible types.
Link copied to clipboard
public class EitherOf5<A extends Message, B extends Message, C extends Message, D extends Message, E extends Message> extends Either implements Element.AValue<T>, Element.BValue<T>, Element.CValue<T>, Element.DValue<T>, Element.EValue<T>
A value which can be one of five possible types.
Link copied to clipboard
public final class Pair<A extends Message, B> extends Tuple implements Element.AValue<T>, Element.BValue<T>
A tuple with two elements.
Link copied to clipboard
public final class Quartet<A extends Message, B, C, D> extends Tuple implements Element.AValue<T>, Element.BValue<T>, Element.CValue<T>, Element.DValue<T>
A tuple with four elements.
Link copied to clipboard
public final class Quintet<A extends Message, B, C, D, E> extends Tuple implements Element.AValue<T>, Element.BValue<T>, Element.CValue<T>, Element.DValue<T>, Element.EValue<T>
A tuple of five elements.
Link copied to clipboard
public final class Triplet<A extends Message, B, C> extends Tuple implements Element.AValue<T>, Element.BValue<T>, Element.CValue<T>
A tuple with three elements.
Link copied to clipboard
public abstract class Tuple implements Iterable<T>, Serializable
Abstract base for tuple classes.