Statemachines forcing your hand even if you are admin
No edit summary
m ((username removed) (log details removed))
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
A Statemachine as defined in MDriven is great way to keep the dynamics of an object in order. You set guards and transitions to really enforce your business rules. Once you start to use them you see how your if/then/else code sort of melts away.
A Statemachine, as defined in MDriven, is a great way to keep the dynamics of an object in order. Set guards and transitions to enforce your business rules. Once you start to use them, you see how your if/then/else code sort of melts away.


You cannot break the rules of the statemachine - even if you are the developer.
You cannot break the rules of the Statemachine - even if you are the developer.
[[File:Statemachines -1.png|none|frame|289x289px]]
[[File:Statemachines -1.png|none|frame|289x289px]]


So going from State1 straight to State3 without passing State2 is not possible. Not possible thru the framework that is. You can always update the state attribute in the database.
Going from State1 straight to State3 without passing State2 is impossible - through the framework, that is. You can always update the state attribute in the database.


And this rounding the framework thru the database '''has been fine up until now'''.
This rounding of the framework through the database '''has been acceptable until now'''.


As we introduced the Slave and HistorySlave MDrivenServer-configurations we really do not want to mess with the database from outside the framework. Since if we do the change will not be recorded in the MDrivenServerSynk table – and thus it will not propagate to the slaves and it will not be recorded with a timestamp in the HistorySlave.
As we introduced the Slave and HistorySlave MDrivenServer-configurations, we do not want to mess with the database from outside the framework. If we do the change, it will not be recorded in the MDrivenServerSynk table – and thus, it will not propagate to the slaves and will not be recorded with a timestamp in the HistorySlave.


But still you will get into situation where you have not interpreted the business correct so that you find that you need to fix something by twitching the statemachines in the production environment.
Still, you will get into a situation where you have not interpreted the business correctly such that you need to fix something by twitching the Statemachines in the production environment.


Earlier today a user asked me why she could not revive a thing that had been accidently set to Discarded:
Earlier today, a user asked me why she could not revive a thing that had been accidentally set to Discarded:
[[File:Statemachines -2.png|none|frame|372x372px]]
[[File:Statemachines -2.png|none|frame|372x372px]]


Well I did not have a good answer – so I said donowillfix. So adding the transition took 2 seconds. But the next planned release is 2 weeks away – she needs it Monday… I could do an “out of plan release” – but I want to release evenings to avoid production disturbance – and I am taking the family skiing over the weekend… You know – the usual excuses – the usual life.
I did not have a good answer – so I said: donowillfix. Adding the transition took 2 seconds, but the next planned release is 2 weeks away – she needs it Monday. I could do an “out-of-plan release” – but I want to release in the evenings to avoid production disturbance.


Things like this will happen in the future as well.
Things like this will happen in the future as well.


The solution I decided upon is to introduce an elevation – to allow you the developer to bypass the rules of the statemachines.
The solution I decided upon is to introduce an elevation – to allow the developer to bypass the rules of the Statemachines.


This is how:
This is how to do it:
  self.stateMachineForceMode('State');
  self.stateMachineForceMode('State');
  self.State:='State3'
  self.State:='State3'
The new operation stateMachineForceMode(nameofstateattribute) can be called just before attacking the state attribute just as if it had been a normal attribute.
The new operation <code>stateMachineForceMode(nameofstateattribute)</code> can be called just before attacking the state attribute just as if it had been a normal attribute.


The stateMachineForceMode is only good for 1 write so this will fail on the 3 line:
The stateMachineForceMode is only good for 1 write so this will fail on the 3 line:
Line 32: Line 32:
But this will work:<blockquote>self.stateMachineForceMode('State');</blockquote><blockquote>self.State:='State3';</blockquote><blockquote>self.stateMachineForceMode('State');</blockquote><blockquote>self.State:='State3'</blockquote>
But this will work:<blockquote>self.stateMachineForceMode('State');</blockquote><blockquote>self.State:='State3';</blockquote><blockquote>self.stateMachineForceMode('State');</blockquote><blockquote>self.State:='State3'</blockquote>


This is how to force state from code
This is how to force the state from code:


         public void StateMachineForce(string NewState)
         public void StateMachineForce(string NewState)
Line 53: Line 53:
                     break;
                     break;
             }
             }
[[Category:OCL]]
[[Category:Model]]

Latest revision as of 05:40, 17 January 2024

A Statemachine, as defined in MDriven, is a great way to keep the dynamics of an object in order. Set guards and transitions to enforce your business rules. Once you start to use them, you see how your if/then/else code sort of melts away.

You cannot break the rules of the Statemachine - even if you are the developer.

Statemachines -1.png

Going from State1 straight to State3 without passing State2 is impossible - through the framework, that is. You can always update the state attribute in the database.

This rounding of the framework through the database has been acceptable until now.

As we introduced the Slave and HistorySlave MDrivenServer-configurations, we do not want to mess with the database from outside the framework. If we do the change, it will not be recorded in the MDrivenServerSynk table – and thus, it will not propagate to the slaves and will not be recorded with a timestamp in the HistorySlave.

Still, you will get into a situation where you have not interpreted the business correctly – such that you need to fix something by twitching the Statemachines in the production environment.

Earlier today, a user asked me why she could not revive a thing that had been accidentally set to Discarded:

Statemachines -2.png

I did not have a good answer – so I said: donowillfix. Adding the transition took 2 seconds, but the next planned release is 2 weeks away – she needs it Monday. I could do an “out-of-plan release” – but I want to release in the evenings to avoid production disturbance.

Things like this will happen in the future as well.

The solution I decided upon is to introduce an elevation – to allow the developer to bypass the rules of the Statemachines.

This is how to do it:

self.stateMachineForceMode('State');
self.State:='State3'

The new operation stateMachineForceMode(nameofstateattribute) can be called just before attacking the state attribute just as if it had been a normal attribute.

The stateMachineForceMode is only good for 1 write so this will fail on the 3 line:

self.stateMachineForceMode('State');
self.State:='State3';
self.State:='State3'

But this will work:

self.stateMachineForceMode('State');

self.State:='State3';

self.stateMachineForceMode('State');

self.State:='State3'

This is how to force the state from code:

       public void StateMachineForce(string NewState)
       {
           string ForceMode = "self.stateMachineForceMode('TheStateAttribute')";
           string close = "self.TheStateAttribute :='close'";
           string open =  "self.TheStateAttribute='open'";
           Eco.Handles.DefaultEcoSpace es = this.AsIObject().ServiceProvider().GetEcoService<IEcoSpaceService>() as Eco.Handles.DefaultEcoSpace;
           switch (NewState)
           {
               case "close":
                   es.ActionLanguage.Execute(this, ForceMode);
                   es.ActionLanguage.Execute(this, close);
                   break;
               case "open":
                   es.ActionLanguage.Execute(this, ForceMode);
                   es.ActionLanguage.Execute(this, open);
                   break;
               default:
                   break;
           }
This page was edited 122 days ago on 01/17/2024. What links here