Structured Fluent Interfaces

The last post showed how a fluent interface can be used to construct structured data. If data is seen as a tree, it can be described entirely in depth first fashion, some method calls descending in a branch, and some others going back to the parent node. When reading the code, however, it may become non-obvious which “descending” method call corresponds to a given “returning” method call.

Continue reading Structured Fluent Interfaces

Key-Value Type Correlation, Generic Version

In my previous post I explored how we can have the type of a map value be correlated with the type of its key.

We reached a design where a class contains a Level Three implementation, with Level One client code.This is all well and good, but in a real project this design will probably expand in two directions simultaneously:

  • Instances: we may need to copy-paste-modify the ConverterLibrary (that maps Pair<Class<F>,Class<T>> to Function<F,T>) class to create libraries of formatters (Class<T> to Parse<T>), parsers, CRUD services, etc. The keys need not be class objects: we can have prototype maps (T to T), maps associating List<T> to keys of type Supplier<T> (e.g. recording values previously returned by the supplier or inversely that the given supplier needs to return), etc.
  • Features: Clients may need methods like containsKey, remove, keySet, etc. This entails dangerously writing more Level Three code, potentially copy-pasting from one instance to another (previous point), potentially forgetting to update all parts of the code.

Continue reading Key-Value Type Correlation, Generic Version

Enforcing State Transitions

To access some service we are using a third-party library with an interface that looks like this:

public class Session {
    public void connect();
    public Answer ask(Question question);
    public void disconnect();

The contract specified in the documentation specifies that:

  1. The first method invoked on the object may only be connect.
  2. The connect method may be used only once on any given instance
  3. On an instance where connect() has been invoked successfully, you must eventually invoke disconnect
  4. No method may be invoked on an instance on which disconnect has been called.

Continue reading Enforcing State Transitions

Maps with Variable Value Types

About Maps and Generics

Since Java introduced Generics, Maps became a bit safer to use.

Before generics, this code would pass compilation without issues:

Map fruitColours = new HashMap();
fruitColours.put(Fruit.banana, "blue");
/* In a method somewhere else */
if (fruitColour.get("banana") == {
    throw new IllegalStateException("Alien blue bananas not supported");

Continue reading Maps with Variable Value Types

Parameter-Dependent Exceptions

Suppose you have a method in a class used to save some data in the database. The method has a parameter telling whether to perform business validation prior to saving. When that option is enabled the implementation will throw an exception in case the data is invalid, and when the option is not set it will save whatever it manages to save, never throwing an exception. The former case would be used when the data is published, and the latter case could be used for automatic draft saving for instance (drawing scenario inspiration from WordPress here).

Continue reading Parameter-Dependent Exceptions