I'm working on a multi-threaded program that interfaces with external USB/serial devices via user-space device drivers.
Early in the design stage, I made the decision to split the program into three components: A, B and C.
- Component A would possess full responsibility of communication with external devices (this is where the user-space device drivers would run). It would run on a dedicated thread.
- Component B would serve an API off of a TCP/IP socket to third-party clients that needed access to the external devices. This component would also run on a dedicated thread.
- Component C would provide a GUI for the user, allowing them to view and manipulate data from the external devices. Again, this would be on a dedicated thread.
So components B and C both require access to the external devices, which component A would provide.
I needed a way for the three components to interface with each other, and at the time I thought making the program event-driven would be appropriate. With this approach, components would emit an event and other components would handle those events. I always knew that some events would require responses, in the form of subsequent events. For example, if component C wanted to pull some data from the external device, to present to the user in the GUI, it would emit an event to request the data from component A, and component A would handle that event, and return the requested data in a subsequent event, which component C would be waiting for.
Since defining the above approach, I've realised that, in some cases, a component may require a specific response to a specific event. So building off of the example above, if component C and component B requested different data from component A, component C should be able to wait for the correct response event (that is, the response to the event emitted by component C).
So I'm considering implementing the ability for a component to wait for an event that is a direct response to the previously emitted event. I would do this via event IDs, where each event would carry an ID, and an optional response ID. The response ID would be the ID of the event that the current event is in response to.
But I feel like I'm on the wrong path. Is this really an appropriate use of event-driven design? Is it OK for events to serve as requests for data, and subsequent events as responses? Would you do it differently? If so, how?
I've just come across this video by Mark Richards, which seems to describe my approach with event IDs and response IDs (which he calls "correlation IDs"). So maybe I'm not on the wrong path - he seems to think using events for request/response is fine. Would still appreciate your thoughts.