Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a state machine with an event already defined as a method #663

Open
vahdat-ab opened this Issue Dec 3, 2015 · 6 comments

Comments

Projects
None yet
3 participants
@vahdat-ab
Copy link
Member

commented Dec 3, 2015

Consider the following source code

class A{
    isA ActiveDevice;
    public boolean turnOff(){
        return false;
    }
}

trait ActiveDevice{
    status{
        on{
            turnOff -> off;
        }
        off{
            turnOn -> on;
        }
    }
}

Umple will generate two methods with the same name.
There should be a mechanism to deal with these cases.
At least a warning can be useful.However, if we can deal with this case in a way we get benefits of both even and method, it will be great.

@vahdat-ab

This comment has been minimized.

Copy link
Member Author

commented Dec 3, 2015

we can also consider the following example:

class A{
    boolean turnOff(){
        return false;
    }
   status{
        on{
            turnOff -> off;
        }
        off{
            turnOn -> on;
        }
    }
}
@vahdat-ab

This comment has been minimized.

Copy link
Member Author

commented Jan 28, 2016

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.

@mkmicik mkmicik self-assigned this Feb 21, 2016

@mkmicik

This comment has been minimized.

Copy link
Contributor

commented Feb 21, 2016

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.

@vahdat-ab

This comment has been minimized.

Copy link
Member Author

commented Feb 23, 2016

Yes, currently it makes sense to have user-defined code first.

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?

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)
We have discussed subjects close to this in issue # 710. You may get some thoughts.

we may want to have some mechanism to signal this.

It's an option, but we prefer to avoid this in order to keep everything simple and do all related checks by Umple compiler.

As such, I think a warning should still be issued when dealing with this case.

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.

@TimLethbridge

This comment has been minimized.

Copy link
Member

commented Feb 23, 2016

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
a) If there is no return statement, in the the user defined code, treat it as if it was a
before turnOff { ... code ... }.
And use the existing mechanisms to inject, and don't issue a warning (as that would cause clutter).

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

@TimLethbridge

This comment has been minimized.

Copy link
Member

commented Sep 12, 2018

See also #1351

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.