Frankly, this isn't going as well as I hoped it would. I'm pretty happy with the naming convention that I ended up with, but the search and replace isn't going so well to this point.
I had estimated that 30% of the usage of the previous methods would be incorrect. But then I stated that was a pessimistic estimate. I don't have numbers, but so far it feels like we were wrong more often than we were right. What's kind of reassuring is that in most places where mistakes were made, 2 mistakes were made, and, well, 2 wrongs made a right. This allowed the application to work, even though the code wasn't what I would have wanted.
Here's what I mean by the 2 wrongs making a right:
1: txtSectionNumber.Text = Formatting.IsStringEmptyString(CourseSection("SectionNumber").ToString)
2:
3: ddlAdministrativeSchool.SelectedIndex = _
4: ddlAdministrativeSchool.Items.IndexOf( _
5: ddlAdministrativeSchool.Items.FindByValue( _
6: IsNullString(Trim(CType(ContentRow("AdministrativeSchoolId"), Guid).ToString))))
That code should have been (using the old methods):
1: txtSectionNumber.Text = Formatting.DisplayIsNullInteger(CourseSection("SectionNumber"))
2:
3: ddlAdministrativeSchool.SelectByGuid(IsNullGuid(ContentRow("AdministrativeSchoolId")))
On the section number line, it was following this path:
- Convert the database value to a string (wrong)
- Convert the string to a string (wrong)
In the case of a value being specified, it would be a numeric string. In the case of a DBNull, it would be an empty string. This worked. But here's what it should've done:
- Convert the database value to an integer, using a constant (Integer.MinValue) to represent DBNull
- Format that integer for display, which will replace the constant with an empty string
On the administrative school dropdown... well, yuck!! It was doing the following:
- Convert the database value to a Guid (would barf if it was null, wrong)
- Convert the Guid to a string
- Trim the string (because Guids often have padding coming out of the database!?, wrong)
- Ensure that string isn't DBNull (which is superfluous because that's impossible, wrong)
- Find the dropdown item having a value matching that string (should be finding it by Guid, wrong)
- Get the index of that dropdown item (why do it this way?, wrong)
- Set the selected index to that index (why do it this way?, wrong)
That's just all kinds of wrong. By some miracle, it worked though. Here's what it should've done:
- Convert the database value to a Guid, using Guid.Empty (the constant defined) to represent DBNull
- Select the dropdown item that has a value matching that Guid
Using the new nullable types classes (remember, I'm in .NET 1.1 here), here's what the code looks like:
1: txtSectionNumber.Text = NullableInt32.ForDisplay(CourseSection("SectionNumber"))
2:
3: ddlAdministrativeSchool.SelectByGuid(NullableGuid.From(ContentRow("AdministrativeSchoolId")))
A couple of sidebar notes:
- I did end up needing a separate method of ForDisplay. I was previously thinking that the From method would do all of the work, but that fell short of formatting for display. I had forgotten about the DisplayIsNull* methods. During the search and replace, I remembered that I'd need to be able to display values, replacing their magic numbers with empty strings. I originally implemented the ForDisplay method as ToString, but this felt like I was building a whole new IsStringEmpty method which would still be misused.
- I also have a ForDatabase method that will return DBNull.value when a value is null, ensuring that we don't pass a constant like Integer.MinValue into the database. The core of the data access layer calls into this when any parameter value is specified, so the developers never touch this method.
- Our dropdown control supports a method for SelectByGuid. We also have other methods similar to this, but since we use Guids ubiquitously, it is very helpful to have this method. Just one of the many reasons why I swear by Custom Controls Everywhere.
I have finished implementing the NullableString class throughout the application. I think I'll do the Guids next because I love Guids, and yesterday was Valentine's Day.