Using APIs to specify a contract between server and client applications, or between different layers of an application, has become a standard practice in software development. We argue that it is as important to define contracts that specify how a user can interact with an application.
The interaction specification should ideally be event-based and semantic, independent of the UI (what we see and touch). In our snake game example from a previous story (State Subjects: Reactive Architectures with State Streaming), the interaction with the SnakeSubject is defined by a Scala trait:
sealed trait Event
case class Turn(direction: WorldLocation) extends Event
case class Eat() extends Event
case class Advance() extends Event
and the state that is published to subscribers on change is defined as a Scala case class:
case class Snake(body: List[WorldLocation], direction: WorldLocation)
Visually, the contract is represented in the diagram below:
Note that the model used internally by the subject or component (if any) may be different than the state that is published to subscribers.
It is also important to understand that the UI is different from the interaction specification. For example, the UI will allow interactions through the arrow keys (which represent message payloads for the Turn events/messages.) In fact, the interaction contract can be seen as the non-visual part of the UX, while the UI is visualizing the interaction contract.