
Hi Michael,
I personally find this library both useful and well implemented for many of my needs. The documentation is lacking and must be extended to include a library reference. Additionally, I would like to see SimpleStates implemented to support internal transitions as called out in the standard. Other issues are detailed; however, do not affect my qualified vote of "acceptance". My conditional recommendation for acceptance (yes vote) is based on resolving the documentation issues and lack of SimpleState internal transitions.
Thank you for the detailed review. Your UML experience is very valuable and appreciated. I'd like to discuss a few points. I've been thinking about internal transitions. I see 2 ways to implement them: - an UML-conform way where states have their own stt with reduced rows (no target) - a row in the state machine stt (also without target) which I wanted to implement anyway. The first has the advantage of being UML-conform and thus respecting the UML priority in case of conflicts (internal transitions having the highest). It also makes the state more valuable and maybe reusable. The second is more general than the UML-conform way as it allows you to define yourself your priority according to the position of the transition in the stt. It will also compile faster and be slightly faster. You also see the conflict better in the stt. But you lose a reuse possibility. I understand why internal transitions have a higher priority in submachines (for exit points to work I suppose) but for simple states? That's why I personally tend to prefer solution 2 but I'm interested in your take about it.
I haven't thought too much about this, but it seems that the functor (Row) mechanism might be extended further to replace the various "arow" syntax completely.
It can do all what the "row" does, all in one. I would still prefer to keep the "row"s because they are so simple that they attract unexperienced users who are sometimes scared of seeing templated functors (I tried ;-) ). They are a good entry point into MSM.
I find myself missing choice points. Using "anonymous transitions" nearly allows the same semantic... but not quite.
For interest, what don't anonymous transitions allow? I scratched my head for a long time and all I found was for the case where you have multiple choice points. In this case, the path goes further only if at least one full path to another state is found (if I got it right). Is there another reason to have choice points?
I also miss not having a "any" or "*" trigger definition. In essence, if no transition match is found for the active trigger ... take this transition.
This one was left out because I found no easy way to do it. It'd probably involve adding behind the hood a row for every event of a machine. It's harder to know how many rows are needed then. Besides, I never found a use case for this, so if you have one, I'm quite interested.
Additionally, an example of converting a runtime int to a type is in order. Most people doing statemachine work are acting on some trigger that now needs to be translated to a data type. There are many ways to slice this but none are listed.
I unfortunately found not many ways and almost all are pretty bad. One would be an ugly switch/case, the other guards (forcing a O(n) dispatch). Probably the best is letting the action generate internally another event. I will look for a way to solve this better.
As an aside, I would be happy to review and offer feedback with documentation modifications. I may be able to offer some assistance with modifications also.
With pleasure! As you see, I already started ;-)
Inconsistent use of eUML. Sometimes it is EUML (particularly at the start of a sentence.) I believe it should always be eUML.
Being not a native speaker, I followed what Word told me and it was probably a bad idea so I'll trust you on this.
While the implementation of deferred events is correct according to UML I have found that the ROOM concept is extremely useful and have implemented it in my own libraries. You may want want to consider it as a feature to MSM
I admit I don't completely get it but it surely sounds interesting. Would you have some written document or spec about it?
Without a deep history concept in MSM I am required to specify a history policy for each contained sub-state machine (composite state). I do find this rather annoying though it is workable.
I find rather annoying the UML way. At least there should be a workable solution for orthogonal regions and deep history. Yes, MSM forces a policy but in exchange gives you much more power.
My initial reaction to flags is "composite states already supply this information". I can see that flags can provide multiple slices of meta state information and *might* be useful. I am in general leery of abstractions that obfuscate additional state information. From a diagram POV, that state information is missing. In my world this typically means that the granularity of machines is wrong
Flags are a generalization of IS_IN for some UML tools. Consider the following example: State1 fulfills some property (called P1). State3 fulfills a property P2. And State 2 fulfills P1+P2. Now, composite won't help you because there is no way to put State2 in 2 composites. So when checking in a guard for, say P1, you'll be left with if (IS_IN(State1) || IS_IN(State2)). I personally prefer is_flag_active<P1>(). In this case, there is probably nothing wrong with your hierarchy, it's simply the IS_IN concept which is not enough general.
I personally like this format for describing a row. I hate to suggest yet one more mechanism... but having "row" utilize a "none" would be nice.
Yes, that there is no "none" is a limitation of having function pointers in "row". Even having default value was making compilers unhappy. It was one of the reasons for having the "Row". OTOH function pointers really can be understood by everybody (I work a lot with ex-C developers).
I find my fence riding odd because I have always thought a DSEL like this would be the cat's meow. I think it might be the copious use of BOOST_TYPEOF is just hard on my eyes and getting used to the ordering of build_state. All of those instantiations of objects with the ().... it just looks messy to me.
I'm open to any suggestion. The only other way I see is to create an instance for each type used in the stt, but it's also not great. We could pack it in a macro, but it hardly qualifies as more beautiful. Could you try the new row grammar which I posted in the vault and tell me if it looks slightly better? (note: sorry, I still use == instead of =. This will be changed too).
eUML seems to be a non-starter for me and these platforms.
I've been wondering about this too. VC makes a much better job at eUML executable size (no size overhead), so it is possible and I hope g++ will catch back. Thanks for the very useful comments. Christophe
participants (1)
-
Christophe Henry