This is a general design question that I’m currently hung up on. It is causing a bit of a mental code block… I don’t want to continue with it like this if it is simply a common pitfall, but I’d like to continue if it’s accepted usage as the code is quite clean and decoupled (barring the cross-cutting messages).
I have a list-based publisher / subscriber pattern in code that I use to allow arbitrary sections of code to send messages that unknown subscribers can listen to. Fairly straightforward.
One of my current use cases for this pattern is to spin up a UI status indicator showing the user the application is busy. There is a message before work starts, a repeating message for progress, and a message for completion. It seems clean, the lower levels of code only publish messages and care not for listeners.
The starting message drives the UI initially; it shows a marquee progress bar in the status bar of the main form. The completion message hides this progress bar. Update messages are represented as text in a label.
Without realising at the time, I made the UI dependent on the order of these messages. The UI relies on the start and completion messages in order to reflect the UI correctly. The “statefulness” I refer to is on the subscriber side (the messages themselves do not retain any state).
Is this usage going against the pub / sub pattern? If so, is the issue the reliance on message order? If not, then good, I can carry on 🙂
In your example, the sequential coupling code smell may be coming from your subscriber knowing too much about the inner workings of the publisher (i.e. When one starts, the other starts).
You can reduce the coupling by reducing the information in the message or by having the subscriber not take advantage of the temporal sequences of the messages.
For example, have the subscriber execute the same routine for the begin and in progress messages, reducing the resolution of the message to “WORKING.” The UI subscriber can spawn the dialog if needed or update it if it already exists. It’s the UI subscriber’s job to manage the lifetime of the dialog box, not the application’s.
However, this small smell is probably not enough to start convoluting the messages between the application and the UI subscriber.
Alternatively, you could make your subscriber robust enough to Do The Right Thing regardless of the sequence of messages that are called. Start, start, process, end, process, start, etc. The subscriber’s responsibility should be managing the progress dialog box…to do the best it can no matter what crazy messages are coming from the application.