<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Coding Practices and Design Patterns</title>
        <link>http://geekswithblogs.net/chrisfalter/category/4245.aspx</link>
        <description>To write good code, you need to have a good approach.  </description>
        <language>en-US</language>
        <copyright>Chris Falter</copyright>
        <managingEditor>chrisfalter@yahoo.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>How to Reuse Code Without Creating an Implicit API</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2009/03/29/how-to-reuse-code-without-creating-an-implicit-api.aspx</link>
            <description>&lt;p&gt;I work for an ISV, and we have to be very cautious about the code that we declare with public scope.  If it's public, a customer can treat it as an API, which might not always be a good idea if the code is really just doing some internal task in a way that could easily change as we improve our software.  In other words, not all that is public should be an API.&lt;/p&gt;
&lt;p&gt;So what do you do if you need to share code across assembly boundaries?  Recently I was writing some unit tests for a class, and the tests needed access to a class method in order to imitate (and test) its behavior.  Of course this method was private--&lt;em&gt;of course!&lt;/em&gt;--so it appeared that I had to choose between 2 very unpalatable options:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Give the method public scope, which would make it visible to all our customers' implementations.  Essentially, this option would make the method part of our API.  Not happening. &lt;/li&gt;
    &lt;li&gt;Copy the 20 lines of code from the method, paste it into my new class, and supplicate the dark spirits of bad software design to supernaturally prevent the method from ever being modified.  But how could I perform the ritual without an eye of newt and toe of frog?* &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But appearances can be deceiving.  It turns out that the &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx"&gt;InternalsVisibleToAttribute&lt;/a&gt;, introduced by Microsoft in .NET 2.0, solves the problem quite neatly.  Using this attribute, you can designate one or more friend assemblies that will be allowed access to classes, methods and properties in the target assembly that have friend scope, while all other code--including customer code--is denied access.&lt;/p&gt;
&lt;p&gt;Using the attribute is a piece of cake:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Mark any classes/methods/properties that need to be visible to other assemblies with "Friend" scope. &lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;Import the System.Runtime.CompilerServices namespace into your assembly's AssemblyInfo.vb file.&lt;/p&gt;
    &lt;blockquote&gt;
    &lt;p&gt;&lt;font color="#0000ff"&gt;Imports&lt;/font&gt; System.Runtime.InteropServices&lt;/p&gt;
    &lt;/blockquote&gt;&lt;/li&gt;
    &lt;li&gt;
    &lt;p&gt;In AssemblyInfo.vb, mark the assembly with the InternalsVisibleToAttribute for each friend assembly that should have access to the friend scope.&lt;/p&gt;
    &lt;blockquote&gt;
    &lt;p&gt;&amp;lt;Assembly: InternalsVisibleTo(&lt;font color="#800000"&gt;"MySystem.Assembly1"&lt;/font&gt;)&amp;gt; &lt;br /&gt;
    &amp;lt;Assembly: InternalsVisibleTo(&lt;font color="#800000"&gt;"MySystem.Assembly2"&lt;/font&gt;)&amp;gt; &lt;/p&gt;
    &lt;/blockquote&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you are working in C#, you will make your changes in the AssemblyInfo.cs file for the assembly that contains the code to be re-used, and you will use "using" instead of "Imports."&lt;/p&gt;
&lt;p&gt;So I could have my cake (re-use of existing code) &lt;em&gt;and&lt;/em&gt; shield it from inappropriate eyes at the same time.  While this technique is obviously useful for writing tests, it can be applied anywhere that code needs to be shared between your system's assemblies without exposing it customers as part of an API.  &lt;/p&gt;
&lt;p&gt;&lt;font size="1"&gt;&lt;/font&gt;&lt;/p&gt;
&lt;font size="1"&gt;* Not to mention the wool of bat and tongue of dog.&lt;/font&gt;
&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=130511"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=130511" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/130511.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2009/03/29/how-to-reuse-code-without-creating-an-implicit-api.aspx</guid>
            <pubDate>Sun, 29 Mar 2009 19:44:23 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/130511.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2009/03/29/how-to-reuse-code-without-creating-an-implicit-api.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/130511.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/130511.aspx</trackback:ping>
        </item>
        <item>
            <title>How To Create a Windows Form Singleton</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2008/06/06/how-to-create-a-windows-form-singleton.aspx</link>
            <description>&lt;p&gt;Recently a friend asked me how you might create a Windows Forms application that only allows a single instance per computer.  A print driver might make use of this functionality, for example, to launch a print job management dialog whenever a document prints.  Never having needed this sort of functionality before, my initial answer wasn't very helpful.  But being both curious and disinclined to back down from a technical challenge, I just had to figure this one out.&lt;/p&gt;
