Starbucks-fueled Developer

Monday, September 19, 2005

DECORATing Web Controls

In reading Jeremy's post on the DECORATOR pattern, I actually found another application of the pattern in my own code (gasp!). While I don't particularly enjoy working with in-place editing on the Data* web controls, I didn't have the choice this time. However, as you'll see, I turned my frown upside down by implementing this very useful pattern...

I'm sure you've written similar code (the mix of VB & C# comments is so it is clear, it's a comment):

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"
'//Find all the edit controls
thePerson.Name = DirectCast(e.Item.FindControl("EditNameField"), TextBox).Text
thePerson.Age = Integer.Parse(DirectCast(e.Item.FindControl("EditAgeField"), TextBox).Text
'//other controls obmitted

case "insert"
'//Find all the controls
thePerson.Name = DirectCast(e.Item.FindControl("NewNameField"), TextBox).Text
thePerson.Age = Integer.Parse(DirectCast(e.Item.FindControl("NewAgeField"), TextBox).Text)

'//other controls obmitted
end select

'//other possible logic removed

End Sub

Honestly, that's some ugly, mind-numbing code. Plus, while it might be hard to see at first, there's a good bit of duplication as well. Let's see how the DECORATOR pattern, in conjunction with another pattern, can brighten our day...

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

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 FindTextBox(controlId as String) as TextBox
Return DirectCast(FindControl(controlName), TextBox)
End Function

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

End Class

Public Class PersonBuilder

Protected controlLocator as IControlLocator

Public Sub New(aControlLocator as IControlLocator)
If IsNothing(aControlLocator) Then Throw New ArgumentNullException("aControlLocator")
controlLocator = aControlLocator
End Sub

Public Function MakePerson() as Person
dim thePerson as Person = New Person()
thePerson.Name = controlLocator.FindTextBox("NameField").Text
thePerson.Age = Integer.Parse(controlLocator.FindTextBox("AgeField").Text)

Return thePerson
End Function

End Class

Boy...that really simplifies the code in the ItemCommand event, doesn't it?

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 DataGridItemControlLocator(e.Item, "Edit")).MakePerson()

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

'//other possible logic removed
End Sub

Personally, I feel that's a ton better. The IControlLocator can be implemented for any ASP.NET control. Objects that implement that interface, like the DataGridItemControlLocator implementation, allow the duplication of the control names - and the corresponding type casts - to be removed from the ItemCommand event of the DataGrid. Finally, the PersonBuilder is my attempt at demonstrating the BUILDER pattern - one of many patterns that helps centralize complex object creation code. It might be a bit contrived, as you would not want to tightly couple it to a given UI framework as this implementation does.

I appreciate any comments, thoughts and suggestions anyone has to offer on this example.

Browser War 2.0: Security

I cam a cross this CNET article stating that Symantec found Mozilla-based browsers to the more vulnerable in comparison to IE. While it is important to have browsers that comply to web standards, I personally prefer a more secure product over one that offers more "bells and whistles". Don't get me wrong! I'm just as disappointed as everyone else with Microsoft's stance on not passing the Acid2 Test, but as I flop between Firefox and IE, the one to get installed and set as my default browser will be the one to offer me the best of both worlds - a secure, feature-rich, approaching compliance with Standards' web browsing experience.

If I could merge IE and Firefox I would. I use several features of Firefox that IE doesn't offer, like only loading images from originating web sites, better RSS and developer (web dev. toolbar) support, and tab-based browsing. But I can't run work intranet apps in Firefox because of ActiveX - and I have a great disdain for ActiveX...

Personally, I have some great ideas for a completely managed code web browser, but they'll most likely never come to fruition because of lack of resources. And there's that whole rendering bit and that Microsoft will mostly likely beat me to it...I'd be greatly surprised if IE7 wasn't largely written in C#. I mean, c'mon, BizTalk is WAY more complex than a web browser and even it is written in C#...

But I digress...

Sunday, September 04, 2005

"Can you do it in Excel?"

Ah the wisdom of a father...That's his [in]famous response to a recent customer when asked "hey, can you build a simple database with a few ASP pages to do XYZ?". His point is that anyone can make a database and tie a few ASP[X] pages to it. But does that time really give you an extra value or benefit for all that work when, quite possibly, a few sheets in an Excel Workbook can give you all the functionality you need? If you ask me, that's a rather Agile philosophy...Funny, he doesn't really "get" Agile development; then again, I haven't exactly mastered it myself - and I'm the one trying to "convert" him!

This is actually something that I'm struggling with in my personal life.

Our wedding is coming up - 40 days, as of Sept. 5. My bride has her moments of tech-savvyness and, generally, she's handled most of the computing-related wedding stuff extremely well. The guest list, directions to the location of the ceremony and reception, e-mails to service providers, everything managed on her USB key.

The downside to all this was that the guest list was, essentially, just a Word document of names - no addresses. Whenever the time came to send a mailing, she created a new document for printing labels and then added everyone manually with their addresses. Unfortunately, while this was, in fact, a pretty Agile way of approaching it (as we didn't have everyone's addresses when making the lists) it just made things more difficult in the end. What if you forget someone after printing out the labels and (for reasons still unknown to me) they need to be alphabetized?

Nigtmare. Enter the programmer, in place of the knight in shining armor.

I set up an Access database to manage the "contacts" and did a quick mail merge with Word. Project saved. However, there's a lot of functionality that's missing. For example, we have about 120 "families" on our guest list that we've divided into first and second round mailings. The list I imported into the database wasn't the complete list - it was only the "A" list. We just finished making the invitations for the "B" list this weekend and will be sending out that mailing within the next 10 days. However, as it stands right now, I'm only going to be able to produce a mail merge document of all the guests, not just the "B" list. Not to mention that we're getting responses back of who is and is not attending the wedding, which will make up our final list that we will need to provide the caterers. Did I mention thank you notes? Future mailing lists like Christmas cards?

Obviously, this knight hasn't completely rescued his damsel in distress.

Sadly, thinking about it now, "Can I do it in Excel?": most likely. Do I want to? Not particularly. I'm envisioning this wonderful web/thin/"smart"-client application that will solve all of our contact management hassles and work beautifully in our well connected, techie home. I've become my arch-nemesis: the demanding, unrealistic customer that wants the next "killer app" tomorrow and for free when, in all reality, there are existing tools that I'm already familiar and comfortable with that will get me what I need in the short term, while having the ability to build additional functionality when I absolutely need it.

But what developer, agile or otherwise, would actually, really approach it that way?! ;-)