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) { ... }
@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:- Tuple classes are for returning more than one message.
- 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().