There are numerous ways to connect the pieces of your software, regardless if it’s front- or back-end, microservices or event-driven programming. This developmental approach is riding the waves nowadays, but it’s been around for a while. However, many developers misunderstand the paradigm or use it for the wrong reasons.
Event-driven architecture is an old software approach that uses creation, propagation, detection and handling of events.
The simplest example is right in front of you – your browser. Upon clicking on a button, an event occurs – “I clicked,” which is a notification you acted. Then, other parts of the system can trigger “handling” the event (thus the name “event handlers”). That’s how you get to the next page.
Vue.js decided to use it for its parent-child components communication, and here’s why I believe that was a fantastic idea!
It’s native to the browser
Vue builds upon this native system and adds a few goodies:
One of the best things about Vue is that it unifies the browser implementation of that event system, so you don’t need to care about differences.
Both Vue and Angular build apps using event-driven programming for child-to-parent component communication. React, on the opposite, passes properties down the chain and lets children components call the methods directly.
When using events, different pieces of the code have different roles. “Producers” are the entities that produce the events (ex: a button). Consumers are the ones that “handle” the events, running some logic (e.g. log to the console).
In our previous example, the button is the producer, and the parent component is the consumer that logs the event.
The event-driven architecture allows you to have loosely coupled components – the button doesn’t know anything about the parent.
”Decoupled” often means that if we change one piece of our code, there is no change required elsewhere (or as less as possible).
This approach increases flexibility, ease of refactoring, and component swapping. The alternative is passing parent-specific details (methods) to its children. In case of code change, you cannot simply swap a component that does the same, but instead of `loadUsers,` have the `requestUsers` method.
Easier flow synchronisation
Often when an event occurs, it leads to an entire flow of actions. If you’re adding a new Person to the platform, in terms of UI components, the system might:
- handle role selection (dropdown item)
- close the dropdown (dropdown)
- validate selection (parent of dropdown)
- initiate back-end request (parent)
The chain of components might look like `Add Person Form` → `Person Role Section` → `Person Role Dropdown` → `Dropdown Option`. Clicking on the latter must trigger actions that lead to something happening on the `Add Person Form.`
Events would allow us to decouple the “links” between components. If the root one waits for the “user role is selected” event, then regardless of where the event comes from, it can initiate the back-end request.
The sweet thing here is that many “handlers” can be attached to the same event. We can also include “add a spinner” functionality to the previous example. The component (and its logic) doesn’t have to be anywhere in this chain of components – it can be separated entirely.
We can know, manipulate and synchronise the current state from within any system point.
Drawbacks of event-driven programming
We must be honest with each other – event-driven programming is no silver bullet. As with every other approach, it also comes with its drawbacks.
Event-driven programming might become complex
Managing and synchronising states across the system is powerful but also more challenging and complex. It requires team members to feel comfortable using it.
It might be prone to errors
Since we rely on events (typically described by their name), we might stumble upon collisions or errors. There’s a massive difference between `click` and `clicked,` even though they feel the same. One will work, and the other – will silently do nothing.
Calling non-existing methods from the parent will trigger an error, but events don’t require listeners (or handlers). They happen and do not know if anyone would care to act.
Happily, Vue.js provides a very descriptive mechanism to validate your events:
It’s not centralised
The most significant benefit might be the biggest drawback. The flow of actions is not centralised, and it’s like a flowing river. Events can occur everywhere, and handlers might be spread as well.
As with any other programming approach – use event-driven programming only when appropriate. It’s neither magic nor rocket science, but it’s fantastic for UI development, as it lets you create way more advanced and easy-to-test solutions.