I'm in the process of redesigning our entire process control system (a daunting task, really!), and want to make the right decisions to how each system in the ecosystem communicates with each other.
In particular, I want to control how systems trigger actions in separate systems.
Some background: In our current implementation, most actions are triggered through an event flag system. When System A wants to call Process 1 from System B, System A raises an event Event Foo in a shared memory section. System B sees Event Foo, knows to call Process 1, does so and continues on. Multiple systems can raise an event, multiple systems can consume an event, and a system can perform multiple actions from one event. What this results in is a complete lack of traceability; it is extremely to difficult to know when an event occurs, who consumed an event, and who raised the event.
Off the bat, I can think of a few improvements to our current system: in the metadata for an event, include the caller system name; keep track of receiver system names; write a logger for the event handling to keep track of timing, callers, and receivers. Additionally, instead of checking shared memory, I would use a managed interface with publishers and subscribers, which would allow me to keep track of all systems involved in an event. From here on out, I will refer to this as a "publish" architecture. This would make debugging easier and is most similar to what we have now, but is not really possible with the current system as it is a closed source, black box process.
But I can also think of an entirely separate way of handling this: have each caller make a direct request to the process it intends to affect. Using my initial example, when System A wants to call Process 1 from System B, System A pushes a request to System B with metadata stating the process and caller ID. To me, this has the advantage of being explicit code - any programmer looking at the call knows who the receiver is and what process is executed. Likewise, a code search for a process and receiver can find the corresponding caller, allowing for backwards traceability as well.
I can think of some pros and cons to each.
- With Pushing, code is more explicit. Receiving processes are directly visible.
- With Publishing, code is more implicit. Receivers/callers are not specified at the publish call, and processes can change without the caller knowing.
- With Pushing, code can become WET (repetitive). Multiple process calls would require multiple pushes. Multiple callers would require copying push commands to multiple places, possibly presenting maintenance concerns when the receiving processing changes.
- With Publishing, code is DRY (succinct). Multiple process calls can be achieved with a single publish. Changing receivers can occur without modifying callers.
- Pushing allows for synchronous operation. Pushes can occur and wait for a processes to complete before proceeding to the next operation.
- Publishing requires mostly asynchronous operation. Without knowing what processes are affected, execution order can't be controlled and would require additional framework to wait for completion.
To recap, I'm considering two options: a publish architecture where any number of callers publish events and and any number of receivers consume events, and a push architecture where a single caller directly interacts with a single receiver. Is one considerably better than the other, and when should I decide to use each?