Bruno Pedro

Event-driven Feature Development

Sharing information between different features can be done in a synchronous or asynchronous fashion. Following an asynchronous communication style doesn’t mean that you’re sharing events. You can, for instance, pass commands between features. By doing so, you’re creating a strong functional dependency between features. To avoid that, you should instead share information about things that happened, or events. By sharing events, you create opportunities for other features to become more relevant to users while acting independently.

Differences between synchronous and asynchronous information sharing

There are multiple ways to share information between different features. You can, for instance, create an API for each one of the features and then call those APIs from any other features that you want to share information from. You can have a centralized dispatcher responsible for sharing information with all the features whenever it receives a request. You can also have all the features share relevant information about their events, and any other features can then consume that information if it’s relevant to them. While the first two approaches are mostly used synchronously, the last one is the ideal candidate to become an asynchronous solution to event sharing across features.

Two synchronous approaches to event sharing

The challenge with both synchronous approaches is that you end up creating strong dependencies between features. What I mean by synchronous is that feature A (the information sender) will have to wait for feature D (the information receiver) to acknowledge and reply. If, for instance, you need to share information between feature A and feature D, you will create a strong dependency where feature A will wait until feature D acts on the information received and replies back. You will want to make sure that feature D replies to feature A through the dispatcher in the point-to-point style. The temptation is to make any of these two approaches asynchronous. By doing that, you remove the need for the sender to wait for a reply from the receiver. While that can be seen as an advantage, it doesn’t remove the dependency between both features. While the communication can be asynchronous, that doesn’t mean that the dependencies between those features are eliminated.

Is asynchronous communication event-driven?

The motivation to follow an asynchronous communication style is to remove the need for the sender to wait for a reply from the receiver. In a synchronous communication style, the sender has to wait for the receiver to act upon the information and reply. In practice, both sender and receiver will be in sync. If you can imagine a timeline, you would see feature A being started, then feature D being executed and completed, and finally feature A being completed. In other words, feature D is a part of feature A and cannot be dissociated. To make things more complicated, from a user perspective, there is no feature D. Feature D is hidden from the user as a part of feature A, so it wouldn’t feel natural for a user to wait for it to end. Following an asynchronous communication style seems to make the user experience much better because users wouldn’t have to wait for so long.

Differences between synchronous and asynchronous feature communication

However, to eliminate the functional dependency between the sender and the receiver, you need to understand the nature of the information being shared. Is feature A sending a command to feature D, or is it simply sharing information about something that happened? If feature A needs feature D to succeed, then the information being passed can be seen as a command, and you should consider a better design to eliminate the dependency. It would be best if you aimed at sharing information that doesn’t promote the dependency between features. Instead, the information you share should make it easier for features to behave independently. To make that happen, think about sharing information about things that already happened and that you believe can be interesting to other features. Information about those things that already happened, or events, can then be consumed by different features to enhance the user experience. The big difference between both approaches is that instead of having feature A pushing commands to feature D, you would have feature D—or any other feature—consuming events from feature A.

Asynchronous event sharing

The end goal is to share as many events as you can. By sharing events, you create opportunities for other features to become more relevant to users. Even if a particular event doesn’t feel interesting to you, there might be another feature that will benefit from it in the future. Doing this will foster an environment where different features can be reactive to events while acting independently.