Starbucks-fueled Developer

Monday, October 03, 2005

UPDATE: DECORATing Web Controls

OK, so if it wasn't apparent in the original post, I'll confess now: it wasn't TDD'd...While I don't have the time, at least right now, to complete it with unit tests and all, I'll at least revisit it and show how it can be improved upon.

One immediate flaw with the existing code is that the PersonBuilder class relies on an implementation of IControlLocator. While this might not appear to be that big of an issue since, after all, it is a web application, the design can be improved upon by extracting the interaction between the PersonBuilder and DataGridItemControlLocator classes:

Public Interface IControlLocator
Function FindControl(controlId as String) as Control
End Interface

Public Interface IPersonDataRetriever
Function GetName() As String
Function GetAge() As Integer
End Interface

Public Class DataGridPersonDataRetriever
Implements IPersonDataRetriever

Private _dgiControlLocator as IControlLocator

Public Sub New(locator as IControlLocator)
If IsNothing(locator) Then Throw New ArgumentNullException("locator")
_dgiControlLocator = locator
End Sub

Public Function GetName() As String Implements IPersonDataRetriever.GetName()
return FindTextBox("NameField").Text
End Function

Public Function GetAge() As Integer Implements IPersonDataRetriever.GetAge()
Return Integer.Parse(FindTextBox("AgeField")).Text
End Function

Private Function FindTextBox(controlId as String) As TextBox
Retrun DirectCast(_dgiControlLocator.FindControl(controlId), TextBox)
End Function
End Class

Public Class DataGridItemControlLocator
Implements IControlLocator

private dgItem as DataGridItem
private controlPrefix as String = ""

Public Sub New(dgi as DataGridItem)
If IsNothing(dgi) Then Throw New AgrumentNullException("dgi")
dgItem = dgi
End Sub

Public Sub New(dgi as DataGridItem, prefix as String)
If IsNothing(prefix) OrElse String.Empty.Equals(prefix.Trim()) Then Throw New ArgumentNullException("prefix")
controlPrefix = prefix.Trim()
End Sub

Public Function FindControl(controlId as String)as Control Implements IControlLocator.FindControl
Return dgItem.FindControl(prefix + controlId)
End Function

End Class

Public Class PersonBuilder

Protected personData as IPersonDataRetriever

Public Sub New(aPersonData as IPersonDataRetriever
If IsNothing(aPersonData) Then Throw New ArgumentNullException("aPersonData")
personData = aPersonData
End Sub

Public Function MakePerson() as Person
dim thePerson as Person = New Person()
thePerson.Name = personData.GetName()
thePerson.Age = personData.GetAge()

Return thePerson
End Function

End Class

Some might not like this as it makes the code for creating the PersonBuilder more complex:

Private Sub PersonDataGrid_ItemCommand(s as object, e as DataGridEventArgs)

Dim thePerson as Person '//or Load the Person object

Select Case e.CommandName.ToLower().Trim()
Case "update"
thePerson = New PersonBuilder(New DataGridPersonDataRetriever(New DataGridItemControlLocator(e.Item, "Edit"))).MakePerson()

case "insert"
thePerson = New PersonBuilder(New DataGridPersonDataRetriever(New DataGridItemControlLocator(e.Item, "New"))).MakePerson()
end select

'//other possible logic removed
End Sub

However, if you ask me, I feel the resulting design separates the concerns from the classes in a much better fashion then the original code. The PersonBuilder class is no longer "coupled" to the IControlLocator interface, which allows the BUILDER to be used in a WinForms environment, should the app need to include rich-client support in the future.

I'm not sure, as I'm no GoF patterns expert, but this seems as close to a Model-View-Controller design as one might be able to achieve when implementing in-place-editing with the various Data-controls that are available as-of Framework 1.1.

I'd love to hear any one's thoughts!

A Simple "Thank You"

Sometimes, that's all we need to get through a rough day...

My bride and I are into the home stretch of the whole wedding fiasco and, needless to say, the next 12 days are going to be hectic - at a minimum. So..with that, tensions are high, and I'll cut you the details and say that I wasn't in the best of moods leaving this evening.

On my way home though, a stranger made me feel good about myself - something that hasn't really happened to me in a good while. My state's department of transportation has made this new and intelligent move to see that all major road work and construction occur in the evening to help mitigate against construction related accidents, lower traffic congestion, etc.

Personally, I don't get this. I mean, I get it. And I appreciate the attempt. However, my experience has been that it's more of a pain than it is a real help. Road signs, even my ripe ol' age of mid-20-something, are difficult to read at night, whether or not you're familiar with the area. One evening, traffic was diverted across the median at an intersection and at the next, there weren't ample indications to get you back on the proper side of the road. I found this out because the guy in front of me split the concrete median with his vehicle, as sparks flew from the under-carage rubbed against the median. It's just a recipe for disaster if you ask me.

Well, tonight, in my attempts to just slow down and appreciate life, decided to take it extra slow through that dreaded construction zone. Not too many people apparently do that these days. At one point, there was a lot of activity going on in lane next to me; so much, that I pretty much came to a stand-still just to be safe. The flagman said "Thank you" as I passed him. For whatever reason, that simple "Thank You" meant a lot to me. I'm sure it meant it a lot to him...