
An interesting post, make sure this information is included in the tutorial/introduction in the documentation. Robert Ramey Christophe Henry wrote:
Hi Phil,
switch ((state<<8) | event) { case (Stopped<<8)|play: start_playback(); state=Playing; break; case (Stopped<<8)|open_close: open_drawer(); state=Open; break; etc. etc.
The greatest advantage of this ad-hoc style is that it is readable by anyone who has even the most basic understanding of C++ without the need to learn a new library, and its exact behaviour is immediately evident. It is also likely to compile and run quickly.
I have no doubt that MSM has many benefits compared to this. Perhaps it would be useful to spell them out?
The question is of course slighty provocative but still valid. The answer will be quite long, sorry about that.
I won't say that your solution is not good. Actually if someone is happy with such a solution, great for him. If you check the review from Franz Alt, you'll see the source code generated by Rhapsody, which is not very different from this one, the O(1) double-dispatch excluded. And it's at least way better than non-formal state machines which I happen to see in production code again and again. A state machine library, including MSM, is made for people who are not happy with such an approach. I wrote MSM out of sheer frustration with Statechart's inability to provide me with what I was looking for, and out of admiration for the solution presented in the MPL book. I only hoped that others felt like me and would like an alternative. Concretely, what I was looking for: - a descriptive, expressive and declarative state machine syntax. - most of UML features which are hard to code with a switch/case dispatch. - a library with the explicit goal of supporting a Model-Driven-Development process - enough speed so that it'd be hard to reject a state machine simply on speed grounds (usual excuse).
Next, you wil ask me what UML features I deem so important that it justifies a library. My personal favorites (order by what I use most): - events containing data. In your case, you are more or less forced to choose between the O(1) (which you did) and forgo event data or the O(n) (chosen by Rhapsody) at a speed cost. Metaprogramming techniques allow us a O(1) with event data. - actions/guards. Luckily, they are easy to implement in a switch/case. - orthogonal regions. I often use them for error handling and they greatly make the machine more readable by reducing the number of transitions. Also hard to get with a switch/case. - submachines (makes the code cleaner). Implementing them inside a switch case is simply horrible. Soon, you need to hide them in subclasses so we are already going in the direction of a library. - flags. Will make the calling code easier - exit points. Not my favorite, but always needed. Will quickly make your switch/case implementation hard to follow. - anonymous events. Hard to write with a switch/case dispatch. Luckily for your case, not everybody likes them. - history. Easy to implement in a switch/case (as long as you don't need them event-dependent) but doesn't make your code any more readable
Of course, like always, developers use only 20% of all UML features. But it's never the same 20%, so what you need depends on your "coding" style. And if you want to implement all these features in a switch/case, your code will quickly become terrible. You'll have to issue guidelines on how to implement them, each developper will have to redo the same again and again with the corresponding flow of bugs (what if I forget a "break"? Uh oh) and low productivity (not even talking about documentation).
Do we agree that this proves the need of a library?
The next valid question would be, why MSM? It doesn't have to. If you're happy with Statechart or another library and don't need the speed, it's really ok for me, I promise ;-) MSM is for people who, like me, want a declarative syntax. People who want to have a look at the transition table and see the whole structure of a machine. Not as clearly as on a diagram but better than just code. That's why there is a transition table, and that's why there is eUML, to make it even clearer. This will greatly help us developers communicate with domain experts who will not understand code, but quite fast understand a state machine (I tried an it works).
The second reason is the descriptive syntax of MSM. I wanted a library which would help a Model-Driven-Development. I wanted a library allowing us to switch from a graphical model to code and code to model. And I wanted the mapping to be complete. The goal would be to, at some point, never have to edit the code. I don't know how far I'll push it but you can be sure that I will push it as far as I can. This is where the functors added in eUML and the reusable states will help.
I hope I managed to answer your question.
Christophe _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost