In an effort to downsize, we recently decided to put the house in Los Angeles on the market-it's our attempt to "cash out," and take advantage of the hot real estate market in SoCal. It's a wonderful house, at the top of a hill overlooking much of north-east Los Angeles, but it's huge, expensive, and worth a lot more than what we paid for it. Yes, I know you're really feeling sorry for me here. I'm totally ambivalent about the sale/move, and hope it's all resolved by the time you read this.

Figuring that selling and moving was going to be a terrible time suck, and because there's no real pressure forcing us to head down this path, we decided to be hard-nosed about the sale and accept no offers below the asking price, which we set at the top of the possible range. You know the drill-you look at all the other houses in the neighborhood that are for sale, decide that yours is nicer than all of those, and up the price a little. We contacted the agent that sold us the house seven years earlier-he's the top seller in the area-and signed the necessary papers.

Then, once we were hooked, the pain started. Brian (the agent) swept in one night, looked about the house, and regaled us with everything we must do in order to sell. We were told to remove every shred of personal content from the house, to paint the outside, clean the windows, fix the roof, fix up a few little leak-damaged spots on the walls, move plants around outside, hang a chandelier in the dining room, put away all computer technology, clean closets, pump and certify the septic system, and on and on. We were even given instructions on how to decorate (down to the big bowl of lemons on the dining room table?see Figure 1.)

Figure 1: Big bowl of lemons. It's amazing how fast lemons turn moldy. Now I know.

At one point, Brian and his helper started rearranging furniture in the living room, to give it a more "elegant" feel. Dust and cat hair were flying. Of course, we actually lived there, and used the space and never really gave much thought as to the feel. We just wanted to be able to plop down on the sofa and watch TiVo. At this point, the sofas may be arranged in a more elegant manner, but there's no place to sit and watch TV. What's a guy to do?

And it gets better. Because of the cats, we had never invested in plants, or nice fabrics, or, well, much decorating of any kind. Certainly there was neither a big bowl for lemons, nor a big bag of lemons, to be found on the premises. Accompanied by my friend Diane, who has a keen eye for design (and a beautiful self-decorated house), I headed out for the local Bed, Bath, and Beyond, Pier 1 Imports, and IKEA, picking out stuff we should have gotten seven years earlier, it appears. We bought throw pillows and candles and rugs and wall hangings and chenille throws (an item of whose existence I wasn't even faintly aware previously) and lots of plants, some real and some fake. And more, lots more. The damages? $2000 or so. I'm in pain, but the house is nice. With visions of the huge real estate windfall, we just bought whatever Diane suggested. (In case you care, what we really learned from this adventure is that $5 IKEA throw pillows will never look any better than exactly what they are: $5 IKEA throw pillows. You get what you pay for. Who did we think we were kidding?)

Now, we have a fully decorated, elegant and presentable house. In case you're interested, Figure 2 shows the results in just a single room. This "after" picture shows the guest bathroom, which before we started, had no soaps, no plants, no rug, no bath towels, no little basket with rolled up towels, and no cacti. Just a litter box or two, and a hand towel. Clearly, things are better now.

Figure 2: Look Ma, it's a real bathroom!

But are they? Is elegant always better? At this point, we can't use half of the rooms (they're closed off for showing) because the cats would eat the plants with inelegant biological results that we might not be able to clean up before perspective buyers came through, and we can't really even watch the TV in the living room because of all the throw pillows and the rearranged sofas. Sure, it may sell faster, but we can't really live in the model house as it is for long.

This situation reminds me of a coding problem that came up recently. My pal, Brian Randell, was trying to quickly rip out some code that could retrieve a URL from an Internet Explore favorite (*.FAV) file. These files contain information about your selected favorites, and contain data in old-fashioned INI format, like this:

[DEFAULT]
BASEURL=http://www.code-magazine.com/
[InternetShortcut]
URL=http://www.code-magazine.com/
Modified=30A88EE7CBBAC40197

Although the contents of this file aren't generally documented, Brian wanted to retrieve just the URL from the file, using Visual Basic .NET. He was in a rush, and asked if I had code lying about to parse INI files.

I had written a set of classes to handle this issue for VBA applications, but hadn't really ever had a need to handle the INI file format in managed code. I'm sure a quick search online would have turned up a similar set of managed classes, but since his only goal was to retrieve a value given a specified key, I figured that I could rip out some brute-force string handling code quicker than searching online.

Listing 1 shows the first pass at solving this string parsing problem. This code does its job by converting both the INI text (which Brian had already managed to load, using the System.IO namespace) and the key value to be located into upper case, and then using the IndexOf method to find the location of the string:

Dim startPos As Integer = _
 iniText.ToUpper.IndexOf(keyName.ToUpper())

If the sought item was found, the code attempts to find the end of the text line containing the item, searching for a CR/LF or the end of the text:

If startPos > 0 Then
  Dim textLine As String
  Dim endPos As Integer = iniText.IndexOf( _
   ControlChars.CrLf, startPos + 1)
  If endPos > 0 Then
    textLine = iniText.Substring( _
     startPos, endPos - startPos)
  Else
    textLine = iniText.Substring(startPos)
  End If
' code removed here.
End If

Finally, the code splits the found line at the "=", and trims the results to remove extra spaces:

Dim items() As String = _
   textLine.Split("=".ToCharArray)
  If items.Length > 1 Then
    returnValue = items(1).Trim()
  End If
End If
Return returnValue

Although this solution isn't elegant, it was quick to write and returned the required value. But it bothered me. As I was in the shower one morning, I was struck. "Isn't this a perfect scenario in which to use regular expressions?" I asked myself. Armed with the urge to make working code more elegant, I started again. This time, I did a quick bit of research into regular expressions in the System.Text.RegularExpression namespace. This feature provides a meta-language that makes it possible for developers to craft incredibly rich search and replace operations based on complex write-only (that's my thought, anyway-you try reading one of these and figuring out what its purpose is) text expressions.

Using a regular expression to find a key value at the beginning of a line followed by "=" is easy, as far as regular expressions go. If you want to learn more about regular expressions, start at this help topic: ms-help://MS.NETFrameworkSDKv1.1/cpguidenf/ html/cpconcomregularexpressions.htm; that's where I started. I crafted the following search expression to find the "URL =" text in the INI file, and to allow me to retrieve the text following the "=" on the line:

^URL\s*=\s*(?<1>.*)

Broken down into its parts, this expression tells my code to look for a string with the following characteristics:

  • Beginning of a line
  • The text URL
  • Zero or more white space characters
  • =
  • Zero or more white space characters
  • Zero or more characters of any kind, captured into a group that you can retrieve later, in code.

Listing 2 shows the revised GetIniValue procedure, this time using regular expressions to do its work. Obviously, explaining the code in detail is beyond the scope of what I can do here, but in "big strokes," the code takes the following actions, which assume that you've added an Imports statement for the System.Text.RegularExpressions namespace:

  • Use the String.Format method to create the correct search string:
' Build up the match string, replacing {0} with
' the key name to find.
Dim strMatch As String = _
 String.Format("^{0}\s*=\s*(?<1>.*)", keyName)

  • Create a new regular expression, using the search string and appropriate options:
Dim regex As New Regex(strMatch, _
 RegexOptions.Multiline Or
 RegexOptions.IgnoreCase)

  • Perform the search:
' Get match, if it's in there.
Dim match As Match = regex.Match(iniText)

  • Retrieve the group containing the results, and return the value:
Dim result As String
If Not match Is Nothing Then
   result = match.Groups(1).Value.Trim()
End If
Return result

Doesn't this code just ooze elegance? Could it get much cleaner than that? It has only one conditional statement and really not much code at all. I really thought I had the best solution.

Only one problem: Brian had originally "poo-poo'd" regular expressions, figuring they'd be slower. Guess what? They are. In some simple tests, running both versions a large number of times, the regular expression version takes around three times as long to run as the original version, on average. You could mitigate much of the overhead by caching the RegEx object in memory, rather than creating a new one each time (you would want to do this if you were performing this operation often), and you can get some speed improvement by compiling the regular expression. Even with these changes, the regular expression version took longer to execute.

What have I learned through this exercise? Clearly, the most elegant code doesn't always win. Sometimes, brute force is a better choice, both in terms of readability and in terms of performance. One could, I suppose, draw a parallel between the house and the code: the original version of the house was a lot easier to live in, just as the original version of the code performs better. I'm hoping the spiffed-up house helps us sell faster, but spiffing up the code, in this case, didn't help anyone very much.