Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
a state machine with an event already defined as a method #663
Consider the following source code
Umple will generate two methods with the same name.
if we are going to add (combine) generated code into the manual code (available in turnOff()) in order to satisfy state machine requirements, we must explore carefuly the order of this combination. The first option is to run first manual code and then the generated code for state machine, and the second one is the opposite. Furthemore, the effect of manual code on the condition of transition must also be explored.
So assuming that we do in fact want to combine the code (and probably issue a warning as well), we'll need to consider a few cases. As Vahdat said, the order of the combined code will matter. I think it makes the most sense to insert the Umple generated code after the user code, as inserting it at the beginning could cause unwanted modification of functionality to the user code. For example, if the user code depends on the state, we don't want the Umple state machine code to modify the state before executing user code.
The simplest, but naive solution would be to simply insert the generated code at the end of the user defined function and before the return statement. Of course, this will require consideration of functions with multiple return statements. For example, if the function contains a conditional block with a return statement in each, should the state machine code be inserted before each return? While this is the only way to ensure that the correct transitions are triggered before returning from the function, it could possibly result in an abundance of duplicated code, which is a poor code smell. A possible solution to this case would be to pull the generated code into a separate function, and call this function before each return statement. This could result in cleaner code.
Another case that we should take into account is what will happen if the user intends to handle the transition manually. If the user needs to do something fancy for a particular transition and doesn't want the Umple code to be generated, we may want to have some mechanism to signal this. In particular, perhaps the user creates a function with the same name on purpose with the intention of overriding the Umple generated code. In this case, we should not generate code for that transition at all. A mechanism for this could be investigated further if we want.
These solutions still depend on the user knowing what they're doing, and cannot guarantee against unforeseen behaviour in the function. As such, I think a warning should still be issued when dealing with this case.
I would appreciate any suggestions or input before moving forward with this. If I missed any cases, please do let me know.
Yes, currently it makes sense to have user-defined code first.
Yes. we need to have it for each branch. Having the generated code as a specific method is a good choice, but there should be a solution to guarantee the generated method is going to be unique. Furthermore, it can pollute the structure of the class (having so many methods)
It's an option, but we prefer to avoid this in order to keep everything simple and do all related checks by Umple compiler.
Yes, having a warning is a good idea to let user knows that we have merged them, but if we come with a good solution we won't need to have it.
@TimLethbridge can comment better in these cases.
Conceptually, as you say, having the user-defined code first, with the state transition added before any return or at the end.
The only catch is that the state transition code can be quite complex, so we really don't want multiple instances of it.
One solution would be to detect the clash and
b) If there are 'return' statements (found by scanning) not at the end of the user code, then raise a warning and ignore the user code (after all, the event code is supposed to return true if the event was 'used' and 'false' if it had no effect, so we don't want to override this expected behaviour).
c) If there is a return statement only at the end with an argument, then strip it before injecting as in point a, and raise a warning.
Of course if the method has a non-boolean return type, then this does not apply.
There may be other even better ideas, so lets discuss a little more if you have any