Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Manage VB6 Code Complexity with the State Behavior Pattern : Page 2

VB6 can be prone to disorganization and the State behavior pattern is a consummate organizer. Use it proactively to prevent spaghetti code or reactively to manage code complexity.


advertisement
Delegate Form Behavior to a State Object
You can use the State behavior pattern with a context of any complexity, but I wouldn't necessarily employ it for every form. In fact, as a rule I wouldn't employ it for contexts with very low complexity. However, it is easier to demonstrate with a simple example and the implementation principle doesn't change as size increases.

 
Figure 1. Simple Customer Form

In this demo, a simple customer form accepts a name and an email address (see Figure 1). The form has two modes: edit and browse. In edit mode, you can modify the value of the controls and update and delete records. In browse mode, you can only view a record. The controls are all disabled. Typically, you might use a flag to manage mode, and all of the code would exist in the form itself. In this example, you delegate the behavior of the form to a state object.



As shown in Listing 1, the form refers to an instance of a class named BaseState. The BaseState object is an instance of either EditState or BrowseState. The precise behavior is dependent on the specific instance of a class that implements BaseState. All that the form has to do (only when the state changes) is determine which state the form is in and create that state object.

Listing 1: The Form's code is implemented in terms of a state object.
Option Explicit Private State As BaseState Public Property Get Customer() As Customer Dim c As Customer Set c = New Customer c.CompanyName = TextName.Text c.Email = TextEmail.Text Set Customer = c End Property Private Sub CommandDelete_Click() State.Delete End Sub Private Sub CommandUpdate_Click() State.SaveChanges End Sub Private Sub Form_Load() TextName.Text = "Paul Kimmel" TextEmail.Text = "pkimmel@softconcepts.com" Set State = New EditState Call State.Initialize(Me) End Sub Friend Property Get Email() As TextBox Set Email = TextEmail End Property Friend Property Get AName() As TextBox Set AName = TextName End Property

Listings 2, 3, and 4 show BaseState, EditState, and BrowseState, respectively.

Listing 2: The BaseState interface
Option Explicit Public Sub Initialize(ByVal Form As Form1) End Sub Public Sub SaveChanges() End Sub Public Sub Delete() End Sub Public Property Let AName(ByVal value As String) End Property Public Property Get AName() As String End Property Public Property Let Email(ByVal value As String) End Property Public Property Get Email() As String End Property

Listing 3: The EditState class implements BaseState and "turns" editing capability on.
Implements BaseState Private f As Form1 Private Sub BaseState_Delete() Debug.Assert f Is Nothing = False If (f Is Nothing) Then Return Dim c As Customer Set c = f.Customer Debug.Print "Customer: " & c.CompanyName & " deleted here" End Sub Private Property Get BaseState_Email() As String If (f Is Nothing = False) Then BaseState_Email = f.Email.Text Else BaseState_Email = "" End If End Property Private Property Let BaseState_Email(ByVal RHS As String) If (f Is Nothing = False) Then f.Email.Text = RHS End If End Property Private Sub BaseState_Initialize(ByVal Form As Form1) Set f = Form End Sub Private Property Let BaseState_AName(ByVal RHS As String) If (f Is Nothing = False) Then f.AName.Text = RHS End If End Property Private Property Get BaseState_AName() As String If (f Is Nothing = False) Then BaseState_AName = f.AName.Text Else BaseState_AName = "" End If End Property Private Sub BaseState_SaveChanges() Debug.Assert f Is Nothing = False If (f Is Nothing) Then Return Dim c As Customer Set c = f.Customer Debug.Print "Customer: " & c.CompanyName & " saved here" End Sub

Listing 4: The BrowseState class implements BaseState but "turns" editing capability off.
Implements BaseState Private f As Form1 Private Sub BaseState_Delete() End Sub Private Property Get BaseState_Email() As String If (f Is Nothing = False) Then BaseState_Email = f.Email.Text Else BaseState_Email = "" End If End Property Private Property Let BaseState_Email(ByVal RHS As String) End Property Private Sub BaseState_Initialize(ByVal Form As Form1) Set f = Form f.CommandSave.Enabled = False f.TextEmail.Enabled = False f.TextName.Enabled = False End Sub Private Property Let BaseState_AName(ByVal RHS As String) End Property Private Property Get BaseState_AName() As String If (f Is Nothing) Then BaseState_YourName = f.AName.Text End If End Property Private Sub BaseState_SaveChanges() End Sub

 
Figure 2. UML Visualization of Relationship Between the Form and State Classes

Because VB6 classes are interfaces, you have to implement every member of BaseState. You also have to do this because Form1 sends the same message regardless of state. However, it is the implementation of specific properties and methods, depending on state, that determines what happens. A useful feature of the State pattern is that you can change the behavior of the form by defining new states. (Figure 2 presents a UML visualization of the relationship between the Form and state classes.)

Bare in mind that .NET supports dynamic assembly loading. This ultimately means you can load state behavioral classes dynamically and can easily add new states without recompiling a deployed application by using a .config file to indicate which states are present or should be loaded and by deploying new state assemblies only. This level of extensibility is probably impossible if not very difficult in VB6.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap