Messaging pattern with (statically) enforced order?

Rasmus Schultz - Dec 10 '18 - - Dev Community

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.

For example:

  • 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?

. . . . . . . . . . . . . . . . . .