States

Posts   
 
    
BlueCell avatar
BlueCell
User
Posts: 83
Joined: 12-Jul-2004
# Posted on: 11-Oct-2004 16:45:39   

I often find the need for states when I am programming. For example, a state might be an edit state or a new state. I see states as something that can be enabled and disabled. When enabled, the state will produce some actions: For example, an edit state might enable the save button. When this edit state is disabled, this state will disable the save button again, making the save button only pressable when something is edited. When you edit one of the controls, the edit state will be set to true. One way to handle states, is to just code this in the eg. textchanged event. This event will set the save button's enabled property to true. When the save button is pressed, this event (clicked) will set the button's enabled property to false. Althought the wanted result can be achieved this way, I find this rather "ugly": many actions in many different events, not knowing if an action belongs to a state or something else. I have tried to solve this using a State Class:

VB .Net Code:


Public Class State
    Private m_Enable As Boolean = False

    Public Property Enable() As Boolean
        Get
            Return m_Enable
        End Get
        Set(ByVal Value As Boolean)
            ' If value is still in the same state, then exit
            If m_Enable = Value Then
                Exit Property
            Else
                m_Enable = Value
            End If
            ' State has change: raise the proper event
            If m_Enable = True Then
                RaiseEvent Enabled(Enable)
            Else
                RaiseEvent Disabled(Enable)
            End If
        End Set
    End Property

    Public Event Enabled(ByVal sender As Object)

    Public Event Disabled(ByVal sender As Object)

End Class

Example:


Private WithEvents editState As State = New State

    Private Sub editState_Enabled(ByVal sender As Object) Handles editState.Enabled
        ' Enable the Save Button: btnSave.Enabled = true
    End Sub

    Private Sub editState_Disabled(ByVal sender As Object) Handles editState.Disabled
        ' Disable the Save Button: btnSave.Enabled = false
    End Sub

Please give any feedback about above: Do you find this need to? Do you solve this in a different way? Do you think this is a bit of "over-enginering"? Etc...

Gr,

Michel van den Berg (aka BlueCell and Promontis)

jeffreygg
User
Posts: 805
Joined: 26-Oct-2003
# Posted on: 11-Oct-2004 20:03:36   

I think the definition of "over-engineered" is whether the infrastructure you build to solve a problem (in this case your "State" class) takes more time and energy to build and maintain than solving it "manually". So, the question back to you is, is it worth it?

That being said we do use something similar. However, we set the state by iterating over each control in the form and adding an eventhandler for the primary "changed" event each control has (Textbox = "TextChanged", ComboBox = "SelectedItemChanged", etc).

This isn't exactly accurate because a combo box being changed may not be changing an entity's data, but it works for now.

In the future, if we continue not using databinding, we'll pursue an attribute-based approach whereby a control can be "labelled" as to whether or not it's changes should trigger a dirty event.

The only reason why we're doing this is because we opted away from databinding. If we were using databinding then we would trap the underlying entities' <Property>Changed events or something similar, as opposed to tracking the controls' changes.

Jeff...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39826
Joined: 17-Aug-2003
# Posted on: 12-Oct-2004 09:08:22   

Don't see states as producers of actions. Your gui or application or object is in a certain 'State' and a separate interpretation routine makes the gui, application or object reflect the state it is in. When you pick such an approach, it is good to create a state transition diagram and a state machine. First you define the states, then you define the events triggering a state change. You then define tuples like 'state X + event Y = state Z'.

The great thing about this is that your application logic is very simple. All you have to do is write a generic state engine which moves the active state to a new state based on an event + active state, and you need a routine which reflects the state in the current application. Then in your logic you just have to fire events if something happens/should happen. So instead of 'enable the save button' when something changes in the editor, you fire the event 'something changed'. The state machine then moves to a different state and reflects that new state in the gui, which will enable the save button.

For small apps, this is overkill, as Jeff explains. For large applications with a lot of windows which interaction between the windows, it is hard to keep track of what to enable, disable which will create a truckload of logic which can easily be solved by a simple statemachine.

Frans Bouma | Lead developer LLBLGen Pro