When your software system communicates with external systems or devices, there is good reason to isolate all communication with the external system into a single place and perform the relevant translation there. I call this pattern The Gateway Interchange Context.
It’s an independent piece of software that sits conceptually at the edge of your architecture and mediates communication between agents outside the architecture and those within it.
Gateway signifies that it’s a specific channel which enables communication and interchange signifies that there is some translation of language between the two systems.
An Example Gateway Interchange Context
Consider a software system for remotely managing and monitoring devices. Those devices could be cars, motorbikes, boats, drones, and other devices which move around.
Internally, the system has many bounded contexts, including:
- Location: tracking the current and historical location of each device
- Geofencing: ability to receive notifications when a device is outside a specified geofence
- Component Monitoring: ability to monitor the health of components of the device like it’s engine, ECU, and so on
- Remote Diagnostics: ability to remotely fix problems
- Device Configurator: remotely configuring and changing configuration (e.g. engine mode)
Ideally, each context would be an Open Host. It would have a single HTTP and/or MQTT endpoint which all devices sent messages to in a standard protocol.
However, Open Host is not alway possible. Many of the devices may have their custom protocol for optimising network usage (and other reasons) by bundling a variety of messages into a single payload .
Rather than having the details of each custom protocol leak into every context (Location, Geofencing, Remote Diagnostics, etc) a Gateway Interchange Context can be used to receive all incoming messages from devices, convert them into a standard format and route them to the contexts which own that data.
Anatomy of a Gateway Interchange Context
The Gateway Interchange Context is by no means a new concept. In fact, it’s a combination of three patterns which were first presented in Enterprise Integration Patterns over a decade ago.
The first element of the GIC is a translator. It receives commands or events from outside the system in one protocol and translates them into another protocol. For example, it could convert a custom UDP protocol into a JSON structure.
Secondly, the GIC is a splitter. It splits the incoming message into multiple smaller messages which are logically decoupled — e.g. location and monitoring data.
Lastly, the GIC is a content based router. It then sends each of the messages as a command to the context which owns that data.
Why is this a command? Each of the split messages represents a piece of data that is owned by a single context. If a context like Geofencing needs location data, it should listen to events from the Location service and not receive the data directly from the GIC.
Gateway Interchange Context Trade-offs
Coupling and cohesion are the key factors in many design decisions, and the Gateway Interchange Context represents an explicit coupling trade-off.
When a message format changes, e.g. a new piece of location data is added to the message format, now two parts of our system need to be modified. The GIC needs to parse, split, and route this new piece of information, and the Location Context needs to receive and use it.
We can avoid having to make two changes in two different contexts by simply allowing all contexts to do the translation themselves. E.g. the Location Context would receive a copy of the untranslated external message and pick out the location data it cares about.
In my opinion, having the custom protocol (or many custom protocol) translations scattered throughout many of the contexts in a system increases the overall complexity requiring many teams to know about the translation details.
If the custom protocol has a major change, then many contexts would need to be changed. This would not be the case if the translation was contained within the GIC. Equally, if a new device is introduced with a new protocol, it would require a change to many contexts, rather than the addition of a single new GIC which translates to the internal protocol.
The GIC is also risky in that business rules could start to creep in. It’s essential that the GIC does the minimum amount of translation.