I'm trying to devise an API for a set of messages/events that get passed in a streaming manner.
Specifically, I'm build a test-framework, and I want to separate the back-end listeners (such as XML reporter, console reporter, code coverage reporter, etc.) such that these implement an interface (or a set of interfaces) that enables the test-framework to send a fixed/known set of message types, which occur in a defined valid order.
- Begin Test Suite A
- Begin Test Case 1
- Log Assertion Result X
- Log Assertion Result Y
- End Test Case 1
- Begin Test Case 2
- Log Assertion Result Z
- End Test Case 2
- End Test Suite A
- Begin Test Suite B
In other words, there's an required order for these messages to make sense: A Test Case can't start before a Test Suite has been started, each Test Case much end before starting a new Test Case, Assertion Results must be logged while there's an active Test Case, and so on.
My first attempt was a set of interfaces, and my idea here was you wouldn't be able to start a Test Case until you've started a Test Suite, because that's how you get your Test Case listener, and you wouldn't be able to submit an Assertion Result until you've started a Test Case, and so on.
This approach only enforces one rule though, ensuring that you can't post a certain type of message before posting another given type of message - there's nothing that guarantees that client code doesn't just keep a reference to a previous Test Case, for example, and submit Assertion Results out of order. There's also nothing that guarantees you call the
end() methods to close a Test Suite or Case. So this doesn't really work.
The only alternative I've been able to think of, is a more traditional event stream - where each message type is an interface that extends a marker interface, and all of the messages are submitted via the same method to a bus that distributes the messages to the listeners.
This is probably easier to implement and understand, and avoids the issue with client code keeping a reference to a previous listener, since there's just one way to submit a message. I can write a standard implementation of such a listener that simply validates message order, and the framework can internally put an instance of this before the user-supplied list of listeners.
That might be simpler and cleaner, but you of course still submit messages in the wrong order - the message order still needs to be validated at run-time.
Is there any sort of messaging pattern that statically enforces message order?