&lt;p&gt;As I was looking for an inter-process synchronization mechanism, I came across the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx"&gt;Semaphore&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx"&gt;Mutex&lt;/a&gt; in the System.Threading namespace.  A semaphore can be used to manage a pooled resource (memory buffer, thread pool, connection pool, etc.) by tracking the number of available resources.  You instantiate a semaphore with an invariant maximum corresponding to the quantity of pooled resource entities (e.g., the number of database connections).  Whenever a thread wants to use the resource, it calls .WaitOne() on the appropriate semaphore and blocks until the semaphore count is greater than zero.  If the count is positive when the call is made, the thread will not need to block at all.  &lt;/p&gt;
&lt;p&gt;When a thread enters a semaphore, the semaphore decrements its count by one.  The calling thread is responsible for calling the semaphore's .Release() method when it has completed using the resource.  This allows the semaphore to increment its count--and as a result, gives another thread access to the pooled resource.  You must call Release() inside of a finally block as soon as feasible in your codepath; my testing shows that the CLR will not release an unreleased semaphore when the semaphore reference goes out of scope, or even when the thread of execution terminates.&lt;/p&gt;
&lt;p&gt;What we need, then, is a semaphore that has a maximum count of one (since we want only one instance of our application to be running) and will increment its count no matter how the thread that entered it terminates.  Happily, this would be a pretty good one-sentence description of the Mutex class.  The thread that calls WaitOne on a mutex (&lt;a href="http://en.wikipedia.org/wiki/Mutex"&gt;"mutual exclusion"&lt;/a&gt;) gains ownership when it enters the mutex.  It can release the mutex at any time by calling the ReleaseMutex method, but should it fail to do so (whether by logic error or run-time failure) before it terminates, the CLR will release the mutex on its behalf.  As a result, the mutex should prove more reliable for our purposes.&lt;/p&gt;
&lt;p&gt;Here is the singleton code in a nutshell:&lt;/p&gt;
&lt;div style="FONT-SIZE: 10pt; FONT-FAMILY: Monospace; BACKGROUND-COLOR: white"&gt;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt;&lt;span style="COLOR: black"&gt; System;&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt;&lt;span style="COLOR: black"&gt; System.Windows.Forms;&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: blue"&gt;using&lt;/span&gt;&lt;span style="COLOR: black"&gt; System.Threading;&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: blue"&gt;namespace&lt;/span&gt;&lt;span style="COLOR: black"&gt; MutexTest&lt;br /&gt;
{&lt;br /&gt;
    &lt;/span&gt;&lt;span style="COLOR: blue"&gt;static&lt;/span&gt;&lt;span style="COLOR: black"&gt; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;class&lt;/span&gt;&lt;span style="COLOR: black"&gt; &lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Program&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;    {&lt;br /&gt;
        [&lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;STAThread&lt;/span&gt;&lt;span style="COLOR: black"&gt;]&lt;br /&gt;
        &lt;/span&gt;&lt;span style="COLOR: blue"&gt;static&lt;/span&gt;&lt;span style="COLOR: black"&gt; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;void&lt;/span&gt;&lt;span style="COLOR: black"&gt; Main()&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Application&lt;/span&gt;&lt;span style="COLOR: black"&gt;.EnableVisualStyles();&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Application&lt;/span&gt;&lt;span style="COLOR: black"&gt;.SetCompatibleTextRenderingDefault(&lt;/span&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;span style="COLOR: black"&gt;);&lt;br /&gt;
&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: green"&gt;// make sure no other instances of this app are running&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;bool&lt;/span&gt;&lt;span style="COLOR: black"&gt; mutexIsAvailable = &lt;/span&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Mutex&lt;/span&gt;&lt;span style="COLOR: black"&gt; m = &lt;/span&gt;&lt;span style="COLOR: blue"&gt;null&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;try&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;            {&lt;br /&gt;
                m = &lt;/span&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;span style="COLOR: black"&gt; &lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Mutex&lt;/span&gt;&lt;span style="COLOR: black"&gt;(&lt;/span&gt;&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;&lt;span style="COLOR: black"&gt;, &lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;"MutexTest.Singleton"&lt;/span&gt;&lt;span style="COLOR: black"&gt;);&lt;br /&gt;
                mutexIsAvailable = m.WaitOne(1, &lt;/span&gt;&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;&lt;span style="COLOR: black"&gt;); &lt;/span&gt;&lt;span style="COLOR: green"&gt;// wait only 1 ms&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;            }&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;catch&lt;/span&gt;&lt;span style="COLOR: black"&gt; (&lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;AbandonedMutexException&lt;/span&gt;&lt;span style="COLOR: black"&gt;)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;/span&gt;&lt;span style="COLOR: green"&gt;// don't worry about the abandonment; &lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;                &lt;/span&gt;&lt;span style="COLOR: green"&gt;// the mutex only guards app instantiation&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;                mutexIsAvailable = &lt;/span&gt;&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;span style="COLOR: black"&gt; (mutexIsAvailable)&lt;br /&gt;
            {&lt;br /&gt;
                &lt;/span&gt;&lt;span style="COLOR: blue"&gt;try&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;                {&lt;br /&gt;
                    &lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Application&lt;/span&gt;&lt;span style="COLOR: black"&gt;.Run(&lt;/span&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;span style="COLOR: black"&gt; &lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Form1&lt;/span&gt;&lt;span style="COLOR: black"&gt;());&lt;br /&gt;
                }&lt;br /&gt;
                &lt;/span&gt;&lt;span style="COLOR: blue"&gt;finally&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;                {&lt;br /&gt;
                    m.ReleaseMutex();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;One of three things can happen when the Main() thread calls m.WaitOne(1, false):&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;If the mutex is unowned (or becomes unowned within one millisecond), mutexIsAvailable is true and the thread enters/owns the mutex. &lt;/li&gt;
    &lt;li&gt;If the mutex remains owned by another instance of the Windows Form app for the one millisecond duration, mutexIsAvailable is false. &lt;/li&gt;
    &lt;li&gt;If the mutex is available because another instance abandoned it without releasing it, the method throws an AbandonedMutexException.  In this case, the thread owns the mutex and may safely launch the application instance, so it sets mutexIsAvailable true. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the Main thread owns the mutex, it runs the application, using a try/finally block in order to guarantee a call to ReleaseMutex.  While strictly speaking it is not necessary to call ReleaseMutex (the CLR will do so on the thread's behalf when it terminates), I have written the code this way in order to maintain a best practice.  In some other situation, the thread that enters the mutex might continue performing more work (or enter a suspended state) after finishing its use of the resource and might not call ReleaseMutex, so it's a good idea to write the code in this fashion.&lt;/p&gt;
&lt;p&gt;What do you think?  Is this code helpful?  Do you have any suggestions for improvement?  Leave a comment!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=122680"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=122680" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/122680.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2008/06/06/how-to-create-a-windows-form-singleton.aspx</guid>
            <pubDate>Fri, 06 Jun 2008 14:31:25 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/122680.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2008/06/06/how-to-create-a-windows-form-singleton.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/122680.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/122680.aspx</trackback:ping>
        </item>
        <item>
            <title>BOOK REVIEW: Don't Make Me Think, 2d Ed. by Steve Krug</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2008/05/13/review-of-dont-make-me-think.aspx</link>
            <description>&lt;p&gt;You've mastered web forms and controls.  You've prototyped a Silverlight 2.0 application.  AJAX? You're all over it.  But have you &lt;em&gt;really&lt;/em&gt; learned how to design a good web page or web site?  &lt;/p&gt;
&lt;p&gt;Steve Krug's "Common Sense Approach to Web Usability" provides surprising and sometimes counterintuitive principles that every good website must follow.  Krug preaches the importance of removing clutter in order to make the purpose and functionality of a site (or page) clear--and happily, he practices what he preaches in this remarkably lucid book.  Here are some of Krug's key insights: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Don't make users think! &lt;/strong&gt;Your job is to make sure users do not have to puzzle over a site's purpose, or how to use it.  Krug offers the search functionality at Amazon.com as a great example of this principle in action.  A user does not have to decide what type of search she wants (by author, by title, by ISBN, etc.); instead, she can just enter whatever text interests her, and Amazon offers a list of matches, ranked by relevance. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Users don't behave the way you think they do.&lt;/strong&gt;  You've been poring over your site--reading everything ten times or more--so you tend to think that users will do the same.  But they don't.  Instead, the users...
    &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;"don't read pages, they scan them."&lt;/em&gt; (In fact you only decided to read this review after you scanned the intro and decided it would be worth your while.) &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;"don't figure out how things work, they muddle through&lt;/em&gt;."&lt;br /&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Design pages for scanning.&lt;/strong&gt;  Since users are going to treat your site like a billboard going by at 70mph (rather than a textbook that they carefully work through), you should learn to design great billboards!
    &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;Create a clear visual hierarchy. &lt;/em&gt;Highlight the important stuff, and indicate relationship by grouping. &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;Use conventions.&lt;/em&gt;  If your site design conforms to what users generally expect, they can more easily understand it at a glance. &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;Break pages into clearly defined areas.&lt;/em&gt; &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;Make what's clickable obvious. &lt;/em&gt; Use arrows or underlines to indicate that text is clickable, for example. &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;Minimize noise. &lt;/em&gt; Prefer clarity to pizzazz.&lt;br /&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Give users simple\mindless choices.&lt;/strong&gt; It's okay to make a user traverse 4 or 5 links to get to his desired destination as long as each choice along the way is clear. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;"Omit needless words.&lt;/strong&gt;"  &lt;em&gt;"Get rid of half the words on each page, then get rid of half of what's left"&lt;/em&gt; is Krug's Third Law of Usability.  More words just make the site look more daunting, which can discourage the user in a hurry.  Krug's Third Law has 2 corollaries:
    &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;Happy talk must die. &lt;/em&gt; "We're so glad you're at our site!  We think you'll like your experience here..." Oops, you just lost your user, who's too busy to keep reading. &lt;/li&gt;
        &lt;li&gt;&lt;em&gt;Instructions must die.  &lt;/em&gt;Users almost never read them anyway (remember, they don't figure out, they muddle through).  So keep instructions brief and simple. &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Krug then discusses some details about 2 features every site must have: navigation and a home page.  Krug recommends that the sections and subsections of a site be indicated with a clear set of links or tabs on the home page, and that the navigation remain available  no matter where the user goes.  (This answers the questions: what can I do on this site?  and Where can I go from here?)  Each page should have a visible name, and the site should a breadcrumb trail with arrows between the levels in order to allow a user to know where he's at in the site's hierarchy.  (These answer the questions: where am I at now? and How do I get back to where I was before?). &lt;/p&gt;
&lt;p&gt;Krug's discussion of the home page acknowledges that the forces conspiring against simplicity are enormous in any ambitious site, because there are so many organizational interests competing for the valuable home page real estate.  Krug provides some useful tips for managing the problems, though, by suggesting how to use logos, taglines, and home page navigation.  &lt;/p&gt;
&lt;p&gt;Next Krug addresses the often religious arguments that site development teams often endure (pulldowns or menus?  Flash animation or simple text?) with this simple advice: forget the arguments and start testing!  Simple usability testing will reveal the key problems with a site, and often they have nothing to do with what the development team has been arguing about.  Krug believes that frequent tests are more important than comprehensive (often expensive tests), and he offers advice on how to do testing on a tight budget (use 3 or 4 subjects; use an inexpensive screen recorder like Camtasia; try to get all the project stakeholders to observe).  He concludes with an extremely useful script of an interaction between a test subject and a test guide.&lt;/p&gt;
&lt;p&gt;Those who have already read the first edition will be pleased to know that Krug has included some very helpful new material in the second edition.  Is your site accessible to sight-impaired users?  If not, Krug offers a top 5 list of tips for making sites accessible, along with a pointer on how to use Cascading Style Sheets to make your site more accessible.  Not to mention that CSS makes your site a lot easier to manage.... And what do you do when your boss (or the customer) wants you to do something that violates every known law of web usability?  Just compose an email that borrows liberally from one of Krug's friendly "here's how it should be done" missives!&lt;/p&gt;
&lt;p&gt;Krug sprinkles his book with examples of sites that work well (and a few that don't) to illustrate his ideas.  He often offers a few "How does (or does not) this page implement the principles we've been discussing?" tests, with his own answers on the following pages.  I found these examples to be enormously helpful.  And Krug offers a wonderful set of additional resources for those who want to pursue the subject further, both within the text and in a notated bibliography at the end.&lt;/p&gt;
&lt;p&gt;Because I am a long-time web user and web developer, I thought I understood just about everything I needed to know about usability to design a good site.  Then I read this book, and learned a ton.  If you work on web sites in any way (whether as designer, developer, or tester), the few hours you spend on Steve Krug's little gem will pay rich dividends.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=122116"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=122116" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/122116.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2008/05/13/review-of-dont-make-me-think.aspx</guid>
            <pubDate>Tue, 13 May 2008 20:31:39 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/122116.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2008/05/13/review-of-dont-make-me-think.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/122116.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/122116.aspx</trackback:ping>
        </item>
        <item>
            <title>Want to Write Great Business Software? Create a Great Domain Model!</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2008/03/25/value-of-domain-model.aspx</link>
            <description>&lt;p&gt;&lt;font face="Arial"&gt;When you are coding in a hurry, it is very tempting to write business logic in the first place that comes to mind, such as a button click handler.  However, for all but the simplest systems, such a practice leads very quickly to a chaotic system whose business logic is scattered like the ash from an erupting volcano. &lt;/font&gt; So let's take a step back and see how you can develop an application more intelligently.&lt;/p&gt;
&lt;h4&gt;"Divide and Conquer"&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;“Divide and Conquer”&lt;/em&gt; is a useful metaphor for organizing the effort of developing a complex system.  A software architect can assign major system responsibilities to various components or layers (which I will refer to as a “part”).  As long as the responsibilities of a part are understood, a developer can develop the part in such a way as to satisfy those responsibilities.  And as long as the parts integrate well, a useful system can emerge. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Divide and Conquer”&lt;/em&gt; has many advantages: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;A team can work in a coordinated fashion on several parts of the system simultaneously, without stepping on each other’s toes. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;Assigning a limited set of related responsibilities to a system part simplifies its design. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;Modifying a system is easier when the part that is responsible for the functionality that must be changed can be identified. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;Ultimately, the complexity of the system decreases as its various responsibilities, and the strategies for handling them, become clear.  Unnecessary complexity is what can make “the last 10%” of a project go into deep cost and time overruns, as quality issues and poor design make their effects known. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;“Divide and Conquer”&lt;/em&gt; is the driving force behind creating logical layers of a user interface, an application layer, a data layer, and a domain model in an enterprise software application.  &lt;/p&gt;
&lt;p&gt;While the advantages of separating UI, application, and data logic into their own layers are well understood and frequently practiced, the point behind creating a domain model is not as widely grasped.  A domain model defines the business entities represented by a system, the activities associated with them, the relationships between them, and the rules and constraints that govern them. These are clearly very important aspects of the system, even though (from the end user’s perspective) they are not as visible as the user interface, application flow, or database.  I will illustrate the importance of a domain model by examining how insurance endorsements work in the homeowners point-of-sale system that my team has developed.&lt;/p&gt;
&lt;h4&gt;Example of a Complex Business Domain&lt;/h4&gt;
&lt;p&gt;Let’s start by examining the data model for endorsements: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;An endorsement can be associated with either an application (future policy) or with a risk (such as a dwelling or a vehicle).  Therefore the Endorsement table has 2 foreign keys: one that relates an endorsement to an application (via the Quotenumber) and the other that relates it to a risk (via the RiskId). &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;Endorsements come in a bewildering variety.  Some endorsements have no related data; some have one or more limits; some have one or more attributes, few of which are common between endorsements.  Clearly it is unwise to attempt to create a single table with identified columns for each of the possible limits or attributes that an endorsement may possess.  In addition, any attempt to create a unique table for each endorsement’s associated attributes is going to result in a very large number of tables—along with the responsibility of defining a new table each time a new endorsement type is created.  Therefore, the design we chose was to create 2 dependent tables for Endorsement: an EndorsementLimit table and an EndorsementDescription table.  Each table has 3 fields: an EndorsementId (foreign key back to the associated endorsement), a “type” field that allows the system to distinguish between all the related descriptions (or limits) of an endorsement, and the associated data field (a numerical limit or a varchar description).  Note that segmentation and history are irrelevant to a point-of-sale system, so the schema is not designed with that capability. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;Some endorsements are concerned with parties to an insurance application other than the applicant, such as an additional interest or an additional insured.  Since these additional entities reside in a different table (the OtherParty table), we use a join table (EndorsementParty) to manage the association between Endorsement and OtherParty. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This portion of the database schema is represented graphically below: &lt;/p&gt;
&lt;p&gt;&lt;img height="573" alt="Entity-Relationship Diagram for Endorsements" width="701" src="/images/geekswithblogs_net/chrisfalter/DomainModel/EndorsementDataDiagram.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;So if we have a data model, why do we need a domain model?  Why can’t some UI code simply write its data directly to the tables?  Clearly this one way of designing a system—you can, after all, do anything with software (provided you have sufficient time and resources).&lt;/p&gt;
&lt;p&gt;Let us consider, though, the knowledge about the business domain that the point-of-sale application must manage with regard to endorsements:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;The relationship of endorsement attributes to an endorsement.&lt;/strong&gt;  A homeowners “HO 05 28” (golf cart) endorsement has several related attributes: a limit (cart value), a make, a model, a serial number, and an indicator of whether collision coverage is included.  Each one of these attributes is stored in its own record in the EndorsementLimit or EndorsementDesc table.  The DescType field distinguishes the four EndorsementDesc records from one another; however, the system must somehow keep track of which DescType is used for which attribute. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Differences between the format of stored data and how it is used.&lt;/strong&gt;  In a database system that does not have a built-in boolean type (such as the DB2 flavor used at my shop), there are probably as many different ways to store boolean data as there are programmers.  True vs. false could be represented as “0” vs. “1”, or as “1” vs. “2”, or as “T” vs. “F”, or as “t” vs. “f”, or as “true” vs. “false”, or as “Y” vs. “N”, etc.  (In one of my consulting engagements, I actually saw all of these &lt;em&gt;plus&lt;/em&gt; a couple more in a single application.) To handle a golf cart endorsement’s indicator of collision coverage, the system must be able to reliably map between the stored data and a run-time choice of true/false. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;The relationships between endorsements and other entities.&lt;/strong&gt;  Some endorsements are related to the risk being insured (such as the earthquake endorsement), and some are related to the (potential) policy itself (such as an “Additional Insured” endorsement). &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;The relationships between endorsement attributes.&lt;/strong&gt;  The “HO 04 65” endorsement (scheduled property) contains a set of schedules; each schedule is designated by a letter such as “A” or “J” and has a description (the personal property being insured) and a limit.  Since descriptions and limits are stored in separate tables, the system must have some way of identifying and associating the schedules’ descriptions and limits. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Rules and constraints on various endorsements.&lt;/strong&gt;  The 6 schedules on a “HO 04 65” endorsement have base (default) limits, for example, such that the total limit of a schedule can be described as the base limit plus an additional limit.  Mathematically speaking, we use the formula &lt;em&gt;Total Limit = Base (fixed by rule) + Additional (stored in EndorsementLimit table)&lt;/em&gt;.  So the system must be able both to provide base, additional, and total limits (given the stored additional limit) and to update the stored additional limit (based on user entry). &lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Complexity Resolved: A Domain Model&lt;/h4&gt;
&lt;p&gt;The beauty of our team's domain model is that it completely hides all of this complexity from the user interface. &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;An endorsement class is defined for each type of endorsement, and it provides an interface that is radically simple for the UI developer to use.  To give just one example, the golf cart endorsement provides a boolean &lt;em&gt;CollisionIncluded&lt;/em&gt; property that can be mapped to a checkbox.  &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;All of the other issues (which EndorsementDesc record the indicator is stored in, how the boolean is mapped to a varchar, etc.) are managed inside an endorsement class—frequently by using capabilities inherited from the EndorsementBase class or borrowed from utility classes in the domain layer. &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;Responsibilities are clearly grouped and assigned in this way of designing a system.  Tasks and attributes that are common to all endorsements are the responsibility of the EndorsementBase class.  The tasks and attributes that are unique to a particular endorsement are the responsibility of the corresponding subclass of EndorsementBase (which already has the common endorsement capabilities via its inheritance relationship with EndorsementBase).  Neither of these classes needs to know anything about the application or user interface which will use them, which in turn need to know nothing at all about the internal implementation details of an endorsement class. The diagram below depicts the assignment of some endorsement responsibilities to classes in our domain layer.&lt;br /&gt;
    &lt;br /&gt;
    &lt;img height="688" alt="Endorsement Class Diagram" width="619" src="/images/geekswithblogs_net/chrisfalter/DomainModel/EndorsementClassDiagram.jpg" /&gt; &lt;/li&gt;
    &lt;li&gt;The association of an endorsement with a policy or with a risk is managed via its membership in an EndorsementCollection that is accessed via the &lt;em&gt;HomeApplication&lt;/em&gt; object or the &lt;em&gt;HomeApplication.Home&lt;/em&gt; object (of type &lt;em&gt;HomeRisk&lt;/em&gt;), respectively. The relationship between these various entities is depicted below.&lt;br /&gt;
    &lt;br /&gt;
    &lt;img height="442" alt="Relationship of Endorsements to HomeApplication and HomeRisk" width="384" src="/images/geekswithblogs_net/chrisfalter/DomainModel/UsingEndorsementsClassDiag.jpg" /&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;There are some things that should never leak.  Space shuttle O-rings.  Tires.  Diapers.  And now that you've read this article, add your business domain model to the list.  Always isolate your business domain logic in a cohesive model; do not let the logic leak into a "smart UI" or into the data layer!  If you follow this rule, you will save yourself and your team much time and effort when you need to modify the business logic in your application.&lt;/p&gt;
&lt;p&gt;Also, keep the importance of your domain model in mind when it is time to choose a development tool.  A rapid application development (RAD) tool that can only design screens and logic flows might be a very good choice for building a very simple system that needs little complexity in its business logic.  However, it is very difficult to envision how a RAD tool would be able to represent the relationships and constraints inherent to a complex business domain, such as homeowners insurance endorsements.  Given the inherent limitations of a RAD tool, the complexity that my team's domain model currently manages quite capably would have to spill out into the flows and screens themselves.  &lt;/p&gt;
&lt;p&gt;While the result may initially seem counterintuitive, a RAD tool that at first glance makes everything look simple might very well in the end produce a system far more complex than a system produced with a set of tools that offer a robust and complete set of programming capabilities.  And this unanticipated complexity can make the systems you develop far more difficult to implement on time and to extend with new customer-requested capabilities.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120748"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120748" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/120748.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2008/03/25/value-of-domain-model.aspx</guid>
            <pubDate>Tue, 25 Mar 2008 14:01:28 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/120748.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2008/03/25/value-of-domain-model.aspx#feedback</comments>
            <slash:comments>6</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/120748.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/120748.aspx</trackback:ping>
        </item>
        <item>
            <title>Refactoring to Comply with the DRY principle (Don't Repeat Yourself)</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2008/03/07/refactor-to-dry.aspx</link>
            <description>&lt;p&gt;If you're not living DRY, you're not a good programmer.&lt;/p&gt;
&lt;p&gt;Okay, I'm not talking about alcohol consumption!  I'm talking about the &lt;strong&gt;Don't Repeat Yourself&lt;/strong&gt; principle--a principle every programmer should live by.  Recently I did a code review for a project we outsourced, and demonstrated how you can refactor bad cut-and-paste code into well-designed code.  You will note that the capabilities of the &lt;a href="http://www.eggheadcafe.com/tutorials/aspnet/b916e3a9-d056-4669-8bf3-aa98ed6669c3/a-good-solution-for-magi.aspx"&gt;MagicStringTranslator&lt;/a&gt; class really help to reduce code clutter. Without further ado, I present the relevant portion of my code review:&lt;/p&gt;
&lt;p&gt;...your branching logic has 12 lines of code in each branch except the final one.  I am inserting an excerpt for reference:&lt;/p&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (m_record.Text.Substring(13, 6).Trim() == &lt;span style="COLOR: #a31515"&gt;"IDENT"&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteBreak();&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"Table style='width: 100%' border='1'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"tr style='background-color:#ccffcc;'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"td style='width: 100%;' colspan='2' align='center'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"span style='font-size: 9pt;"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.Write(&lt;span style="COLOR: #a31515"&gt;"SUBJECT INFORMATION"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"span"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TD"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TR"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"Table"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        }&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (m_record.Text.Substring(13, 6).Trim() == &lt;span style="COLOR: #a31515"&gt;"SUMRY"&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteBreak();&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"Table style='width: 100%' border='1'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"tr style='background-color:#ccffcc;'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"td style='width: 100%;' colspan='2' align='center'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"span style='font-size: 9pt;"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.Write(&lt;span style="COLOR: #a31515"&gt;"SUMMARY"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                        writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"span"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TD"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TR"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"Table"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        }&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (m_record.Text.Substring(13, 6).Trim() == &lt;span style="COLOR: #a31515"&gt;"COLLT"&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;           &lt;font color="#006600"&gt;// this code and several more near-identical branches are omitted for brevity’s sake&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        }&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;Eleven of these lines of code are identical.  This is bad for 3 reasons: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;What would happen if one of the lines of code had a bug?  You would have to fix it in each branch, and be sure to do it the same way in each one.  This code structure is &lt;strong&gt;bug-prone&lt;/strong&gt;. &lt;/li&gt;
    &lt;li&gt;The structure implies that each branch does different things, when the code in fact does essentially the same thing.  As a result, the code structure is &lt;strong&gt;misleading&lt;/strong&gt;. &lt;/li&gt;
    &lt;li&gt;The code ends up being way too verbose; it is saying the same thing over and over and over.  As a result, the code structure is &lt;strong&gt;hard to read and understand&lt;/strong&gt;. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In fact, your code does suffer from an insidious little bug.  You are comparing a substring of length 6 to a literal of length 5.&lt;/p&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (m_record.Text.Substring(13, 6).Trim() == &lt;span style="COLOR: #a31515"&gt;"IDENT"&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;This only happens to work when the 6th character is a blank, because in this circumstance the Trim() method reduces the string to length 5, and the comparison is valid.  What would happen if the 6th character did not happen to be a blank?&lt;/p&gt;
&lt;p&gt;But don't try to fix this bug in the seven places where it occurs!  There are better ways to improve the code.  One way is to restrict the branching logic to the one line of code, then use that one line together with the other 11 exactly once.&lt;/p&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; title = &lt;span style="COLOR: #2b91af"&gt;String&lt;/span&gt;.Empty;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;switch&lt;/span&gt; (m_record.Identifier)&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        {&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"IDENT"&lt;/span&gt;: &lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                title = &lt;span style="COLOR: #a31515"&gt;"SUBJECT INFORMATION"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                &lt;span style="COLOR: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"SUMRY"&lt;/span&gt;: &lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                title = &lt;span style="COLOR: #a31515"&gt;"SUMMARY"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                &lt;span style="COLOR: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"COLLT"&lt;/span&gt;: &lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                title = &lt;span style="COLOR: #a31515"&gt;"COLLECTION ITEMS"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                &lt;span style="COLOR: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"ACCNT"&lt;/span&gt;: &lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                title = &lt;span style="COLOR: #a31515"&gt;"TRADE ACCOUNT ACTIVITY"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                &lt;span style="COLOR: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"MSSGE"&lt;/span&gt;: &lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                title = &lt;span style="COLOR: #a31515"&gt;"MESSAGE"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                &lt;span style="COLOR: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"EMPLY"&lt;/span&gt;: &lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                title = &lt;span style="COLOR: #a31515"&gt;"EMPLOYMENT"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                &lt;span style="COLOR: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            &lt;span style="COLOR: blue"&gt;case&lt;/span&gt; &lt;span style="COLOR: #a31515"&gt;"INQHS"&lt;/span&gt;: &lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                title = &lt;span style="COLOR: #a31515"&gt;"INQUIRY HISTORY"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                &lt;span style="COLOR: blue"&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        }&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"Table style='width: 100%' border='1'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"tr style='background-color:#ccffcc;'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"td style='width: 100%;' colspan='2' align='center'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"span style='font-size: 9pt;"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.Write(title);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"span"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TD"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TR"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"Table"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;An even better way is to delegate the relationship between magic string (e.g., “INQHS”) and description (e.g., “INQUIRY HISTORY”) to a class specialized for this purpose.  Then you can simply use the class directly, without writing any branching logic at all.  In this situation, define a &lt;a href="http://www.eggheadcafe.com/tutorials/aspnet/b916e3a9-d056-4669-8bf3-aa98ed6669c3/a-good-solution-for-magi.aspx"&gt;MagicStringTranslator&lt;/a&gt; subclass for the Identifier property:&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;    &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;class&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;IdentifierCode&lt;/span&gt; : &lt;span style="COLOR: #2b91af"&gt;MagicStringTranslator&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;    {&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; SUBJECT_INFO = &lt;span style="COLOR: #a31515"&gt;"IDENT"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; SUMMARY = &lt;span style="COLOR: #a31515"&gt;"SUMMARY"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; COLLECTION_ITEMS = &lt;span style="COLOR: #a31515"&gt;"COLLT"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; TRADE_ACCOUNT_ACTIVITY = &lt;span style="COLOR: #a31515"&gt;"ACCNT"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; MESSAGE = &lt;span style="COLOR: #a31515"&gt;"MSSGE"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; EMPLOYMENT = &lt;span style="COLOR: #a31515"&gt;"EMPLY"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;const&lt;/span&gt; &lt;span style="COLOR: blue"&gt;string&lt;/span&gt; INQUIRY_HISTORY = &lt;span style="COLOR: #a31515"&gt;"INQHS"&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;    }&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;Then make the class’ Identifier property of type IdentifierCode:&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        &lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;IdentifierCode&lt;/span&gt; Identifier&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            {&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                  &lt;span style="COLOR: blue"&gt;get&lt;/span&gt;{ &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: #2b91af"&gt;IdentifierCode&lt;/span&gt;(segments[(&lt;span style="COLOR: blue"&gt;int&lt;/span&gt;)&lt;span style="COLOR: #2b91af"&gt;Fields&lt;/span&gt;.Identifier].Data); }&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                  &lt;span style="COLOR: blue"&gt;set&lt;/span&gt; { } &lt;span style="COLOR: green"&gt;// no-op setter provided so that XmlSerializer can serialize this property&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            }&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;Finally, use the Identifier directly, without any need for branching logic:&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"Table style='width: 100%' border='1'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"tr style='background-color:#ccffcc;'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"td style='width: 100%;' colspan='2' align='center'"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"span style='font-size: 9pt;"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteFullBeginTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;&lt;span style="FONT-SIZE: 10pt; COLOR: #76923c"&gt;                    writer.Write(m_record.Identifier.Description);&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"strong"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                    writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"span"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;                writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TD"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;            writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"TR"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;        writer.WriteEndTag(&lt;span style="COLOR: #a31515"&gt;"Table"&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt; &lt;/div&gt;
&lt;div style="MARGIN: 0in 0in 0pt"&gt;And you're done.&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120367"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120367" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/120367.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2008/03/07/refactor-to-dry.aspx</guid>
            <pubDate>Fri, 07 Mar 2008 13:45:40 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/120367.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2008/03/07/refactor-to-dry.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/120367.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/120367.aspx</trackback:ping>
        </item>
        <item>
            <title>A Good Solution for "Magic String" Data</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2008/03/06/good-solution-for-magic-string-data.aspx</link>
            <description>&lt;p&gt;&lt;font face="Arial"&gt;Dealing with vendor data (or your own) in the form of "codes" can pose significant challenges. You must ensure that your source code remains readable, that data are properly validated, and that data can be displayed as user-friendly descriptions. The built-in solutions (named constants and enums) help, but they have some significant shortcomings. If you derive a class of named constants from the MagicStringTranslator class, though, you can vanquish all 3 challenges in one fell swoop!&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Egghead Cafe has kindly published the improved version of my article &lt;a href="http://www.eggheadcafe.com/tutorials/aspnet/b916e3a9-d056-4669-8bf3-aa98ed6669c3/a-good-solution-for-magi.aspx"&gt;here&lt;/a&gt;.  Enjoy!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120321"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120321" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/120321.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2008/03/06/good-solution-for-magic-string-data.aspx</guid>
            <pubDate>Thu, 06 Mar 2008 16:08:45 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/120321.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2008/03/06/good-solution-for-magic-string-data.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/120321.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/120321.aspx</trackback:ping>
        </item>
        <item>
            <title>Make Magic Strings Easy to Understand and Type Safe</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2008/02/27/120016.aspx</link>
            <description>&lt;p&gt;As organizations pass data back and forth, they often use codes to represent the data.  For example, a marital status of divorced might be represented as "D", married as "M", and so forth.  You have to solve three problems when you are dealing with magic strings:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;When you write logic to handle the data, things can get chaotic on a hurry if you are not careful; the use of literal magic strings in your source code can make it incomprehensible.  &lt;/li&gt;
    &lt;li&gt;You can get into trouble by passing a string that is not in the set of valid codes as a parameter to a method that is expecting one of the codes.  Since the parameter type is typically string, the compiler will not help you detect the error. &lt;/li&gt;
    &lt;li&gt;You often have to translate codes into it description so a user of your system will know which data have been gathered. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Using named constants can help make your source code more readable, but you still have more work to do: you must write extra logic to check whether a string belongs to the set of valid codes, and to translate a code into a description that a user can understand.  If you declare your named constants in a class that inherits from the MagicStringTranslator class, though, you will get the data validation and the translation for free.  Check out the &lt;a href="http://www.eggheadcafe.com/tutorials/aspnet/b916e3a9-d056-4669-8bf3-aa98ed6669c3/a-good-solution-for-magi.aspx"&gt;article&lt;/a&gt; I wrote for the details!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120016"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120016" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/120016.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2008/02/27/120016.aspx</guid>
            <pubDate>Wed, 27 Feb 2008 07:40:16 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/120016.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2008/02/27/120016.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/120016.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/120016.aspx</trackback:ping>
        </item>
        <item>
            <title>"New" Statement Considered Harmful</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2008/02/15/new-statement-considered-harmful.aspx</link>
            <description>&lt;p&gt;All of us have probably written code like this:&lt;/p&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;&lt;font color="#008080"&gt;Foo&lt;/font&gt; &lt;/font&gt;f = &lt;font color="#0000ff"&gt;new&lt;/font&gt; Foo();&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;And what could be simpler?  As long as the logic in the constructor is simple (or better yet, the constructor is empty), it would seem that the simplest code is the best, so just use the constructor.  Certainly the MSDN documentation is rife with code that uses public constructors.  You can probably find plenty of public constructors used right here on my blog.  Why invest the effort in writing (and using) a factory class that will probably never do anything useful, other than call a public constructor?&lt;/p&gt;
&lt;p&gt;In his excellent &lt;a href="http://www.netobjectives.com/webinars/EmergentDesign/EmergentDesign_12_11_2007.mp3"&gt;podcast&lt;/a&gt; entitled "Emergent Design: The Evolutionary Nature of Software Development," Scott Bain of Net Objectives nevertheless makes a strong case against the routine use of public constructors.  The problem, notes Scott, is that the use of a public constructor ties the calling code to the implementation of Foo as a concrete class.  But suppose that you later discover that there need to be many subtypes of Foo, and Foo should therefore be an abstract class instead of a concrete class--what then?  You've got a big problem, that's what; a lot of client code that has been making use of Foo's public constructor suddenly becomes invalid.&lt;/p&gt;
&lt;p&gt;Exposing a public constructor, observes Bain, allows code to violate &lt;a href="http://en.wikipedia.org/wiki/Open_Closed_Principle"&gt;the open/closed principle&lt;/a&gt;.  This principle states that software should be open for extension, but closed for modification.  Restating this in more mundane terms, developers should design their code in such a way that extending it (for example, making a class more useful by defining it as abstract and subclassing it as appropriate) does not provoke side effects elsewhere--and that's the "closed for modification" part in a nutshell.&lt;/p&gt;
&lt;p&gt;Bain points out that there is a simple, low-cost practice that avoids the public constructor's violation of the open/closed principle.  Just give a class constructor protected scope, and define a static Create method that uses the constructor--that's it.  Here's class Foo's new skeletal definition in C#:&lt;/p&gt;
&lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;public class&lt;/font&gt; &lt;font color="#008080"&gt;Foo&lt;/font&gt;&lt;br /&gt;
{&lt;br /&gt;
  &lt;font color="#0000ff"&gt;protected &lt;/font&gt;Foo() {}&lt;br /&gt;
&lt;br /&gt;
  &lt;font color="#0000ff"&gt;public static&lt;/font&gt; &lt;font color="#008080"&gt;Foo&lt;/font&gt; Create() { return &lt;font color="#0000ff"&gt;new&lt;/font&gt; Foo(); }&lt;br /&gt;
}&lt;/font&gt;&lt;br /&gt;
&lt;p&gt;How hard was that?  At the cost of a single line of code, you get benefits well beyond the already mentioned ability to transform the class into an abstract base class:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;If object construction becomes more complex, you can use a factory class inside the Create method. &lt;/li&gt;
    &lt;li&gt;You can implement the &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;Dependency Injection&lt;/a&gt; pattern, which facilitates unit testing with mock objects. &lt;/li&gt;
    &lt;li&gt;You can use Microsoft's &lt;a href="http://msdn2.microsoft.com/en-us/architecture/bb410104.aspx"&gt;Policy Injection Application Block&lt;/a&gt; to implement cross-cutting concerns such as logging, authorization, and validation. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unfortunately, you may occasionally encounter a corner case where you must define a public constructor.  The .NET Framework's XmlSerializer cannot be used on a class with no public default constructor, since XmlSerializer must instantiate the class in order to discover the public properties that must be serialized.  If you plan to serialize a class using XmlSerializer, then, you must make the constructor public--but you should mark it with the ObsoleteAttribute to warn fellow developers not to use it:&lt;/p&gt;
&lt;p&gt; &lt;font face="Courier New"&gt;&lt;font color="#0000ff"&gt;public class&lt;/font&gt; &lt;font color="#008080"&gt;Foo&lt;/font&gt;&lt;br /&gt;
{&lt;/font&gt;&lt;br /&gt;
&lt;font face="Courier New"&gt;  [&lt;font color="#008080"&gt;Obsolete&lt;/font&gt;(&lt;font color="#993300"&gt;"Do not use--provided only for use by XmlSerializer.  Client code should call Foo.Create()."&lt;/font&gt;)]&lt;br /&gt;
  &lt;font color="#0000ff"&gt;public &lt;/font&gt;Foo() {}&lt;br /&gt;
&lt;br /&gt;
  &lt;font color="#0000ff"&gt;public static&lt;/font&gt; &lt;font color="#008080"&gt;Foo&lt;/font&gt; Create() { return &lt;font color="#0000ff"&gt;new&lt;/font&gt; Foo(); }&lt;br /&gt;
}&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;If due to habit a fellow programmer calls the public constructor (against your intentions), the C# compiler will emit a helpful warning message.  Of course, there are programmers who ignore warnings, but that is the subject of a different post.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=119675"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=119675" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/119675.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2008/02/15/new-statement-considered-harmful.aspx</guid>
            <pubDate>Fri, 15 Feb 2008 20:59:48 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/119675.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2008/02/15/new-statement-considered-harmful.aspx#feedback</comments>
            <slash:comments>12</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/119675.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/119675.aspx</trackback:ping>
        </item>
        <item>
            <title>Of Sobriety Tests and Loop Iteration</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2007/11/08/116713.aspx</link>
            <description>&lt;p&gt;A few years ago I listened in fascination to a radio interview with a highway patrol officer who was describing how she conducted field sobriety tests.  In addition to the typical tests of walking in a straight line and of standing on one foot, she would ask the erratic driver to recite the alphabet.  One driver slurred, "A.  Is that good enough?"  "That's all the alphabet you can recite?" she responded.  "Yep," he answered.  She booked him.  She would also ask drivers to count backwards from 100.  If a driver skipped around or had to think hard, his mental facilities were not sharp enough to permit him to drive safely.&lt;/p&gt;
&lt;p&gt;Counting backwards can also come in handy when you're performing a loop iteration.  For years we had some data access code that looped through a DataRowCollection in order to commit changes to a DB2 database:&lt;/p&gt;
&lt;div style="FONT-SIZE: 9pt; FONT-FAMILY: monospace; BACKGROUND-COLOR: white"&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt;&lt;span style="COLOR: black"&gt; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;void&lt;/span&gt;&lt;span style="COLOR: black"&gt; SaveRows(DataTable tbl)&lt;br /&gt;
{&lt;br /&gt;
    &lt;/span&gt;&lt;span style="COLOR: blue"&gt;string&lt;/span&gt;&lt;span style="COLOR: black"&gt; spName = &lt;/span&gt;&lt;span style="COLOR: blue"&gt;null&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
    &lt;/span&gt;&lt;span style="COLOR: blue"&gt;for&lt;/span&gt;&lt;span style="COLOR: black"&gt; (&lt;/span&gt;&lt;span style="COLOR: blue"&gt;int&lt;/span&gt;&lt;span style="COLOR: black"&gt; i = 0; i &amp;lt; tbl.Rows.Count; i++)&lt;br /&gt;
    {&lt;br /&gt;
        DataRow row = tbl.Rows[i];&lt;br /&gt;
        DataRowState rowState = row.RowState;&lt;br /&gt;
        &lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;span style="COLOR: black"&gt; ((rowState &amp;amp; DataRowState.Unchanged) &amp;gt; 0)&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;continue&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
        &lt;/span&gt;&lt;span style="COLOR: blue"&gt;switch&lt;/span&gt;&lt;span style="COLOR: black"&gt; (row.RowState)&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;case&lt;/span&gt;&lt;span style="COLOR: black"&gt; DataRowState.Added:&lt;br /&gt;
                spName = &lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;"SPI"&lt;/span&gt;&lt;span style="COLOR: black"&gt; + tbl.TableName;&lt;br /&gt;
                &lt;/span&gt;&lt;span style="COLOR: blue"&gt;break&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;case&lt;/span&gt;&lt;span style="COLOR: black"&gt; DataRowState.Modified:&lt;br /&gt;
                spName = &lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;"SPU"&lt;/span&gt;&lt;span style="COLOR: black"&gt; + tbl.TableName;&lt;br /&gt;
                &lt;/span&gt;&lt;span style="COLOR: blue"&gt;break&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;case&lt;/span&gt;&lt;span style="COLOR: black"&gt; DataRowState.Deleted:&lt;br /&gt;
                spName = &lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;"SPD"&lt;/span&gt;&lt;span style="COLOR: black"&gt; + tbl.TableName;&lt;br /&gt;
                &lt;/span&gt;&lt;span style="COLOR: blue"&gt;break&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;/span&gt;&lt;span style="COLOR: blue"&gt;try&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;        {&lt;br /&gt;
            IDbDataParameter[] parms = DataHelperParameterCache.GetSpParameterSet(DataHelper.ConnectionString, spName);&lt;br /&gt;
            CallStoredProc(spName, parms, row);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;/span&gt;&lt;span style="COLOR: blue"&gt;catch&lt;/span&gt;&lt;span style="COLOR: black"&gt; (&lt;/span&gt;&lt;span style="COLOR: #2b91af"&gt;Exception&lt;/span&gt;&lt;span style="COLOR: black"&gt; ex)&lt;br /&gt;
        {&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt;&lt;span style="COLOR: black"&gt; (tx != &lt;/span&gt;&lt;span style="COLOR: blue"&gt;null&lt;/span&gt;&lt;span style="COLOR: black"&gt;)&lt;br /&gt;
            {&lt;br /&gt;
                tx.Rollback();&lt;br /&gt;
                rolledBack = &lt;/span&gt;&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;&lt;span style="COLOR: black"&gt;;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;/span&gt;&lt;span style="COLOR: blue"&gt;throw&lt;/span&gt;&lt;span style="COLOR: black"&gt; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;new&lt;/span&gt;&lt;span style="COLOR: black"&gt; BaseApplicationException(&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;"Fatal Exception while running stored proc "&lt;/span&gt;&lt;span style="COLOR: black"&gt; + spName, ex);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;Then after we had called this function on all the DataTables in the DataSet, we called DataSet.AcceptChanges().  This code generally worked well.&lt;/p&gt;
&lt;p&gt;Then one day we realized that by not using a IDbTransaction (we left it null) and calling DataSet.AcceptChanges() at the end, we would leave our DataSet in a state inconsistent with the data store if a failure occurred part way through the process of saving tables and rows.  For example, if a row had been inserted to the data store, but AcceptChanges() had not been called, then its RowState was still DataRowState.Added.  And the next time a user tried to save his work, our system would try to insert an additional row, rather than updating the row that was already in the data store.  So we decided to call DataRow.AcceptChanges() after each row operation (after the call to CallStoredProc in the above code).&lt;/p&gt;
&lt;p&gt;A few days later, our testers reported that the last of 2 delete operations would no longer commit to the data store.  What?  How could adopting a new strategy for accepting changes cause that kind of bug?&lt;/p&gt;
&lt;p&gt;Well, what happens when you call DataRow.AcceptChanges() when the RowState is DataRowState.Deleted?  Poof!  It vanishes into thin air.  As a result, the next row would get skipped over in the loop iteration, since its ordinal had shifted back by one.  &lt;/p&gt;
&lt;p&gt;Allow me to illustrate: you've got 2 rows, and you're going through the loop.  The first time you enter the loop body, &lt;em&gt;i&lt;/em&gt; is 0 and you're working with Rows[0], the first row.  Before you finish the loop, you call DataRow.AcceptChanges(), and the row disappears in a cloud of smoke, &lt;em&gt;alakazam!&lt;/em&gt;  Now the row that used to be at Rows[1] shifts back to Rows[0], and Rows.Count == 1.  And we're at the end the loop, so we increment &lt;em&gt;i&lt;/em&gt; to 1 and do the test:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;i &amp;lt; tbl.Rows.Count&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This statement is false, so we exit the &lt;em&gt;for&lt;/em&gt; loop.  Thus the row that shifted from index 1 to index 0 (when its sibling vanished) never got processed.&lt;/p&gt;
&lt;p&gt;My first thought on fixing the problem was to use a &lt;em&gt;foreach&lt;/em&gt; loop and let it figure out how to deal with the deletion for me.  However, the DataRowCollection quite correctly threw an &lt;em&gt;InvalidOperationException&lt;/em&gt; when we tried it, and I can't blame the class designers for the behavior.  Remember, the iterator is supposed to keep track of the Current and the Next member of the collection as you traverse it.  But if you delete the Current member, where should Current point to?  Can it point to the member of the collection immediately following the deleted member?  Not really; Current and Next would then be referring to the same member.  And if the iterator shifted the Next by one to avoid the clash, the same way it shifted Current by one, we might skip over the collection member that immediately follows the deleted member when the iterator's MoveNext method is called.  As the .NET Framework documentation states:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The &lt;strong&gt;foreach&lt;/strong&gt; statement is used to iterate through the collection to get the desired information, but should &lt;strong&gt;not&lt;/strong&gt; be used to change the contents of the collection to avoid unpredictable side effects.&lt;/em&gt; [emphasis mine]&lt;/p&gt;
&lt;p&gt;My colleague Kyle then came up with a terrific idea: just count backwards!  Start at the last member and iterate back to the first; and if a member is deleted, the loop still operates correctly.   So now our code looks like this:&lt;/p&gt;
&lt;div style="FONT-SIZE: 9pt; FONT-FAMILY: monospace; BACKGROUND-COLOR: white"&gt;&lt;span style="COLOR: blue"&gt;for&lt;/span&gt;&lt;span style="COLOR: black"&gt; (&lt;/span&gt;&lt;span style="COLOR: blue"&gt;int&lt;/span&gt;&lt;span style="COLOR: black"&gt; i = tbl.Rows.Count - 1; i &amp;gt;= 0; i--)&lt;br /&gt;
{&lt;br /&gt;
    &lt;/span&gt;&lt;span style="COLOR: green"&gt;// everything else is the same as before&lt;br /&gt;
&lt;/span&gt;&lt;span style="COLOR: black"&gt;}&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;You might not think the great programmers grow up in Appalachian hill country, but Kentucky Kyle has been full of pleasant surprises for us ever since we were astute enough to hire him.  Or maybe they just have to deal with field sobriety tests a lot more in the Kentucky hills.  Whatever the background, my hat is off to Kyle for his excellent idea.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=116713"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=116713" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/116713.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2007/11/08/116713.aspx</guid>
            <pubDate>Thu, 08 Nov 2007 11:44:40 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/116713.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2007/11/08/116713.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/116713.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/116713.aspx</trackback:ping>
        </item>
        <item>
            <title>Test-Driven Design: Make Sure You Fail!</title>
            <link>http://geekswithblogs.net/chrisfalter/archive/2007/10/20/116190.aspx</link>
            <description>&lt;p&gt;The idea behind test-driven design (TDD) is to incorporate testing into the process of constructing your system, rather than waiting for developers to check in their code and to build a system that someone else tests.  TDD has some advantages worth considering:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Defects are identified sooner in the development process, which makes delivery of a reliable system cheaper and quicker. &lt;/li&gt;
    &lt;li&gt;Developers have more scope to improve the quality of code by refactoring, since they can run unit tests as they are making changes to verify whether the system still behaves as expected. &lt;/li&gt;
    &lt;li&gt;Unit tests serve as built-in documentation on how to call and make use of interfaces. &lt;/li&gt;
    &lt;li&gt;This built-in documentation is guaranteed not to go out of date.  (You've never had the joy of working with out-of-date documentation, have you?  You haven't &lt;em&gt;lived&lt;/em&gt; until you've debugged some code whose documentation does not match.  Or perhaps I should say, you haven't worked in software development unless you've debugged, etc.) &lt;/li&gt;
    &lt;li&gt;A team can run unit tests in the final step of the build process, in order to verify that the new build has no obvious defects. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The test-driven design process goes like this:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Get the requirement from the customer. &lt;/li&gt;
    &lt;li&gt;Design a test suite that will verify that the requirement is satisfied. &lt;/li&gt;
    &lt;li&gt;Run the test suite and make sure it fails. &lt;/li&gt;
    &lt;li&gt;Write code and run the test suite until it succeeds. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When the test suite succeeds and there are no obvious ways to simplify the code, the developer performs his customary victory dance and checks in the code.&lt;/p&gt;
&lt;p&gt;I have incorporated TDD into the development process for some web services that have multiple customers.  If we did not have a more or less complete suite of unit tests, any modification would be hard to manage.  &lt;em&gt;Any&lt;/em&gt; codepath that &lt;em&gt;any&lt;/em&gt; customer relies on could have a regression when any code is changed, right?  So in the absence of TDD, &lt;em&gt;any&lt;/em&gt; modification would require that several testers (Pat, Tammy, and Charles at our office) spend a fair amount of their precious time running regression tests.  Consequently, I have created suites of unit tests to verify that no regressions have occurred, and have even given them names ("virtual Pat," "virtual Tammy," and "virtual Charles") .  Virtual Pat and her virtual colleagues are working hard so that the real Pat and her colleagues can head home at 5pm.  &lt;/p&gt;
&lt;p&gt;Recently I received a requirement to modify a service method so that it would return extra data.  After I revised the unit tests, I almost skipped over step #3 (make sure the test fails).  After all, I was in a hurry, and why bother?  Aren't my coding skills good enough to write a simple test?&lt;/p&gt;
&lt;p&gt;Evidently not.  &lt;/p&gt;
&lt;p&gt;I ran the test suite and &lt;em&gt;it did not fail.&lt;/em&gt;  I rubbed my eyes in disbelief and ran the suite again; of course, it succeeded again.   A quick glance at the tests showed that the test suite contained the extra data expected from the method, but I had failed to write the assertions that would compare the expected data with the actual data returned from the method.  So if the actual data returned from the method was not correct, the test (and the developer) would never know it.  Doh! &amp;lt;Sound of hand smacking forehead /&amp;gt; &lt;/p&gt;
&lt;p&gt;So I added the assertions, ran the test suite (Hurrah!  It failed!), wrote the new code, ran the test suite again, and it succeeded.  I checked in my code, and it's working as expected.&lt;/p&gt;
&lt;p&gt;The moral of this tale is simple: in test-driven design, you have to fail before you can succeed.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=116190"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=116190" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/chrisfalter/aggbug/116190.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Chris Falter</dc:creator>
            <guid>http://geekswithblogs.net/chrisfalter/archive/2007/10/20/116190.aspx</guid>
            <pubDate>Sat, 20 Oct 2007 18:39:53 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/chrisfalter/comments/116190.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/chrisfalter/archive/2007/10/20/116190.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/chrisfalter/comments/commentRss/116190.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/chrisfalter/services/trackbacks/116190.aspx</trackback:ping>
        </item>
    </channel>
</rss>