<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-4234347557302975420</atom:id><lastBuildDate>Tue, 21 Feb 2012 10:49:00 +0000</lastBuildDate><category>Tools</category><category>Book Review</category><category>Patterns</category><category>BlogEngine Experiment</category><category>Learning</category><category>Clean Code</category><category>Soft Skills</category><category>Workplace</category><category>WP7-Series</category><category>Refactoring</category><category>Recommendations</category><category>Apprenticeship</category><title>Dev|Adept Syndicated Feed</title><description>Better code. Better life.</description><link>http://blog.devadept.com/</link><managingEditor>noreply@blogger.com (Eric King)</managingEditor><generator>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/devadept" /><feedburner:info uri="devadept" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>33.606004</geo:lat><geo:long>-111.886999</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-sa/3.0/</creativeCommons:license><feedburner:emailServiceId>devadept</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-6551995164041305702</guid><pubDate>Sun, 29 Jan 2012 03:53:00 +0000</pubDate><atom:updated>2012-01-28T20:53:45.063-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">WP7-Series</category><title>WP7 Series Part 2: Ensuring Blendability with Dependency Injection</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-weFqLWrOlgk/TySpJe31jOI/AAAAAAAAADc/gsrpfAgVqdE/s1600/MVVM_Light_Logo.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="168" src="http://2.bp.blogspot.com/-weFqLWrOlgk/TySpJe31jOI/AAAAAAAAADc/gsrpfAgVqdE/s200/MVVM_Light_Logo.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;h2&gt;
Starting with MVVM&lt;/h2&gt;
&lt;br /&gt;
In &lt;a href="http://blog.devadept.com/2012/01/wp7-series-part-1-to-build-windows.html"&gt;WP7 Series Part 1&lt;/a&gt; I explained that I wanted to build a Windows Phone application using some basic MVVM principles to maintain 'Blendability'. After tinkering with some options, I've decided to use the &lt;a href="http://mvvmlight.codeplex.com/"&gt;MVVM Light Toolkit&lt;/a&gt; as the basic framework. It provides some good tools for the toolbox but doesn't otherwise drastically change how I code.&lt;br /&gt;
&lt;br /&gt;
After installing the toolkit and creating a new MVVMLight phone application, open the App.xaml file and you'll find an entry in the Application.Resources section that looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Application.Resources&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;lt;!--Global&amp;nbsp;View&amp;nbsp;Model&amp;nbsp;Locator--&amp;gt;&lt;/span&gt;
&lt;span style="color: #a31515;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ViewModel&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515;"&gt;ViewModelLocator&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: white; color: red;"&gt;x&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;:&lt;/span&gt;&lt;span style="background-color: white; color: red;"&gt;Key&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;=&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;"Locator"&lt;/span&gt;&lt;span style="background-color: white; color: red;"&gt;&amp;nbsp;
&lt;/span&gt;&lt;span style="background-color: white; color: red;"&gt;                                d&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;:&lt;/span&gt;&lt;span style="background-color: white; color: red;"&gt;IsDataSource&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;=&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;"True"&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;&amp;nbsp;/&amp;gt;
&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="background-color: white; color: #a31515;"&gt;Application.Resources&lt;/span&gt;&lt;span style="background-color: white; color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"&gt;&lt;span style="color: blue;"&gt;
&lt;/span&gt;&lt;/pre&gt;
This 'ViewModelLocator' is the heart of the MVVM Light framework and is meant to be used by every page to find its data context. It does so by assigning a property of the Locator resource to the page's context, like so (at the top of MainPage.xaml):&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"&gt;&lt;span style="color: red;"&gt;DataContext&lt;/span&gt;&lt;span style="color: blue;"&gt;="{&lt;/span&gt;&lt;span style="color: #a31515;"&gt;Binding&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;Main&lt;/span&gt;&lt;span style="color: blue;"&gt;,&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;Source&lt;/span&gt;&lt;span style="color: blue;"&gt;={&lt;/span&gt;&lt;span style="color: #a31515;"&gt;StaticResource&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;Locator&lt;/span&gt;&lt;span style="color: blue;"&gt;}}&lt;/span&gt;&lt;span style="color: blue;"&gt;"&lt;/span&gt;
&lt;/pre&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"&gt;&lt;span style="color: blue;"&gt;
&lt;/span&gt;&lt;/pre&gt;
This line basically says "bind my DataContext to the 'Main' property of the 'Locator' resource". Everything so far is great, and pretty straightforward. A quick look inside the ViewModelLocator.cs file shows that the 'Main' property is a static instance of the MainViewModel.cs class. I'm not going to go into the details of how the ViewModelLocator instanciates the ViewModels, though, because I don't particularly like how it works. I'll show my variation a bit farther down.&lt;br /&gt;
&lt;br /&gt;
Meanwhile, let's glance inside the MainViewModel.cs class. One of the first things I notice is the way DesignTime vs RunTime data is decided.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;MainViewModel()
{
    &lt;span style="color: blue;"&gt;if&lt;/span&gt;&amp;nbsp;(IsInDesignMode)
    {
        &lt;span style="color: green;"&gt;//&amp;nbsp;Code&amp;nbsp;runs&amp;nbsp;in&amp;nbsp;Blend&amp;nbsp;--&amp;gt;&amp;nbsp;create&amp;nbsp;design&amp;nbsp;time&amp;nbsp;data.&lt;/span&gt;
    }
    &lt;span style="color: blue;"&gt;else&lt;/span&gt;
    {
        &lt;span style="color: green;"&gt;//&amp;nbsp;Code&amp;nbsp;runs&amp;nbsp;"for&amp;nbsp;real"&lt;/span&gt;
    }
}&lt;/pre&gt;
&lt;br /&gt;
With this method, every ViewModel is going to have the same (or very similar) logic duplicated in its constructor. I'd rather have that logic centralized some place else, and have the ViewModel ignorant of its source of data (DesignTime or RunTime). It just uses whatever data it gets.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Enter Dependency Injection&lt;/h2&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-GnBT5quW1Ao/TyS1uij1KnI/AAAAAAAAADk/iOfE1QsXy_4/s1600/ninject-logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-GnBT5quW1Ao/TyS1uij1KnI/AAAAAAAAADk/iOfE1QsXy_4/s1600/ninject-logo.png" /&gt;&lt;/a&gt;&lt;/div&gt;
Back to the ViewModelLocator. Since the ViewModelLocator is where the ViewModel classes get instanciated, it seems an appropriate place to decide where to get the data for the ViewModels. I understand that the MVVM Light Toolkit may eventually include a small Inversion of Control container (called SimpleIoc), but I'm comfortable with &lt;a href="http://ninject.org/"&gt;Ninject&lt;/a&gt;, so that's what I ended up using. It takes just a few seconds to install Ninject using &lt;a href="http://nuget.org/packages/Ninject/2.2.1.4"&gt;NuGet&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
In 'Blendable' apps, the concepts of design-time data and run-time data are equally important, so I decided to treat design-time data as an integral part of my data access layer. I like using the &lt;a href="http://martinfowler.com/eaaCatalog/repository.html"&gt;Repository&lt;/a&gt; pattern, even though its popularity &lt;a href="http://ayende.com/blog/3955/repository-is-the-new-singleton"&gt;may be waning in some circles&lt;/a&gt;, so it makes sense that I should have both design-time and run-time data repositories available.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-DUYmQsBiZMw/TyS45R62_OI/AAAAAAAAADs/bG-y72nvibA/s1600/data_layer_folders.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-DUYmQsBiZMw/TyS45R62_OI/AAAAAAAAADs/bG-y72nvibA/s1600/data_layer_folders.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
After creating the repositories (as shown on the right, each implementing the IExampleRepository interface), I created Ninject modules for each of them.&amp;nbsp;You'll notice I created a ViewModelModule; I use that in the ViewModelLocator also.&lt;br /&gt;
&lt;br /&gt;
Now, returning to the ViewModelLocator, I can create a Ninject kernel, and add either the DesignTimeModule or the RunTimeModule depending on the same IsInDesignMode property that the MainViewModel was using. You can see that below in the BuildKernel() method.&lt;br /&gt;
&lt;br /&gt;
My ViewModelLocator now looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ViewModelLocator&lt;/span&gt;
{
    &lt;span style="color: blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;StandardKernel&lt;/span&gt;&amp;nbsp;_kernel;
 
    &lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;ViewModelLocator()
    {
        BuildKernel();
    }
 
    &lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;IMainViewModel&lt;/span&gt;&amp;nbsp;Main
    {
        &lt;span style="color: blue;"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;_kernel.Get&amp;lt;&lt;span style="color: #2b91af;"&gt;IMainViewModel&lt;/span&gt;&amp;gt;();&amp;nbsp;}
    }
 
    &lt;span style="color: blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt;&amp;nbsp;BuildKernel()
    {
        _kernel&amp;nbsp;=&amp;nbsp;&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;StandardKernel&lt;/span&gt;(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ViewModelModule&lt;/span&gt;());
 
        &lt;span style="color: blue;"&gt;if&lt;/span&gt;&amp;nbsp;(&lt;span style="color: #2b91af;"&gt;ViewModelBase&lt;/span&gt;.IsInDesignModeStatic)
        {
            _kernel.Load(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;DesignTimeDataModule&lt;/span&gt;());
        }
        &lt;span style="color: blue;"&gt;else&lt;/span&gt;
        {
            _kernel.Load(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;RunTimeDataModule&lt;/span&gt;());
        }
    }
}&lt;/pre&gt;
&lt;br /&gt;
The final piece of the puzzle comes into place by changing the MainViewModel so that it's constructor asks for an IExampleRepository to be injected. The ViewModel itself doesn't care whether it's design-time data or run-time data.
&lt;br /&gt;
&lt;br /&gt;
The MainViewModel now looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; font-family: Consolas; font-size: 13px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;MainViewModel&lt;/span&gt;&amp;nbsp;:&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ViewModelBase&lt;/span&gt;,&amp;nbsp;&lt;span style="color: #2b91af;"&gt;IMainViewModel&lt;/span&gt;
{
    &lt;span style="color: blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;readonly&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;IExampleRepository&lt;/span&gt;&amp;nbsp;_repository;
 
    &lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;MainViewModel(&lt;span style="color: #2b91af;"&gt;IExampleRepository&lt;/span&gt;&amp;nbsp;repository)
    {
        _repository&amp;nbsp;=&amp;nbsp;repository;
    }
 
    &lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;nbsp;ApplicationTitle
    {
        &lt;span style="color: blue;"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: #a31515;"&gt;"MVVM&amp;nbsp;LIGHT"&lt;/span&gt;;&amp;nbsp;}
    }
 
    &lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;nbsp;PageName
    {
        &lt;span style="color: blue;"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;&lt;span style="color: #a31515;"&gt;"My&amp;nbsp;page:"&lt;/span&gt;;&amp;nbsp;}
    }
 
    &lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;nbsp;Welcome
    {
        &lt;span style="color: blue;"&gt;get&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color: blue;"&gt;return&lt;/span&gt;&amp;nbsp;_repository.GetWelcomeMessage();&amp;nbsp;}
    }
}&lt;/pre&gt;
&lt;br /&gt;
The 'Welcome' message (displayed in the middle of the MainPage) is now retrieved through the injected repository, which may be either run-time or design-time data. The end result, in the emulator:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-Rzy7WISZTOU/TyS-cf_hiKI/AAAAAAAAAD0/4uuaGbjfJcc/s1600/run-time-screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/-Rzy7WISZTOU/TyS-cf_hiKI/AAAAAAAAAD0/4uuaGbjfJcc/s320/run-time-screenshot.png" width="192" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
In Visual Studio, design view :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-YTu-Xm8Axdc/TyS-1yhH9EI/AAAAAAAAAD8/jQA7mnsfrPA/s1600/vs-design-time.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/-YTu-Xm8Axdc/TyS-1yhH9EI/AAAAAAAAAD8/jQA7mnsfrPA/s400/vs-design-time.PNG" width="218" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
And, finally, in Expression Blend :&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-cdW8a72rqxE/TyS_WMAhW7I/AAAAAAAAAEE/qPSQa9fW24E/s1600/blend-design-time.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-cdW8a72rqxE/TyS_WMAhW7I/AAAAAAAAAEE/qPSQa9fW24E/s400/blend-design-time.PNG" width="235" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
So there you have it: one way of injecting design-time and run-time data into a ViewModel using the ViewModelLocator and Dependency Injection, with just a few changes to the out-of-the-box MVVM Light template.&lt;br /&gt;
&lt;br /&gt;
The code for this sample can be found at&amp;nbsp;&lt;a href="https://bitbucket.org/devadept/mvvmlightsample/"&gt;https://bitbucket.org/devadept/mvvmlightsample/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://blog.devadept.com/search/label/WP7-Series"&gt;Read all posts in the WP7-Series&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-6551995164041305702?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=zZQd_fvELCk:FmXjMW8igIQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=zZQd_fvELCk:FmXjMW8igIQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=zZQd_fvELCk:FmXjMW8igIQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=zZQd_fvELCk:FmXjMW8igIQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=zZQd_fvELCk:FmXjMW8igIQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/zZQd_fvELCk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/zZQd_fvELCk/wp7-series-part-2-ensuring-blendability.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-weFqLWrOlgk/TySpJe31jOI/AAAAAAAAADc/gsrpfAgVqdE/s72-c/MVVM_Light_Logo.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2012/01/wp7-series-part-2-ensuring-blendability.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-7681025716810304263</guid><pubDate>Fri, 27 Jan 2012 05:00:00 +0000</pubDate><atom:updated>2012-01-26T22:00:45.830-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">WP7-Series</category><title>WP7 Series Part 1: To build a Windows Phone 7 app</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-rsMdHfmL8FQ/TyIijgCpWYI/AAAAAAAAADI/aD1aK9iRKy0/s1600/hd7.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-rsMdHfmL8FQ/TyIijgCpWYI/AAAAAAAAADI/aD1aK9iRKy0/s200/hd7.png" width="141" /&gt;&lt;/a&gt;&lt;/div&gt;
And suddenly it's 2012... Where has the time gone?&amp;nbsp;&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: right;"&gt;
&lt;/div&gt;
&lt;div&gt;
It's a new year, and I've decided to take on a new challenge by building a Windows Phone 7 app. I've had my Windows phone (an &lt;a href="http://www.htc.com/us/products/hd7-tmobile/"&gt;HTC HD7&lt;/a&gt;) for over a year, and I absolutely love it. I've not written a XAML app yet, nor a mobile app, but I saw mention of the &lt;a href="http://www.30tolaunch.com/"&gt;30 to Launch&lt;/a&gt; challenge a week or so ago, and have decided to give it a try.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I've done the &lt;span style="background-color: #f3f3f3; font-family: 'Courier New', Courier, monospace;"&gt;File -&amp;gt; New Windows Phone Project&lt;/span&gt; a few times in the past year, but have never felt inspired enough to really delve into creating an app 'for realz', but one thing I do know: I don't want to use the standard out-of-the-box code-behind process. I really want to try to keep to an MVVM model and maintain good 'blendability'.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
To that extent, I've tried to do a little research up front to look at some options. I could go the route that &lt;a href="https://twitter.com/#!/kellabyte"&gt;@kellabyte&lt;/a&gt; had taken during her learning experience and &lt;a href="http://kellabyte.com/2011/07/24/refactoring-to-improve-maintainability-and-blendability-using-ioc-part-1-view-models/"&gt;write much of the framework myself&lt;/a&gt;. Or, I could try to leverage as much as possible a framework somebody else has written, like &lt;a href="http://www.caliburnproject.org/"&gt;Caliburn Micro&lt;/a&gt; or &lt;a href="http://mvvmlight.codeplex.com/"&gt;MVVM Light&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-IwiRKRTvo8E/TyIvTMSo77I/AAAAAAAAADQ/6Zv_xi_lYfw/s1600/WP7_Project.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="150" src="http://4.bp.blogspot.com/-IwiRKRTvo8E/TyIvTMSo77I/AAAAAAAAADQ/6Zv_xi_lYfw/s320/WP7_Project.PNG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
I watched several of the training videos on &lt;a href="http://www.pluralsight-training.net/microsoft/Courses#windows-phone-7"&gt;Pluralsight&lt;/a&gt;, followed by all of the&amp;nbsp;&lt;a href="http://channel9.msdn.com/Series/The-Full-Stack"&gt;Full Stack&lt;/a&gt; series of videos, plus a few others like Laurent Bugnion's &lt;a href="http://channel9.msdn.com/Events/MIX/MIX11/OPN03"&gt;Deep Dive MVVM&lt;/a&gt; video on &lt;a href="http://channel9.msdn.com/Tags/wp7"&gt;Channel 9&lt;/a&gt;. I've read through several tutorials, and browsed a bunch of open source code. I figure it's time to &lt;a href="https://plus.google.com/107153899732046384088/posts/KUdARsu88L6"&gt;get off my butt and write some code&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
So, after playing around with a few options, I've settled on a basic app structure that I'm happy with, that uses MVVM Light and Ninject at the core, along with a repository pattern wrapped around SQL CE for data. It allows for easy display of design-time-data in Blend, and adheres to MVVM very well. I'll explain more about the structure in my next post.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href="http://blog.devadept.com/search/label/WP7-Series"&gt;Read all posts in the WP7-Series&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-7681025716810304263?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=V-yZi3HGL7Q:bYxMKfKHiXI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=V-yZi3HGL7Q:bYxMKfKHiXI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=V-yZi3HGL7Q:bYxMKfKHiXI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=V-yZi3HGL7Q:bYxMKfKHiXI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=V-yZi3HGL7Q:bYxMKfKHiXI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/V-yZi3HGL7Q" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/V-yZi3HGL7Q/wp7-series-part-1-to-build-windows.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-rsMdHfmL8FQ/TyIijgCpWYI/AAAAAAAAADI/aD1aK9iRKy0/s72-c/hd7.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2012/01/wp7-series-part-1-to-build-windows.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-577209859088843365</guid><pubDate>Sat, 06 Aug 2011 22:36:00 +0000</pubDate><atom:updated>2011-08-06T15:36:15.747-07:00</atom:updated><title>The organizational mindshift of Agile</title><description>Quite often, adopting Agile requires organizations to change more than expected, and sometimes more than the organizations are willing. I don't think that organizational leaders understand that Agile is not a set of practices or tools from which they can pick and choose, instantly transforming them into an '&lt;a href="http://en.wikipedia.org/wiki/Business_agility"&gt;Agile Organization&lt;/a&gt;'.&lt;br /&gt;
&lt;br /&gt;
Instead, &lt;a href="http://agilemanifesto.org/"&gt;Agile is a set of values&lt;/a&gt;; often the values are foreign to those the organization has long held. Embracing these values requires adopting some new practices and tools, for certain, but it must be the &lt;i&gt;values&lt;/i&gt; driving the change, not the tools.&lt;br /&gt;
&lt;br /&gt;
I listened to &lt;a href="http://agiletoolkit.libsyn.com/path-to-agility-2011-kelly-allen-deming-then-now-and-for-the-foreseeable-future"&gt;an episode&lt;/a&gt; of the &lt;a href="http://agiletoolkit.libsyn.com/"&gt;Agile Toolkit Podcast&lt;/a&gt; the other day, in which host &lt;a href="http://www.electroglide.biz/"&gt;Bob Payne&lt;/a&gt;&amp;nbsp;and &lt;a href="http://www.kellyallan.com/kelly.html"&gt;Kelly Allan&lt;/a&gt; discuss Agile and its relationship to &lt;a href="http://en.wikipedia.org/wiki/W._Edwards_Deming"&gt;W. Edwards Deming&lt;/a&gt;'s management teachings. At about the 12:00 minute mark, this exchange discusses how much change an Agile transition demands from a traditional, conservative organization:&lt;br /&gt;
&lt;blockquote&gt;
Kelly - Agile, I think, will help drive even more of Deming's thinking into, and I hope will drive out a lot of the prevailing notions of management as it's practiced.&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote&gt;
Bob - Yep.&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote&gt;
Kelly - So, what do I mean by that? In part, certain practices like pay for&amp;nbsp;performance and performance appraisals, incentives and rewards and driving in fear&amp;nbsp;and management by quota and management by results and these kinds of things, have no&amp;nbsp;place in the Agile world. Agile rejects that.&lt;/blockquote&gt;
&lt;blockquote&gt;
Bob - We try.&lt;br /&gt;
&lt;br /&gt;
Kelly - Yes. The rest of the organization, of course, is still stuck in that old&amp;nbsp;management model. So Agile picked up all those things by - so, for example, Deming&amp;nbsp;calls the annual performance appraisal one of the 'deadly diseases' that he lists.&amp;nbsp;His eighth point is 'drive out fear from the organization'. Because if there's fear&amp;nbsp;in the organization, you tamp down innovation, you tamp down experimentation, you&amp;nbsp;tamp down new product development.&lt;/blockquote&gt;
Those words, "they have no place in the Agile world", are pretty strong. And I agree with them. But I don't think many business leaders understand how strong the Agile values are when they say they're ready to transition to Agile. What they are &lt;i&gt;wanting&lt;/i&gt; is to change a few things here and there, holding their core (often anti-Agile) values steady, and claim victory. They expect software to somehow get built better and faster, as if through some sort of magic applied with the Agile label.&lt;br /&gt;
&lt;br /&gt;
In reality, the management practices of the past are simply dressed up to look like Agile, and continue to be applied as before. See, change is not so hard!&lt;br /&gt;
&lt;br /&gt;
In his book &lt;a href="http://www.amazon.com/gp/product/0596527675/ref=as_li_tf_tl?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399369&amp;amp;creativeASIN=0596527675"&gt;The Art of Agile Development&lt;/a&gt;, author &lt;a href="http://jamesshore.com/"&gt;James Shore&lt;/a&gt; has this to say about the common practice of reporting time usage to management:&lt;br /&gt;
&lt;blockquote&gt;
If the project is under time pressure - and projects usually are - stakeholders may want to know that the team is using its time wisely. Often, when the team mentions its velocity, stakeholders question it. "Why does it take 6 programmers a week to finish 12 days worth of work? Shouldn't they finish 30 days of work in that time?"&lt;/blockquote&gt;
&lt;blockquote&gt;
Although I prefer that stakeholders trust the team to schedule its tasks wisely, that trust takes time to develop. In the beginning, I often produce a report that shows how the programmers are using there time. This report requires that programmers track their time in detail, so I stop producing it as soon as possible, typically after a month or two.&lt;/blockquote&gt;
In other words, this report, which has probably been a staple report for the organization over the years, is foreign to Agile, which values &lt;i&gt;trusting your team&lt;/i&gt; over &lt;i&gt;requiring the team to track time.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
To the Agile mind, this time-tracking is &lt;i&gt;waste,&lt;/i&gt; as it doesn't lead to working software; in fact it delays the working software. In the Agile point of view, this waste shows that the organization's Agile implementation is &lt;i&gt;broken&lt;/i&gt;, and Agile itself demands that it get fixed.&lt;br /&gt;
&lt;br /&gt;
An organization that isn't ready to consider that these practices and processes are broken, that isn't ready to consider rejecting them as Agile does, is simply not ready for Agile.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-577209859088843365?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=SuHo7og32jc:D5qHXqvczBo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=SuHo7og32jc:D5qHXqvczBo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=SuHo7og32jc:D5qHXqvczBo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=SuHo7og32jc:D5qHXqvczBo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=SuHo7og32jc:D5qHXqvczBo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/SuHo7og32jc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/SuHo7og32jc/organization-mindshift-of-agile.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2011/08/organization-mindshift-of-agile.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-5567596790736004185</guid><pubDate>Fri, 22 Jul 2011 03:14:00 +0000</pubDate><atom:updated>2011-07-21T20:14:50.166-07:00</atom:updated><title>Agile and the Power of Feedback Loops</title><description>Last month I came across a great article on Wired Magazine titled "&lt;a href="http://www.wired.com/magazine/2011/06/ff_feedbackloop/all/1"&gt;Harnessing the Power of Feedback Loops&lt;/a&gt;". It reminded me of the importance of one of the basic tenets of Agile programming methodologies, extremely short feedback loops.&lt;br /&gt;
&lt;blockquote&gt;
The potential of the feedback loop to affect behavior was explored in the 1960s, most notably in the work of Albert Bandura, a Stanford University psychologist and pioneer in the study of behavior change and motivation. Drawing on several education experiments involving children, Bandura observed that giving individuals a clear goal and a means to evaluate their progress toward that goal greatly increased the likelihood that they would achieve it. He later expanded this notion into the concept of self-efficacy, which holds that the more we believe we can meet a goal, the more likely we will do so.&lt;/blockquote&gt;
Many times I've seen 'agility' (as it pertains to software development) defined in terms of implementing certain processes and disciplines, or sometimes the lack of disciplines altogether. If you institute a two-week 'sprint', you must be Agile, right? Got a burndown chart? Agile. Don't like documentation? Skip it, and be more Agile!&lt;br /&gt;
&lt;br /&gt;
That misses the point. The way I see it, the single most important aspect of software development agility is &lt;i&gt;feedback&lt;/i&gt;. In a truly agile environment, we see feedback loops everywhere. The point of a short work cycle, whether you call them sprints or iterations, or forego them completely with the continuous pull of kanban, is to keep the feedback coming. Daily stand-up? All about meaningful feedback. Pair programming provides the ultimate real-time collaborative feedback between two programmers. Fast running automated unit tests? Feedback.&lt;br /&gt;
&lt;blockquote&gt;
Why does putting our own data in front of us somehow compel us to act? In part, it’s that feedback taps into something core to the human experience, even to our biological origins. Like any organism, humans are self-regulating creatures, with a multitude of systems working to achieve homeostasis. Evolution itself, after all, is a feedback loop, albeit one so elongated as to be imperceptible by an individual. Feedback loops are how we learn, whether we call it trial and error or course correction. In so many areas of life, we succeed when we have some sense of where we stand and some evaluation of our progress. Indeed, we tend to crave this sort of information; it’s something we viscerally want to know, good or bad. As Stanford’s Bandura put it, “People are proactive, aspiring organisms.” Feedback taps into those aspirations.&lt;/blockquote&gt;
It's important to remember, as we put in place all of these processes and tools and practices and policies to become 'agile', that the point of them all is to provide the feedback that we as humans are hard-wired to respond to. Feedback is the secret sauce of agile.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-5567596790736004185?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=o8rY0fBH6KA:654kpewXIfc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=o8rY0fBH6KA:654kpewXIfc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=o8rY0fBH6KA:654kpewXIfc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=o8rY0fBH6KA:654kpewXIfc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=o8rY0fBH6KA:654kpewXIfc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/o8rY0fBH6KA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/o8rY0fBH6KA/agile-and-power-of-feedback-loops.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2011/07/agile-and-power-of-feedback-loops.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-2641649292036907115</guid><pubDate>Sun, 11 Jul 2010 18:28:00 +0000</pubDate><atom:updated>2010-07-11T11:28:16.944-07:00</atom:updated><title>How I Learn</title><description>In the &lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/podcast/#episode11"&gt;11th episode of the 37signals Podcast&lt;/a&gt;, a listener asks a question of Jason Fried and David Heinemeier Hansson (at the 15:30 mark):&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;Q&lt;/b&gt;: Michael Hopkins would like to hear about what your team does to learn.&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;A&lt;/b&gt;: [Jason] Some people go to conferences, other people just pay attention and observe things. I think that's the best way to learn, just to stay focused on your industry in some ways and see what everyone else is doing and pay attention to the right news sources and learn stuff that way, and to just try it out. That's really the best way to learn anything, to try it and to experiment with stuff.&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;b&gt;A&lt;/b&gt;: [David] My approach is basically... Whenever I get annoyed about something, that's when I learn. So, I'm annoyed about how a technical process works or something else works, and I don't necessarily know right now how to fix this, so I gotta find out how to fix it. So I gotta learn whatever skills I need to pick up or patterns or whatever else, what have you, to fix things that bug me.&lt;/blockquote&gt;Hearing their answers sparked the question in me ... what do &lt;i&gt;I&lt;/i&gt;&amp;nbsp;do to learn?&lt;br /&gt;
&lt;br /&gt;
I really identify with Jason's answer. In many respects, I'm an observer. I like listening, watching, observing, being &lt;i&gt;aware&lt;/i&gt;. Taking the time to reason things out. Seeing how others reason. It's how I absorb facts and ideas.&lt;br /&gt;
&lt;br /&gt;
Really learning a topic requires more than one type of observation style, though. Simply reading a book isn't enough. My best learning comes when I combine different observation styles. So, I've developed a multi-pronged learning attack:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Read&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
There's no shortage of informative, thoughtful, quality reading material out there. Lately I've found myself on a sort of reading renaissance, renewing my childhood love of reading. In the past year or two I've made a concerted effort to maintain a constant reading schedule. I've tried to keep a good mix of fiction and non-fiction, technical and non-technical, purposeful and frivolous. I find that the mere act of reading helps keep the mind engaged. &lt;a bitly="BITLY_PROCESSED" href="http://library.scottsdaleaz.gov/"&gt;The library&lt;/a&gt; is my friend (Remember libraries? Yes, they still exist.)&lt;br /&gt;
&lt;br /&gt;
As for software development, there are a ton of good books out there, from classics like &lt;a href="http://cc2e.com/"&gt;Code Complete&lt;/a&gt;, &lt;a href="http://www.amazon.com/dp/0262510871"&gt;&lt;/a&gt;&lt;a href="http://www.amazon.com/Structure-Interpretation-Computer-Programs-Engineering/dp/0262011530?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=0262011530" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /&gt;, and &lt;a href="http://www.amazon.com/dp/0201633612/"&gt;&lt;/a&gt;&lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=0201633612" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /&gt;, to new(er) gems like &lt;a href="http://www.pragprog.com/titles/tpp/the-pragmatic-programmer"&gt;&lt;/a&gt;&lt;a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;The Pragmatic Programmer&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=020161622X" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /&gt;,&amp;nbsp;&lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=0132350882" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /&gt;, and&amp;nbsp;&lt;a href="http://www.amazon.com/Passionate-Programmer-Remarkable-Development-Pragmatic/dp/1934356344?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;The Passionate Programmer: Creating a Remarkable Career in Software Development (Pragmatic Life)&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=1934356344" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /&gt;. For more inspiration, there's a &lt;a href="http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read"&gt;good list of must-read programming books on stackoverflow&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
But books aren't the only thing to read. I can't think of a better way to keep up-to-date with the software development industry than a &lt;a bitly="BITLY_PROCESSED" href="http://www.google.com/reader/"&gt;good RSS feed reader&lt;/a&gt; and a good list of technical blogs. Develop a reading schedule and maintain some discipline, or else productive reading can quickly turn to wasted time.&lt;br /&gt;
&lt;br /&gt;
Lastly, read source code. There is an abundance of good open-source software out there. Check out &lt;a href="http://code.google.com/hosting/"&gt;Google Code&lt;/a&gt;, &lt;a href="http://www.codeplex.com/"&gt;Codeplex&lt;/a&gt;, and &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt;&amp;nbsp;to start.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Listen&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
I've become a real fan of podcasts. There's no better way for a wallflower like me to listen in on conversations between interesting people discussing interesting topics. Whether it's &lt;a bitly="BITLY_PROCESSED" href="http://www.hanselminutes.com/default.aspx?showID=226"&gt;Scott Hanselman talking about the business of social media&lt;/a&gt; or &lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/podcast/#episode7"&gt;37signals talking about their design process&lt;/a&gt; or &lt;a bitly="BITLY_PROCESSED" href="http://itc.conversationsnetwork.org/series/stackoverflow.html"&gt;Jeff and Joel shooting the breeze about StackOverflow&lt;/a&gt;, these are conversations that are going to happen anyway, but we are invited to listen in. You're missing out if you don't. Check out my &lt;a href="http://blog.devadept.com/p/podcasts.html"&gt;list of favorite podcasts&lt;/a&gt; it you're looking for a place to start. It's a great way to make your commute productive.&lt;br /&gt;
&lt;br /&gt;
Audio books are a good hybrid of the Read and Listen styles. Books that teach programming techniques probably don't translate well to the audio format, but books &lt;i&gt;about&lt;/i&gt;&amp;nbsp;the programming industry do. Again, the &lt;a href="http://phoenix.lib.overdrive.com/"&gt;public library&lt;/a&gt; is your friend. There's a ton of content out there that won't cost you a penny to absorb.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Watch&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
They say sometimes a picture is worth a thousand words. I'm constantly amazed at the amount and quality of video content that's available on the Internet. Sometimes it's one man behind hundreds of video courses (&lt;a href="http://www.khanacademy.org/"&gt;Khan Academy&lt;/a&gt;), other times it's an Ivy League university (&lt;a href="http://ocw.mit.edu/courses/audio-video-courses/"&gt;MIT OpenCourseWare&lt;/a&gt;). It might be a mind-opening talk like&amp;nbsp;&lt;a href="http://vimeo.com/5895898"&gt;Seth Godin&amp;nbsp;on quieting the lizard brain&lt;/a&gt;&amp;nbsp;or &lt;a href="http://www.ted.com/talks/malcolm_gladwell_on_spaghetti_sauce.html"&gt;Malcolm Gladwell on spaghetti sauce&lt;/a&gt;. There's a ton of vendor-provided how-to videos like &lt;a href="http://www.asp.net/mvc/videos"&gt;ASP.NET MVC Video Tutorials&lt;/a&gt;&amp;nbsp;and &lt;a href="http://rubyonrails.org/screencasts"&gt;Ruby on Rails Screencasts&lt;/a&gt;. If you can't attend big conferences, many of them record their sessions and provide the content online, like &lt;a href="http://live.visitmix.com/Videos"&gt;Microsoft Mix&lt;/a&gt; and &lt;a href="http://railsconf.blip.tv/"&gt;RailsConf&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Paid video learning content can also be very useful. I've recently subscribed to &lt;a href="http://www.tekpub.com/"&gt;TekPub&lt;/a&gt;, which has videos on subjects ranging from &lt;a href="http://www.tekpub.com/production/aspmvc"&gt;ASP.NET MVC2&lt;/a&gt; to &lt;a href="http://www.tekpub.com/production/hg"&gt;Mecurial&lt;/a&gt;&amp;nbsp;to &lt;a href="http://www.tekpub.com/production/sinatra"&gt;Sinatra&lt;/a&gt;&amp;nbsp;and more. To get a feel for what the paid content is like, check out their &lt;b&gt;free &lt;/b&gt;&lt;a href="http://www.tekpub.com/production/coder"&gt;Coder to Developer&lt;/a&gt; series.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Discuss&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
After reading, hearing, and seeing so much great content, you're bound to have questions and ideas and opinions bounding around in your head. Let them out. Talk about them.&lt;br /&gt;
&lt;br /&gt;
The most obvious place to do so is in your workplace. Strike up a conversation with your development team during your next team meeting or around the water cooler. Set up a "developer day" to get the team together and explore ways of improving processes or integrating new technologies. However you can, the important thing is to get the discussions flowing.&lt;br /&gt;
&lt;br /&gt;
There are plenty of opportunities outside of work, too. &lt;a href="http://azgroups.org/"&gt;Local user groups&lt;/a&gt; are an obvious option. But there are also online discussions available on sites like &lt;a href="http://groups.google.com/groups/dir?sel=topic%3D46479.46475,lang%3Den&amp;amp;"&gt;Google Groups&lt;/a&gt;, &lt;a href="http://tech.dir.groups.yahoo.com/dir/1600006764"&gt;Yahoo! Groups&lt;/a&gt;, &amp;nbsp;and&amp;nbsp;&lt;a href="http://www.linkedin.com/home?myGroups=&amp;amp;trk=hb_side_mygrps"&gt;LinkedIn&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A great place to ask programming questions is &lt;a href="http://stackoverflow.com/"&gt;StackOverflow&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Teach&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
You never know how much you really understand a subject until you (try to) teach it to somebody else. Sometimes it can be humbling, but it's always rewarding. The very act of &lt;i&gt;preparing to teach&lt;/i&gt; will lead to a higher understanding the topic.&lt;br /&gt;
&lt;br /&gt;
It's not hard to get started teaching. Here are a few ideas:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Volunteer to give a presentation to your coworkers, or perhaps to a local user group.&lt;/li&gt;
&lt;li&gt;Lead a design session that integrates a technique or tool you've just learned.&lt;/li&gt;
&lt;li&gt;Log on to &lt;a href="http://stackoverflow.com/"&gt;StackOverflow&lt;/a&gt; and answer some questions.&lt;/li&gt;
&lt;li&gt;Teach a child how to make a simple game using &lt;a href="http://scratch.mit.edu/"&gt;Scratch &lt;/a&gt;or &lt;a href="http://alice.org/"&gt;Alice&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Volunteer at your local school or community center to teach a beginner's programming class&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;b&gt;Do&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Most importantly, use what you learn. Build things. There's no substitute for hands-on experience.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-2641649292036907115?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=iQale2jfGl8:EAAYV5bb1eU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=iQale2jfGl8:EAAYV5bb1eU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=iQale2jfGl8:EAAYV5bb1eU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=iQale2jfGl8:EAAYV5bb1eU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=iQale2jfGl8:EAAYV5bb1eU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/iQale2jfGl8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/iQale2jfGl8/how-i-learn.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.devadept.com/2010/07/how-i-learn.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-7518697526139944658</guid><pubDate>Thu, 08 Jul 2010 22:10:00 +0000</pubDate><atom:updated>2010-07-08T15:11:46.237-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Soft Skills</category><category domain="http://www.blogger.com/atom/ns#">Recommendations</category><category domain="http://www.blogger.com/atom/ns#">Patterns</category><category domain="http://www.blogger.com/atom/ns#">Learning</category><category domain="http://www.blogger.com/atom/ns#">Book Review</category><category domain="http://www.blogger.com/atom/ns#">Apprenticeship</category><title>Improve Your Software Craftsmanship with Apprenticeship Patterns</title><description>&lt;a href="http://www.amazon.com/Apprenticeship-Patterns-Guidance-Aspiring-Craftsman/dp/0596518382?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=bil&amp;amp;camp=213689&amp;amp;creative=392969" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;" target="_blank"&gt;&lt;img alt="Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman" src="http://ws.amazon.com/widgets/q?MarketPlace=US&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;ASIN=0596518382&amp;amp;tag=devadept-20" /&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-family: Arial; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;I feel that software development, at least the customer-facing business application type of development that I do, &lt;a href="http://en.wikipedia.org/wiki/Software_craftsmanship"&gt;is a craft&lt;/a&gt;. Although my current official job title is "Software Engineer", I feel less like an &lt;a href="http://en.wikipedia.org/wiki/Engineer"&gt;engineer&lt;/a&gt; and more like a &lt;a href="http://en.wikipedia.org/wiki/Master_craftsman"&gt;craftsman&lt;/a&gt;.&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;There has &lt;a href="http://www.codinghorror.com/blog/2009/07/software-engineering-dead.html"&gt;already been much debate&lt;/a&gt; about this distinction, and I won't repeat it all here. But suffice it to say that the critical difference, to me, lies in how one should go about &lt;i&gt;getting better&lt;/i&gt; at their particular flavor of software programming. I tend to agree with &lt;a href="http://c2.com/cgi/wiki?ArtCraftEngineeringScience"&gt;this assessment&lt;/a&gt; of the continuum of software programming as it relates to the concepts of "art", "craft", "engineering", and "science":&lt;/div&gt;&lt;blockquote&gt;Programming is rarely a science, sometimes engineering, but usually a craft. No example of programming-as-science comes to mind, but there is certainly a lot of science going into programming (codify natural laws found by science, and you have a simulator). Programming is an engineering discipline when the goal is not to add new functionality, but to make existing functionality work to certain quantitative goals. A lot of OS design and database work, for instance, is engineering. Making new functionality is usually a craft, where the result isn't getting something to work at such-and-such a speed but getting something to work&amp;nbsp;&lt;em&gt;at all&lt;/em&gt;.&lt;/blockquote&gt;If the types of programs you write tend to be farther to the engineering side of the spectrum, concentrating on speed, efficiency, scalability, interoperability and other quantitative goals, how do you improve your skills? Generally, you increase your algorithmic vocabulary by learning or inventing new algorithmic techniques, or you devise clever ways to harness existing methods in unique and powerful ways. This is mostly an academic exercise, and can be accomplished with traditional educational practices.&lt;br /&gt;
&lt;br /&gt;
But what if your programs&amp;nbsp;are more aligned with &lt;i&gt;qualitative&lt;/i&gt;&amp;nbsp;goals? What if the success of your software depends more on being &lt;i&gt;understandable&lt;/i&gt; and &lt;i&gt;easy to use&lt;/i&gt; than on being ultra-fast or efficient or (gasp) bug free? How do you get better at &lt;i&gt;that&lt;/i&gt;? For most of the software that I write, the success of the software depends much more on the qualitative aspects than the quantitative (assuming the engineering quality is reasonable, of course). In my experience, improving one's ability to be successful with that kind of software has shown to be more about &lt;i&gt;practice&lt;/i&gt;&amp;nbsp;than about &lt;i&gt;education&lt;/i&gt;. You improve the same way you would improve in any other&lt;i&gt;&amp;nbsp;&lt;/i&gt;craft.&lt;br /&gt;
&lt;br /&gt;
I recently came across the book &lt;a href="http://oreilly.com/catalog/9780596518387/"&gt;Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman&lt;/a&gt;.&lt;br /&gt;
&lt;blockquote&gt;Are you doing all you can to further your career as a software developer? With today's rapidly changing and ever-expanding technologies, being successful requires more than technical expertise. To grow professionally, you also need soft skills and effective learning techniques. Honing those skills is what this book is all about. Authors &lt;a href="http://nuts.redsquirrel.com/"&gt;Dave Hoover&lt;/a&gt; and &lt;a href="http://blog.oshineye.com/"&gt;Adewale Oshineye&lt;/a&gt; have cataloged dozens of behavior patterns to help you perfect essential aspects of your craft.&lt;/blockquote&gt;The authors&amp;nbsp;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=bil&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=0596518382" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /&gt;recognize that the most effective way of honing a craft is through the process of apprenticeship. In&amp;nbsp;lieu of a traditional apprenticeship&amp;nbsp;(does anybody know of one?), it is up to you to provide one for yourself. Steps for doing so are provided in the book.&lt;br /&gt;
&lt;br /&gt;
The best part, though, is that you don't even have to buy the book to see what those steps are. The entire contents are freely available through the publisher's website at&amp;nbsp;&lt;a href="http://apprenticeship-patterns.labs.oreilly.com/"&gt;http://apprenticeship-patterns.labs.oreilly.com/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
There you will find advice on how to:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Unleash Your Enthusiasm&lt;/li&gt;
&lt;li&gt;Confront Your Ignorance&lt;/li&gt;
&lt;li&gt;Retreat Into Competence&lt;/li&gt;
&lt;li&gt;Nurture Your Passion&lt;/li&gt;
&lt;li&gt;Find Mentors&lt;/li&gt;
&lt;li&gt;Be the Worst&lt;/li&gt;
&lt;li&gt;Share What You Learn&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;and many other patterns to follow on the road to mastery over your craft. Each pattern is presented with its relevant context, what problem the pattern solves, and specific actions you, the apprentice, can take. From the preface:&lt;/div&gt;&lt;blockquote&gt;This book is written for the person who has had a taste of software development and aspires to become a great software developer. You may be a web developer or a medical device programmer, or you may be building trading applications for a financial institution. Or perhaps you have just graduated from high school or college knowing that software is your future.&lt;br /&gt;
&lt;br /&gt;
Although this book was written for newcomers, more experienced developers will benefit from its content as well. People with several years of experience may find themselves nodding their heads in recognition of dilemmas they’ve already faced, and may come away with new insights or at least a new vocabulary to describe the solutions they want to apply for themselves or suggest to their colleagues. Even people with a decade or more of experience—particularly those who may be struggling to navigate their careers—will find inspiration and perspective to counter the siren call of promotion to management.&lt;/blockquote&gt;If that describes you, then you owe it to yourself to (at least) give the online version a look.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-7518697526139944658?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=PoqaAyAphd8:R6ThO0cylIs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=PoqaAyAphd8:R6ThO0cylIs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=PoqaAyAphd8:R6ThO0cylIs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=PoqaAyAphd8:R6ThO0cylIs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=PoqaAyAphd8:R6ThO0cylIs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/PoqaAyAphd8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/PoqaAyAphd8/improve-your-software-craftsmanship.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/07/improve-your-software-craftsmanship.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-8131383968735668134</guid><pubDate>Sun, 28 Mar 2010 23:44:00 +0000</pubDate><atom:updated>2010-04-01T13:56:02.398-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Recommendations</category><category domain="http://www.blogger.com/atom/ns#">Book Review</category><title>Book Review: Linchpin</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_R9uCU3ijWHE/S6_VTaU-iJI/AAAAAAAAADE/aJAQIPOdFEg/s1600-h/linchpin.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_R9uCU3ijWHE/S6_VTaU-iJI/AAAAAAAAADE/aJAQIPOdFEg/s320/linchpin.jpg" width="260" /&gt;&lt;/a&gt;&lt;/div&gt;I started reading&amp;nbsp;&lt;a href="http://www.amazon.com/Linchpin-Are-Indispensable-Seth-Godin/dp/1591843162?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;&lt;i&gt;Linchpin: Are You Indispensable?&lt;/i&gt;&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=1591843162" style="border-bottom-style: none !important; border-color: initial !important; border-left-style: none !important; border-right-style: none !important; border-top-style: none !important; border-width: initial !important; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;" width="1" /&gt;&amp;nbsp;by Seth Godin about the same time as I began reading &lt;i&gt;Rework&lt;/i&gt;, which&lt;a href="http://blog.devadept.com/2010/03/book-review-rework.html"&gt; I reviewed in a previous post&lt;/a&gt;. So, my reaction to each book will naturally be flavored by my experience with the other.&lt;br /&gt;
&lt;br /&gt;
While &lt;i&gt;Rework&lt;/i&gt;&amp;nbsp;is a short, quick read, &lt;i&gt;Linchpin&lt;/i&gt;&amp;nbsp;is much more substantial, although still an acceptable 230 pages or so. While &lt;i&gt;Rework&lt;/i&gt;&amp;nbsp;shows us how a business can be run effectively with unconventional means, &lt;i&gt;Linchpin&lt;/i&gt;&amp;nbsp;tells us how to be successful and unconventional individuals.&lt;br /&gt;
&lt;br /&gt;
The best summary of the message of &lt;i&gt;Linchpin&lt;/i&gt;&amp;nbsp;can be found on page 174:&lt;br /&gt;
&lt;blockquote&gt;You must become indispensable to thrive in the new economy. The best ways to do that are to be remarkable, insightful, an artist, someone bearing gifts. To lead. The worst way is to conform and become a cog in a giant system.&lt;/blockquote&gt;This is, at some level, rather obvious. Seth spends a lot of time explaining the &lt;a href="http://en.wikipedia.org/wiki/Gift_economy"&gt;gift economy&lt;/a&gt;&amp;nbsp;and the &lt;a href="http://sethgodin.typepad.com/seths_blog/2010/01/quieting-the-lizard-brain.html"&gt;lizard brain&lt;/a&gt;&amp;nbsp;and what he means by &lt;a href="http://sethgodin.typepad.com/seths_blog/2010/01/making-art.html"&gt;making art&lt;/a&gt;. And all of this is pretty good stuff. But what it all comes down to is this: If you want to succeed as an employee, as an employer, as a &lt;i&gt;person&lt;/i&gt;, you&amp;nbsp;need to stand out from the crowd by exceeding expectations and giving freely your best work, even if less will do. Hardly earth-shattering stuff, but worth repeating.&lt;br /&gt;
&lt;br /&gt;
As &lt;a href="http://blog.penelopetrunk.com/2010/02/15/almost-a-review-of-seth-godins-book-linchpin/"&gt;Penelope Trunk of Brazen Careerist says&lt;/a&gt;:&lt;br /&gt;
&lt;blockquote&gt;He is right. Of course. Seth is always right. The problem with all of Seth’s books is that he sets the bar so high with every one of them.&lt;/blockquote&gt;Another problem with his books is that he rarely tells you &lt;i&gt;how&lt;/i&gt;&amp;nbsp;he thinks you can achieve those very high bars. &amp;nbsp;Just that you need to meet them. Somehow. This is a problem that Seth himself mentions in &lt;i&gt;Linchpin&lt;/i&gt;.&lt;br /&gt;
&lt;blockquote&gt;One of my favorite negative reviews of my book &lt;i&gt;Tribes&lt;/i&gt;:&lt;/blockquote&gt;&lt;blockquote&gt;"Godin doesn't explain how to go about doing the actual hard groundwork of leadership. He makes it sound like anyone with an idea and &amp;nbsp;a cell phone can rally thousands of people to their cause in minutes if they just realize it's not hard"&lt;/blockquote&gt;&lt;blockquote&gt;My response: Telling people leadership is important is one thing. Showing them step by step precisely how to be a leader is impossible.&lt;/blockquote&gt;&lt;i&gt;Linchpin&lt;/i&gt;&amp;nbsp;works the same way. He tells you that being indispensable is important, and why, but stops short of telling you how. That would be impossible. Which makes &lt;i&gt;Linchpin&lt;/i&gt; much more of a "get off your butt and do something" inspirational-style book than a "here's a bunch of things you can do to make your life better" self-help book.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-8131383968735668134?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=Glj7Rjxe0c8:eW802OCwjRI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=Glj7Rjxe0c8:eW802OCwjRI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=Glj7Rjxe0c8:eW802OCwjRI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=Glj7Rjxe0c8:eW802OCwjRI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=Glj7Rjxe0c8:eW802OCwjRI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/Glj7Rjxe0c8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/Glj7Rjxe0c8/book-review-linchpin.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_R9uCU3ijWHE/S6_VTaU-iJI/AAAAAAAAADE/aJAQIPOdFEg/s72-c/linchpin.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/03/book-review-linchpin.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-2097977229550846735</guid><pubDate>Sun, 14 Mar 2010 05:48:00 +0000</pubDate><atom:updated>2010-03-13T22:48:54.744-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Recommendations</category><category domain="http://www.blogger.com/atom/ns#">Book Review</category><title>Book Review: Rework</title><description>&lt;div style="clear: both; float: right; margin: 0px 15px 15px 15px;"&gt;&lt;br /&gt;
&lt;a bitly="BITLY_PROCESSED" href="http://www.amazon.com/Rework-Jason-Fried/dp/0307463745?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=bil&amp;amp;camp=213689&amp;amp;creative=392969" imageanchor="1" target="_blank"&gt;&lt;img alt="Rework" src="http://1.bp.blogspot.com/_R9uCU3ijWHE/S5xayeCn0wI/AAAAAAAAACk/xz7S1o9o1qU/s1600/rework-front-cover.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Rework&lt;/b&gt;&lt;/i&gt;&lt;b&gt; &lt;/b&gt;is the latest batch of short-and-sweet business wisdom from Jason Fried and David Heinemeier Hansson, the people behind &lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/"&gt;37signals&lt;/a&gt; (Basecamp, Ruby on Rails, etc.).&lt;br /&gt;
&lt;br /&gt;
A very quick read, &lt;i&gt;&lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/rework/"&gt;Rework&lt;/a&gt;&lt;/i&gt;&amp;nbsp;is essentially a collection of short blog-like observations about how 37signals runs their (small) business, and how they think you could run a business too if you wanted to. Most of these observations have been expressed by the 37signals team in some form or another already, and those who are already familiar with their philosophy of &lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/svn"&gt;Signal vs. Noise&lt;/a&gt; will find few surprises.&lt;br /&gt;
&lt;br /&gt;
Even so, &amp;nbsp;these things need to be said, and they need to be shared, and I'm glad Jason and David did.&lt;br /&gt;
&lt;br /&gt;
The book in many ways is the authors thumbing their noses at the Harvard MBA "here's how you need to run a real business" crowd. They say "no, you don't have to do it that way" with passages titled:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Ignore the real world &lt;/li&gt;
&lt;li&gt;Planning is guessing&lt;/li&gt;
&lt;li&gt;Why grow?&lt;/li&gt;
&lt;li&gt;Mission statement impossible&lt;/li&gt;
&lt;li&gt;Outside money is Plan Z&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;They advocate counter-intuitive concepts such as:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Underdo your competition&lt;/li&gt;
&lt;li&gt;Don't write it down&lt;/li&gt;
&lt;li&gt;Pass on great people&lt;/li&gt;
&lt;li&gt;Let your customers outgrow you&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;And they encourage individualism and honesty with sections like:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Don't copy&lt;/li&gt;
&lt;li&gt;Own your bad news&lt;/li&gt;
&lt;li&gt;How to say you're sorry&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;All of this is good, if not at least partially obvious. But it's almost as if, in publishing them in book form, the authors are giving &lt;s&gt;entrepreneurs&lt;/s&gt; business starters permission to act the way they would &lt;i&gt;like &lt;/i&gt;to act, but can't because all of the &lt;i&gt;other&lt;/i&gt;&amp;nbsp;business books say otherwise. This is the book that says "We did it this way, and it's working fine for us. Ignore what the suits tell you, and you can do it this way too."&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;The best pieces of advice, as far as I'm concerned, are the ones where the authors ask us, the readers, to go a bit above and beyond just making money with our businesses, and make the world a better place. In the section "Out-teach your competition", the authors write:&lt;/div&gt;&lt;blockquote&gt;Teach and you'll form a bond you just don't get from marketing tactics. Buying people's attention with a magazine or online banner ad is one thing. Earning their loyalty by teaching them forms a whole different connection. They'll trust you more. They'll respect you more. Even if they don't use your product, they can still be your fans.&lt;/blockquote&gt;&lt;div&gt;Similarly, they advise to "Emulate chefs" like Julia Child, Mario Batali, and Bobby Flay, who share their recipes and techniques with the world with positive effects:&lt;/div&gt;&lt;blockquote&gt;As a business owner, you should share everything you know, too. This is&amp;nbsp;anathema&amp;nbsp;to most in the business world. Businesses are usually paranoid and secretive. They think they have a proprietary this and competitive advantage that. Maybe a rare few do, but most don't. And those that don't should stop acting like those that do. Don't be afraid of sharing.&lt;/blockquote&gt;The ideas of respect and &amp;nbsp;trust, honesty and sharing, appear many times throughout the book, and it's obvious that the overarching feeling the authors are trying to get across is something like "Cut the bullsh*t, be serious, be honest, and be yourself". Hardly anything new, but good advice nonetheless.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="1" src="http://3.bp.blogspot.com/_R9uCU3ijWHE/S5xqiT1-B-I/AAAAAAAAACo/52BEdXjOg3I/s1600/planningisguessing.png" /&gt;&lt;/div&gt;While &lt;i&gt;Rework&lt;/i&gt; is about 280 pages long, several of the pages are hand-drawn sketches, illustrating the written ideas. Many of them are quite clever.&lt;br /&gt;
&lt;br /&gt;
As explained in &lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/svn/posts/2187-podcast-episode-9-all-about-rework"&gt;Signals vs. Noise podcast Episode #9 (All about Rework)&lt;/a&gt;, the decision to add the illustrations came late in the editing process, after the authors (in typical 37signals style) cut their written content in half to simplify it, and then found they didn't have enough words to create a book of the right size to fit nicely on a bookstore shelf.&lt;br /&gt;
&lt;br /&gt;
Rather than add words that would dilute the message, they hired &lt;a bitly="BITLY_PROCESSED" href="http://www.rohdesign.com/weblog/archives/003165.html"&gt;Mike Rohde of Rohdesign&lt;/a&gt; to provide the illustrations, thus simultaneously giving &lt;i&gt;Rework&lt;/i&gt; bookshelf-friendly dimensions and a great style. Mike later wrote a blog post about &lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/svn/posts/2180-illustrating-rework-part-1-of-2"&gt;his experience illustrating Rework&lt;/a&gt;. Interesting stuff.&lt;br /&gt;
&lt;br /&gt;
I certainly recommend picking up a copy for yourself and spending a few hours absorbing Jason's and David's advice. If you would like to get a peek at the contents first, head over to &lt;a bitly="BITLY_PROCESSED" href="http://37signals.com/rework/"&gt;the book's website&lt;/a&gt;. Here are some of my favorite passages:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;"Why don't we just call plans what they really are: guesses."&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp;"Let's retire the term &lt;i&gt;entrepreneur&lt;/i&gt;. It's outdated and loaded with baggage. It smells like a members-only club."&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp;"There's a world of difference between truly standing for something and having a mission statement that &lt;i&gt;says&lt;/i&gt; you stand for something."&lt;/blockquote&gt;&lt;blockquote&gt;"The problem with abstractions (like reports and documents) is that they create illusions of agreement. A hundred people can read the same words, but in their heads, they're imagining a hundred different things."&lt;/blockquote&gt;&lt;blockquote&gt;&amp;nbsp;"We're all terrible estimators. (...) That's why estimates that stretch weeks, months, and years into the future are fantasies. The truth is you just don't know what's going to happen that far in advance."&lt;/blockquote&gt;&lt;blockquote&gt;"We all know résumés are a joke. They're exaggerations. (...) Worst of all, they're too easy. Anyone can create a decent-enough&amp;nbsp;résumé. That's why half-assed applicants love them so much."&lt;/blockquote&gt;&lt;blockquote&gt;"If you are trying to decide among a few people to fill a position, hire the best writer."&lt;/blockquote&gt;&lt;blockquote&gt;"When you treat people like children, you get children's work. (...) When everything constantly needs approval, you create a culture of non-thinkers. You create a boss-versus-worker relationship that screams, "I don't trust you.""&amp;nbsp;&lt;/blockquote&gt;&amp;nbsp;Finally, a trailer for the book:&lt;br /&gt;
&lt;br /&gt;
&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ZJFTC9C_IBk&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/ZJFTC9C_IBk&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en_US&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-2097977229550846735?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=gDKune1ifL4:T6dWJMzYu8w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=gDKune1ifL4:T6dWJMzYu8w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=gDKune1ifL4:T6dWJMzYu8w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=gDKune1ifL4:T6dWJMzYu8w:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=gDKune1ifL4:T6dWJMzYu8w:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/gDKune1ifL4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/gDKune1ifL4/book-review-rework.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_R9uCU3ijWHE/S5xayeCn0wI/AAAAAAAAACk/xz7S1o9o1qU/s72-c/rework-front-cover.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/03/book-review-rework.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-2596588283600054217</guid><pubDate>Mon, 08 Mar 2010 00:30:00 +0000</pubDate><atom:updated>2010-03-26T20:31:02.469-07:00</atom:updated><title>More than functional</title><description>I listened to &lt;a href="http://www.pluralsight-training.net/community/blogs/pluralcast/archive/2010/03/01/pluralcast-10-reading-code-with-alan-stevens.aspx"&gt;Episode 10&lt;/a&gt; of the Pluralcast podcast the other day, in which David Starr discusses "Reading Code" with Alan Stevens:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;A few weeks ago at the MVP Summit in Redmond, I was fortunate enough to run into Alan Stevens, a man my wife refers to as “your southern-gentleman-vegan-hippy friend.” Alan shared with me some new ideas he has around the act of writing (songs or literature) as a metaphor for good practices of software development. The basic idea is that we write a line of code once, and read it many times. Why aren’t we optimizing for the reading part?&lt;/blockquote&gt;&lt;br /&gt;
The discussion they had struck close to home with me, as it resembled discussions my wife and I have occasionally. She is a fiction writer, and we commonly discuss her craft and how it relates to my craft of software development. In the podcast, Alan Stevens talks about his process of writing code in a way that resembles how he writes prose.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_R9uCU3ijWHE/S5RDxWzNABI/AAAAAAAAACY/yJtZqAU48y0/s1600-h/declarationdraft_small.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img alt="rough draft" border="0" src="http://1.bp.blogspot.com/_R9uCU3ijWHE/S5RDxWzNABI/AAAAAAAAACY/yJtZqAU48y0/s320/declarationdraft_small.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;With prose, it's pretty standard practice to write a first-draft with the purpose of just getting ideas down on paper and providing a basic structure, knowing that this draft is never meant to be used or seen by anybody other than the author. The author with then go through and make edits, adding, removing, and changing content, producing more drafts along the way, until, much later in the process, a (semi) final product is revealed. Then, that product will be looked at by an editor or two, and more changes will be made before publication. It's understood that a first-draft is &lt;i&gt;almost never&lt;/i&gt; publishing quality, and it's not expected to be able to write a non-trivial product in one go. That's just not how our brains work.&lt;br /&gt;
&lt;br /&gt;
When we write code, however, we seldomly venture past the first draft. We write the code for a module or a feature, verify it's functional, and then we pack away the code with no intention of ever changing it again. I mean, it works, right? There's no such thing as a "first draft". Occasionally there might be a code review session which will result in some edits. But really, how often does that happen?&lt;br /&gt;
&lt;br /&gt;
As it turns out, we always have to come back and read it again sometime. We all know that the code we write spends most of its lifetime in maintenance mode, but we tend to write it with an eye towards functionality only, forgetting about readability. As a result, when we come back to read our code later, we have to spend an inordinate amount of time rebuilding its context. Time we may not have had to spend if we have spent some time moving beyond the purely functional level.&lt;br /&gt;
&lt;br /&gt;
Lately, when I write code, I tend to consider my first run-through as a first-draft, like prose. Even if it ends up working perfectly on the first build, I always intend to make a couple more passes over the code with an eye toward readability. I don't &lt;i&gt;expect&lt;/i&gt; to write anything correctly the first time through, even if all my unit tests pass on the first try. I have to think about how I or others will see the code when we read it again 6 months, a year, or (aaagghh!) 3 years from now. &lt;br /&gt;
&lt;br /&gt;
If you find this correlation between writing code and writing prose to be interesting, then you should give the podcast a listen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-2596588283600054217?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=vpLzWuAfYgE:snB0CpI0TDQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=vpLzWuAfYgE:snB0CpI0TDQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=vpLzWuAfYgE:snB0CpI0TDQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=vpLzWuAfYgE:snB0CpI0TDQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=vpLzWuAfYgE:snB0CpI0TDQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/vpLzWuAfYgE" height="1" width="1"/&gt;</description><enclosure type="audio/mpeg" url="http://pluralsight-free.s3.amazonaws.com/pluralcast/pc_010_reading_code.mp3" length="0" /><link>http://feedproxy.google.com/~r/devadept/~3/vpLzWuAfYgE/more-than-functional.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_R9uCU3ijWHE/S5RDxWzNABI/AAAAAAAAACY/yJtZqAU48y0/s72-c/declarationdraft_small.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/03/more-than-functional.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-5396304174090727739</guid><pubDate>Fri, 05 Mar 2010 00:20:00 +0000</pubDate><atom:updated>2010-03-07T16:08:38.665-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Workplace</category><title>The most innovative municipal IT Department in the country</title><description>&lt;a bitly="BITLY_PROCESSED" href="http://www.blogger.com/"&gt;&lt;/a&gt;&lt;span id="goog_1267746889697"&gt;&lt;/span&gt;&lt;span id="goog_1267746889698"&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a bitly="BITLY_PROCESSED" href="http://4.bp.blogspot.com/_R9uCU3ijWHE/S1vDeWVJ4tI/AAAAAAAAABM/ro3RVLmbQyQ/s1600/pti_award.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_R9uCU3ijWHE/S1vDeWVJ4tI/AAAAAAAAABM/ro3RVLmbQyQ/s320/pti_award.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;The most innovative municipal IT Department in the country is here in Scottsdale, Arizona, at least according to the Public Technology Institute:&lt;br /&gt;
&lt;br /&gt;
&lt;a bitly="BITLY_PROCESSED" href="http://www.pti.org/index.php/ptiee1/more/601/"&gt;Public Technology Institute:  2009-2010 Technology Solutions Award Winners&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Building on &lt;a bitly="BITLY_PROCESSED" href="http://blog.devadept.com/2009/04/sweet.html"&gt;our success from last year&lt;/a&gt;, the City of Scottsdale Information Technology department has won six more Technology Solutions Awards (more than any other municipality in the country). We had three projects designated "Winner" in our population category, and three more projects received "Significant Achievement" designation. All of this during a year when the economy caused &lt;a bitly="BITLY_PROCESSED" href="http://news.google.com/archivesearch?q=city+of+scottsdale+budget&amp;amp;scoring=a&amp;amp;hl=en&amp;amp;ned=us&amp;amp;sa=N&amp;amp;sugg=d&amp;amp;as_ldate=2009/01&amp;amp;as_hdate=2009/06&amp;amp;lnav=hist8"&gt;severe budget cuts in our city&lt;/a&gt;, across the state, and the throughout country.&amp;nbsp;It's a great feeling to be involved with such quality work and such good people.&lt;br /&gt;
&lt;br /&gt;
Here is a list of our winning projects, summaries can be read on the PTI page linked above:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;The BIG Map &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;(&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Winner: Sustainability)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;Tax Audit Lead Finder &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;(&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Significant Achievement: Sustainability)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;eSubpoena: Creating Efficiencies in the Criminal and Civil Subpoena Process &lt;/b&gt;(&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Significant Achievement: Public Safety Technology)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;GIS Disaster Recovery Implementation &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;(&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Winner: Geospatial Information Systems)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;Employee Self Service Portal &lt;span class="Apple-style-span" style="font-weight: normal;"&gt;(&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;Winner: Web and E-Government Services)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;QuickPay Utilities Application &lt;/b&gt;(Significant Achievement: Web and E-Government Services)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-5396304174090727739?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=XSCbRxdoUbY:kSb4vUD5hXw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=XSCbRxdoUbY:kSb4vUD5hXw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=XSCbRxdoUbY:kSb4vUD5hXw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=XSCbRxdoUbY:kSb4vUD5hXw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=XSCbRxdoUbY:kSb4vUD5hXw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/XSCbRxdoUbY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/XSCbRxdoUbY/most-innovative-municipal-it-department.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_R9uCU3ijWHE/S1vDeWVJ4tI/AAAAAAAAABM/ro3RVLmbQyQ/s72-c/pti_award.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/03/most-innovative-municipal-it-department.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-6521981801635870504</guid><pubDate>Thu, 04 Mar 2010 18:58:00 +0000</pubDate><atom:updated>2010-03-07T16:17:24.047-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Soft Skills</category><category domain="http://www.blogger.com/atom/ns#">Workplace</category><category domain="http://www.blogger.com/atom/ns#">Book Review</category><title>The importance of cultural literacy</title><description>&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=devadept-20&amp;amp;l=bil&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=0394758439" style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none; margin: 0px; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;" width="1" /&gt;I believe, as do many others, that being a great developer means more than having great technical, code writing skills. I believe this is true because I believe developing great software takes more than simply writing great code.&lt;br /&gt;
&lt;br /&gt;
Even the most technically precise, supremely optimized, highly cohesive, loosely coupled,&amp;nbsp; well documented,&amp;nbsp; easily understandable, utterly attractive code can form the basis of an application that nobody wants to use, particularly if the application was developed without taking into account the needs and desires, likes and dislikes, of the intended audience.&lt;br /&gt;
&lt;br /&gt;
Crafting a well-rounded software application requires something more: “&lt;a href="http://en.wikipedia.org/wiki/Soft_skills" target="_blank" title="Soft Skills article on Wikipedia"&gt;soft skills&lt;/a&gt;”, the skills required to be able to converse with, empathize with, relate to, and work with other people, be they your customers, your coworkers, or anybody else who has a stake in the successful outcome of the software you are developing.&lt;br /&gt;
&lt;br /&gt;
As &lt;a href="http://elegantcode.com/about/david-starr/" target="_blank" title="read David Starr's posts on the Elegant Code website"&gt;David Starr of Elegant Code&lt;/a&gt; recently pointed out, &lt;a href="http://elegantcode.com/2010/03/04/soft-skills-are-actual-skills/trackback/" target="_blank" title="Read &amp;quot;Soft skills are actual skills&amp;quot; on elegantcode.com"&gt;soft skills are actual skills&lt;/a&gt;, and they can be learned. He points to an “effective communication pattern” that developers can learn as if they were learning a &lt;a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)" target="_blank" title="Design Pattern article on Wikipedia"&gt;software design pattern&lt;/a&gt;. And there are lots ways for people to learn &lt;a href="http://en.wikipedia.org/wiki/Communication_skills_training" target="_blank" title="Communication Skills Training article on Wikipedia"&gt;communication skills&lt;/a&gt;, with methods and techniques for:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Establishing personal contact, &lt;/li&gt;
&lt;li&gt;Active listening, &lt;/li&gt;
&lt;li&gt;Reducing emotional tensions with the partner, &lt;/li&gt;
&lt;li&gt;Defending one’s opinion, position, or point of view, &lt;/li&gt;
&lt;li&gt;Discussing organization and administration, &lt;/li&gt;
&lt;li&gt;Public presentations. &lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
I feel, however, that for such training to be truly effective, one must supplement the methods and techniques with some homework. That homework, in the context of interpersonal communications, I’ve learned to call “&lt;a href="http://en.wikipedia.org/wiki/Cultural_literacy" target="_blank" title="Cultural Literacy on Wikipedia"&gt;cultural literacy&lt;/a&gt;".&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
About 20 years ago I picked up a book called &lt;em&gt;&lt;a href="http://www.amazon.com/Cultural-Literacy-Every-American-Needs/dp/0394758439%3FSubscriptionId%3D0JTCV5ZMHMF7ZYTXGFR2%26tag%3Ddevadept-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0394758439" target="_blank"&gt;Cultural Literacy: What Every American Needs to Know&lt;/a&gt;&lt;/em&gt;. It’s still on my bookshelf, and, although much of the topical content is a bit out of date (&lt;a href="http://www.amazon.com/New-Dictionary-Cultural-Literacy-American/dp/0618226478%3FSubscriptionId%3D0JTCV5ZMHMF7ZYTXGFR2%26tag%3Ddevadept-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0618226478" target="_blank" title="Amazon.com: The New Dictionary of Cultural Literacy: What Every American Needs to Know"&gt;I see there have been updates&lt;/a&gt;),&amp;nbsp; I still refer to it occasionally to this day. From the back cover:&lt;br /&gt;
&lt;blockquote&gt;&lt;span style="color: #7d7a77;"&gt;In this forceful manifesto Professor &lt;a href="http://www.amazon.com/E.-D.-Hirsch/e/B001IGOMRC/ref=ntt_dp_epwbk_1" target="_blank" title="E. D. Hirsch's page on Amazon.com"&gt;E. D. Hirsch, Jr.&lt;/a&gt;, argues that children in the United States are being deprived of the basic knowledge that would enable them to function in contemporary society. They lack cultural literacy: a grasp of background information that writers and speakers assume their audience already has. Thus even if a student has basic competence in the English language, he or she has little chance of entering the American mainstream without knowing what a silicon chip is, or when the Civil War was fought.&lt;/span&gt;&lt;/blockquote&gt;While the point of the book is to affect childhood education reform, I believe its principles can be applied to the adult workplace, too.&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
The back cover also asks the reader to test their &lt;em&gt;cultural literacy&lt;/em&gt; by putting certain words or phrases into context: “absolute zero”, “sea legs”, “Billy the Kid”, “carpetbagger”, “lame duck”, “Iago”, “tabula rasa”, “Zeitgeist”, etc. &lt;br /&gt;
&lt;br /&gt;
The point of the exercise being to illustrate that there are words, phrases, places, and names used in various forms of communication that bring with them extra meaning wrapped in context. Being &lt;em&gt;culturally literate&lt;/em&gt; means being able to recognize that extra meaning and use it to communicate better.&lt;br /&gt;
&lt;br /&gt;
I find myself in an interesting point in my life: not quite 40 years old, I commonly find myself working with folks a generation older than I am, and some who are a generation younger than I am. To the older ones, the terms “Watergate”, “Vietnam”, and “socialism”&amp;nbsp; probably have much greater emotional impact than the same terms do for me, for various reasons. Likewise, “lol”, “friend me”, and “&lt;a href="http://www.urbandictionary.com/define.php?term=No%20stalk&amp;amp;defid=4742156" target="_blank" title="&amp;quot;No stalk&amp;quot; definition on Urban dictionary"&gt;no stalk&lt;/a&gt;” have crept into the vocabulary of those much younger than me. &lt;br /&gt;
&lt;br /&gt;
To communicate effectively with those around me, I feel I need to be aware of these contexts; I need to constantly work on my cultural literacy. The best developers among us are those who can understand and communicate with others, and the best communicators are those who are culturally literate.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-6521981801635870504?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=tTPkH1shfMo:K3BKTa7ekV0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=tTPkH1shfMo:K3BKTa7ekV0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=tTPkH1shfMo:K3BKTa7ekV0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=tTPkH1shfMo:K3BKTa7ekV0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=tTPkH1shfMo:K3BKTa7ekV0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/tTPkH1shfMo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/tTPkH1shfMo/importance-of-cultural-literacy.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.devadept.com/2010/03/importance-of-cultural-literacy.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-1528073979555551572</guid><pubDate>Sun, 14 Feb 2010 02:08:00 +0000</pubDate><atom:updated>2010-03-04T16:22:44.407-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">Learning</category><title>Abstractions, Abstractions, Pile Them On</title><description>In my modest experience as a web developer using ASP.NET, I have gone through several stages of comfort and happiness with Web Forms, most of which I assume are pretty common:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;em&gt;Amazement&lt;/em&gt; at how little code or markup you need to write in order to spit out a bunch of html &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Confusion &lt;/em&gt;over this “&lt;a bitly="BITLY_PROCESSED" href="http://msdn.microsoft.com/en-us/library/aa720416(VS.71).aspx" target="_blank"&gt;Postback&lt;/a&gt;” thing &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Slowly growing comfort&lt;/em&gt; with the “&lt;a bitly="BITLY_PROCESSED" href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" target="_blank"&gt;Page Life Cycle&lt;/a&gt;” and its foibles &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Eagerness&lt;/em&gt; to use more controls, especially those new-fangled “&lt;a bitly="BITLY_PROCESSED" href="http://www.asp.net/ajax/AjaxControlToolkit/Samples/" target="_blank"&gt;Ajax&lt;/a&gt;” ones &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Happiness&lt;/em&gt; over how quickly pretty good applications could be written &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Frustration&lt;/em&gt; at the quality of the html that gets spit out &lt;/li&gt;
&lt;li&gt;&lt;em&gt;More frustration&lt;/em&gt; over state-management (view state? session variables? hidden form fields? cookies? client-side caching? server side caching? AARRGGHH!!) &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Yet more frustration&lt;/em&gt; with the hoops you have to jump through with the Page Life Cycle &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Even more frustration&lt;/em&gt; with the &lt;a bitly="BITLY_PROCESSED" href="http://blog.slaven.net.au/archives/2008/05/02/the-updatepanel-is-evil/" target="_blank"&gt;Update Panel&lt;/a&gt; and the general clumsiness of ASP.NET Ajax &lt;/li&gt;
&lt;li&gt;&lt;em&gt;Hope&lt;/em&gt; that tools like &lt;a bitly="BITLY_PROCESSED" href="http://jquery.com/" target="_blank"&gt;jQuery&lt;/a&gt; will help deal with the above frustrations &lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
You may have noticed a trend. :-) Like many, I think I have grown slowly weary of the idiosyncrasies of the Web Forms engine and its “&lt;a bitly="BITLY_PROCESSED" href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html" target="_blank"&gt;Leaky Abstraction&lt;/a&gt;” problems. In our zeal to abstract away the complexities of a naturally stateless web environment, we’ve accepted abstractions piled upon abstractions piled upon more abstractions.&amp;nbsp; I can’t help but feel we’ve arrived at a point where, despite creating abstractions to simplify web development, the weight of the abstractions (or, more precisely, the weight of the &lt;em&gt;leaks&lt;/em&gt;) have complicated things more than they’ve helped.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Of course, I’m not the first to realize that &lt;a bitly="BITLY_PROCESSED" href="http://www.onenaught.com/posts/42/aspnet-is-a-leaky-abstraction" target="_blank"&gt;ASP.NET is a leaky abstraction&lt;/a&gt;. And I’m certainly not suggesting that the abstractions shouldn’t &lt;a bitly="BITLY_PROCESSED" href="http://www.codinghorror.com/blog/2005/04/respecting-abstraction.html" target="_blank"&gt;be respected&lt;/a&gt;. On the contrary, I understand that the tall abstraction pile helps us build better software. But, as&lt;a bitly="BITLY_PROCESSED" href="http://www.ericsink.com/Abstraction_Pile.html" target="_blank"&gt; Eric Sink says&lt;/a&gt;:&lt;br /&gt;
&lt;blockquote&gt;This is what programmers do.&amp;nbsp; We build piles of abstractions.&amp;nbsp; We design our own abstractions and then pile them up on top of layers we got from somebody else.&amp;nbsp; Abstractions can be great.&amp;nbsp; We use them because they save us a lot of time.&amp;nbsp; But abstractions can also cause lots of problems.&amp;nbsp; They're never perfect, as Joel Spolsky explains in his excellent article on "&lt;a bitly="BITLY_PROCESSED" href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;The Law of Leaky Abstractions&lt;/a&gt;".&lt;br /&gt;
&lt;br /&gt;
But you can't have the benefits of an abstraction without its risks.&amp;nbsp; We need to make wise decisions about our piles of abstractions.&lt;/blockquote&gt;So, we’ve built layer on layer of abstractions, &lt;a bitly="BITLY_PROCESSED" href="http://codeclimber.net.nz/archive/2007/07/02/How-to-clean-your-ASP.NET-HTML-markup-with-the-CSS.aspx" target="_blank"&gt;some layers created solely to fix problems created by other abstractions&lt;/a&gt;. And it can get very confusing just keeping them straight. &lt;br /&gt;
&lt;br /&gt;
Consider &lt;a bitly="BITLY_PROCESSED" href="http://stackoverflow.com/questions/2252857" target="_blank"&gt;this recent question&lt;/a&gt; on &lt;a bitly="BITLY_PROCESSED" href="http://stackoverflow.com/" target="_blank" title="StackOverflow"&gt;StackOverflow&lt;/a&gt; concerning view state and dynamically loaded controls. The developer is using an Update Panel (abstraction of Ajax functionality) holding a Panel (abstraction of a div) on a page with manually updated view state (abstraction of application state). Sometime during the page lifecycle, the developer wants to add dynamically loaded controls (abstraction of HTML elements), but during the postback (abstraction of a stateful event), the controls lose their state. He’s using &lt;a bitly="BITLY_PROCESSED" href="http://msdn.microsoft.com/en-us/magazine/cc748662.aspx" target="_blank"&gt;somebody’s example&lt;/a&gt; as a reference, but with a slight difference. What can he do?&lt;br /&gt;
&lt;br /&gt;
This entire situation exemplifies what happens when we pile too many abstractions on top of one another, such that we end up with so many leaks that we don’t know how to resolve them. Yet, what’s our first impulse when trying to help? We suggest to &lt;a bitly="BITLY_PROCESSED" href="http://stackoverflow.com/questions/2252857/viewstate-variable-lost-on-user-control-loaded-dynamically/2256776#2256776" target="_blank"&gt;try yet one more abstraction&lt;/a&gt;. This, to provide page functionality that (if done with different tools) probably wouldn’t need any of the abstraction layers that are getting in the way.&lt;br /&gt;
&lt;br /&gt;
I can certainly see, therefore,&amp;nbsp; the attraction that many web developers have to ASP.NET MVC. It, unlike web forms, &lt;em&gt;accepts&lt;/em&gt; the fact that the web is primarily a stateless environment. It is able, therefore, to strip away many of the abstractions we’ve built to simulate a stateful environment. To be fair, many of the frustrations we have with the current version of web forms are being addressed with ASP.NET 4.0. And MVC adds a few new abstractions of its own. But still…&lt;br /&gt;
&lt;br /&gt;
MVC has a few paradigms that may be tough to learn for those whose experience is entrenched in web forms. Gone are the training wheels, and that scares some, and frustrates others (I’ve got to learn something else now?). On the whole, though, using MVC feels like a more &lt;em&gt;natural&lt;/em&gt; way to develop web applications. It sheds many of the abstraction layers that web forms has built up for us, and in turn feels less complicated. &lt;br /&gt;
&lt;br /&gt;
At least, so far. Let’s see how long that lasts. :-)&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="border-collapse: collapse; font-family: arial, sans-serif; font-size: 13px;"&gt;GPFKURH6UEK9&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-1528073979555551572?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=_9OCoMcGovo:szLjre6kBLM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=_9OCoMcGovo:szLjre6kBLM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=_9OCoMcGovo:szLjre6kBLM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=_9OCoMcGovo:szLjre6kBLM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=_9OCoMcGovo:szLjre6kBLM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/_9OCoMcGovo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/_9OCoMcGovo/abstractions-abstractions-pile-them-on.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.devadept.com/2010/02/abstractions-abstractions-pile-them-on.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-2995879579097811336</guid><pubDate>Fri, 12 Feb 2010 04:05:00 +0000</pubDate><atom:updated>2010-02-11T21:05:33.927-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Workplace</category><category domain="http://www.blogger.com/atom/ns#">Recommendations</category><title>Developer Soft Skills</title><description>&lt;p&gt;I listened to a good podcast &lt;a href="http://deepfriedbytes.com/podcast/episode-44-soft-skills-every-developer-needs-with-brian-prince/" target="_blank"&gt;episode of Deep Fried Bytes&lt;/a&gt; (Episode 44) the other day:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;In this episode Keith and Woody sat down with &lt;a href="http://brianhprince.com/"&gt;Brian Prince&lt;/a&gt;, Developer/Architect Evangelist for Microsoft, to discuss the soft skills developers and software engineers need.&amp;#160; Brian has been speaking at conferences about soft skills for many years.&amp;#160; In true Deep Fried fashion this show is chalk full of stories.&amp;#160; The guys discuss tips for handling one's career as well as life work balance, sales and communication.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Soft_skills" target="_blank"&gt;Soft skills&lt;/a&gt; are social, interpersonal, and leadership skills that programmers (and many other people, for that matter) sometimes neglect to develop. I strongly believe that it’s impossible to be a truly adept developer without cultivating the skills involved with effective interpersonal relationships. We are, after all, people writing code for other people.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Anyhow, the discussion between the Deep Fried Bytes guys and Brian Prince touched on a lot of important ‘soft skill’ issues. It’s well worth the listen.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image_12[1]" border="0" alt="image_12[1]" src="http://lh5.ggpht.com/_R9uCU3ijWHE/S3TTjVN7e6I/AAAAAAAAACQ/ztDxC4I4GxU/image_12%5B1%5D%5B8%5D.png?imgmax=800" width="250" height="136" /&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-2995879579097811336?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=9gtP1Jm5E4k:R0-WRtntxmI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=9gtP1Jm5E4k:R0-WRtntxmI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=9gtP1Jm5E4k:R0-WRtntxmI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=9gtP1Jm5E4k:R0-WRtntxmI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=9gtP1Jm5E4k:R0-WRtntxmI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/9gtP1Jm5E4k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/9gtP1Jm5E4k/developer-soft-skills.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_R9uCU3ijWHE/S3TTjVN7e6I/AAAAAAAAACQ/ztDxC4I4GxU/s72-c/image_12%5B1%5D%5B8%5D.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.devadept.com/2010/02/developer-soft-skills.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-5488318591356526004</guid><pubDate>Tue, 09 Feb 2010 05:08:00 +0000</pubDate><atom:updated>2010-03-04T16:23:47.287-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><title>Using ELMAH with multiple applications</title><description>I’ve been using &lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/" target="_blank" title="Error Logging Modules and Handlers for ASP.NET"&gt;ELMAH&lt;/a&gt; a lot lately, and have it deployed to multiple ASP.NET applications. &lt;a bitly="BITLY_PROCESSED" href="http://blog.devadept.com/2009/09/tickle-me-elmah.html"&gt;As I’ve said before&lt;/a&gt;, I love it. It’s certainly easy to set up and useful for each application to have an error log of its own. &lt;br /&gt;
&lt;br /&gt;
However, sometimes I want to see a consolidated list of errors across all of those&amp;nbsp; applications. Here are a few of the things I’ve done to create what I call a “Master” ELMAH error log viewer.&lt;br /&gt;
&lt;br /&gt;
First, the easy part. Each of the applications that I’ve deployed are connected to the same SQL Server database, prepared using &lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/source/browse/trunk/src/Elmah/SQLServer.sql" target="_blank"&gt;the standard ELMAH configuration&lt;/a&gt;. All of them log to the same database. &lt;br /&gt;
&lt;br /&gt;
The ELMAH viewer page HTTP handler, however, is designed to filter the errors by application. It does this by inferring the application name (or getting it from the config file, if you’ve specified it there), and then sending that application name to the database as a parameter for the ELMAH_GetErrorsXML and ELMAH_GetErrorXML stored procedures. The stored procedures have a WHERE clause in the SELECT statement that filters the errors. This is great for the applications individually, but we have to override that behavior if we want to have a consolidated view.&lt;br /&gt;
&lt;br /&gt;
To start, I created two additional stored procedures in the database called ELMAH_GetErrorsXML_Master and ELMAH_GetErrorXML_Master. These sprocs are identical to the standard ELMAH sprocs, except I’ve removed the ‘@Application’ parameter and the ‘WHERE [Application] = @Application’ clauses.&lt;br /&gt;
&lt;br /&gt;
Next (this requires &lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/downloads/list" target="_blank"&gt;downloading the source code&lt;/a&gt;, editing it, and recompiling), I created a ‘SQLMasterErrorLog.cs’, based on the existing ‘&lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/source/browse/trunk/src/Elmah/SqlErrorLog.cs" target="_blank"&gt;SQLErrorLog.cs&lt;/a&gt;’ class. I edited the GetErrorXml() and GetErrorsXML() methods to match the new sprocs I created, removing the @Application parameter. &lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
For example, this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; SqlCommand GetErrorXml(&lt;span class="kwrd"&gt;string&lt;/span&gt; appName, Guid id)&lt;/pre&gt;&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;SqlCommand command = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlCommand(&lt;span class="str"&gt;"ELMAH_GetErrorXml"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alteven"&gt;command.CommandType = CommandType.StoredProcedure;&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alteven"&gt;SqlParameterCollection parameters = command.Parameters;&lt;/pre&gt;&lt;pre class="alt"&gt;parameters.Add(&lt;span class="str"&gt;"@Application"&lt;/span&gt;, SqlDbType.NVarChar, &lt;/pre&gt;&lt;pre class="alteven"&gt;_maxAppNameLength).Value = appName;&lt;/pre&gt;&lt;pre class="alt"&gt;parameters.Add(&lt;span class="str"&gt;"@ErrorId"&lt;/span&gt;, SqlDbType.UniqueIdentifier).Value = id;&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; command;&lt;/pre&gt;&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
became this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; SqlCommand GetErrorXml(&lt;span class="kwrd"&gt;string&lt;/span&gt; appName, Guid id)&lt;/pre&gt;&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;pre class="alt"&gt;SqlCommand command = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlCommand(&lt;span class="str"&gt;"ELMAH_GetErrorXml_Master"&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="alteven"&gt;command.CommandType = CommandType.StoredProcedure;&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alteven"&gt;SqlParameterCollection parameters = command.Parameters;&lt;/pre&gt;&lt;pre class="alt"&gt;parameters.Add(&lt;span class="str"&gt;"@ErrorId"&lt;/span&gt;, SqlDbType.UniqueIdentifier).Value = id;&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; command;&lt;/pre&gt;&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
GetErrorsXML() got the same treatment. I also updated the &amp;lt;summary&amp;gt; description and the ‘Name’ property to reflect the changes I had made.&lt;br /&gt;
&lt;br /&gt;
Next, I changed the &lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/source/browse/trunk/src/Elmah/ErrorLogPage.cs" target="_blank"&gt;ErrorLogPage.cs&lt;/a&gt; file to display an extra column in the log viewer table for the Application Name. In the "’RenderErrors()” method, I added these lines (top line only):&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;headRow.Cells.Add(FormatCell(&lt;span class="kwrd"&gt;new&lt;/span&gt; TableHeaderCell(), &lt;span class="str"&gt;"App"&lt;/span&gt;, &lt;span class="str"&gt;"app-col"&lt;/span&gt;));&lt;/pre&gt;&lt;pre class="alteven"&gt;headRow.Cells.Add(FormatCell(&lt;span class="kwrd"&gt;new&lt;/span&gt; TableHeaderCell(), &lt;span class="str"&gt;"Host"&lt;/span&gt;, &lt;span class="str"&gt;"host-col"&lt;/span&gt;));&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;and &lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;bodyRow.Cells.Add(FormatCell(&lt;span class="kwrd"&gt;new&lt;/span&gt; TableCell(), error.ApplicationName, &lt;span class="str"&gt;"app-col"&lt;/span&gt;));&lt;/pre&gt;&lt;pre class="alteven"&gt;bodyRow.Cells.Add(FormatCell(&lt;span class="kwrd"&gt;new&lt;/span&gt; TableCell(), error.HostName, &lt;span class="str"&gt;"host-col"&lt;/span&gt;));&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;After saving and compiling, I had a new elmah.dll that contains a “SQLMaster” error log.&lt;br /&gt;
&lt;br /&gt;
The final step was creating a web application to hold the new ELMAH viewer. I made an empty ASP.NET application, with nothing in it but a Default.aspx file that really only exists to autoforward to the errors.axd handler. With one small tweak to the standard configuration, I was off and running:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;&amp;lt;errorLog type=&lt;span class="str"&gt;"Elmah.SqlMasterErrorLog, Elmah"&lt;/span&gt; connectionStringName=&lt;span class="str"&gt;"elmah"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-5488318591356526004?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=5U-Z93kmvEo:jn_WQNtiLU8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=5U-Z93kmvEo:jn_WQNtiLU8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=5U-Z93kmvEo:jn_WQNtiLU8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=5U-Z93kmvEo:jn_WQNtiLU8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=5U-Z93kmvEo:jn_WQNtiLU8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/5U-Z93kmvEo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/5U-Z93kmvEo/using-elmah-with-multiple-applications.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>6</thr:total><feedburner:origLink>http://blog.devadept.com/2010/02/using-elmah-with-multiple-applications.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-1963964937305268387</guid><pubDate>Thu, 04 Feb 2010 05:03:00 +0000</pubDate><atom:updated>2010-03-04T16:24:28.983-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Learning</category><category domain="http://www.blogger.com/atom/ns#">Book Review</category><title>A few days with my son and Python</title><description>I’ve had the &lt;a bitly="BITLY_PROCESSED" href="http://www.amazon.com/Hello-World-Computer-Programming-Beginners/dp/1933988495%3FSubscriptionId%3D0JTCV5ZMHMF7ZYTXGFR2%26tag%3Ddevadept-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D1933988495" target="_blank"&gt;Hello World! Computer Programming for Kids and Other Beginners&lt;/a&gt; book for about a week now, and my son and I have spent a few hours dabbling with it. So far I’d have to say that I’m pretty pleased with his level of interest.&lt;br /&gt;
&lt;br /&gt;
The first few chapters are designed to get the reader to the general concept of computer programming and how to use the development environment (which is &lt;a bitly="BITLY_PROCESSED" href="http://en.wikipedia.org/wiki/IDLE_(Python)" target="_blank" title="IDLE on wikipedia"&gt;IDLE&lt;/a&gt;, a basic Python interactive shell). The book walks you through a bunch of basic string and number manipulating commands, and then the first chapter ends by asking the reader to type in a slightly longer program (about 18 lines) to run as a demo of concepts to be learned later in the book. The program, a pirate-themed random-number guessing game, is then run in the IDLE shell.&lt;br /&gt;
&lt;br /&gt;
Watching my son do this reminded me of when I was a kid, typing a 100+ line BASIC program into a friend’s Commodore64 cassette-tape drive, executing, and hoping I hadn’t made a typo. Except now, a lot of the tedium has been removed and the feedback loop is so much faster. Ahh, kids these days just don’t realize how easy they have it… &lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Anyhow, as ‘cool’ as the pirate-speak is in the sample code (“What's yer guess?” and “Avast! Ye got it! Found my secret, ye did!”) my son’s interest rose exponentially once I suggested that it was &lt;em&gt;his&lt;/em&gt; program and he could change the words if he wanted to. He decided to substitute a Pokémon theme, and spent the next 45 minutes modifying the code appropriately. Nice.&lt;br /&gt;
&lt;br /&gt;
To spur my own learning and keep him interested, I created a text file with a list of all of the &lt;a bitly="BITLY_PROCESSED" href="http://en.wikipedia.org/wiki/List_of_Pok%C3%A9mon" target="_blank" title="List of Pokémon"&gt;Pokémon characters&lt;/a&gt; (my some told me there are 150 of them, it turns out there are 493) and used it as a resource for another version of the number-guessing game. We were now able to have a Pokémon identify itself by name and the player guesses its ‘number’. My son spent another 45 minutes or so playing this one. Next we made another version of the app which lets the player type in the character’s name and the program will find its number in the character list. Big hit.&lt;br /&gt;
&lt;br /&gt;
So far it's been baby steps for both of us, but it’s been fun. While trying to find ways to incorporate his schoolwork into the programming exercises, I made up a little quiz-game with the States and their Capital Cities. He loves it. I hope his interest continues.&lt;br /&gt;
&lt;br /&gt;
I’m also enjoying learning Python. I can remember how I felt a few years ago when I made the transition from writing VBA and VB6 and ‘classic’ ASP code to writing C# and ASP.NET. Everything seemed much more &lt;em&gt;stiff&lt;/em&gt; and &lt;em&gt;restrictive&lt;/em&gt;, what with all of the curly braces and semicolons all over the place. One character out of place and the whole build breaks. But now I’m used to it. Dare I say, I’m almost &lt;em&gt;dependent&lt;/em&gt; on it. &lt;br /&gt;
&lt;br /&gt;
Python, however, seems so much more &lt;em&gt;loose&lt;/em&gt;. It’s dynamically typed, and code blocks are denoted using whitespace rather than the (oh so comforting) curly braces. I don’t feel so much &lt;em&gt;free&lt;/em&gt; writing Python code as I feel &lt;em&gt;naked&lt;/em&gt;. When defining a class, where do I put the property definitions? “Properties?” replies Python. “We don’t need no stinking properties!”.&amp;nbsp; The way the code &lt;em&gt;looks&lt;/em&gt; is fairly comfortable, although the sense of &lt;em&gt;elegance&lt;/em&gt; hasn’t quite hit me yet. &lt;br /&gt;
&lt;br /&gt;
I feel good about it, though. Perhaps after working my way through &lt;em&gt;Hello World!&lt;/em&gt; with my son I’ll go a bit deeper. Maybe I can look forward to tackling &lt;a bitly="BITLY_PROCESSED" href="http://diveintopython.org/" target="_blank"&gt;Dive Into Python&lt;/a&gt; and/or &lt;a bitly="BITLY_PROCESSED" href="http://www.djangoproject.com/" target="_blank"&gt;Django&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-1963964937305268387?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=oaaMquqph6o:p5wG0n9a6X0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=oaaMquqph6o:p5wG0n9a6X0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=oaaMquqph6o:p5wG0n9a6X0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=oaaMquqph6o:p5wG0n9a6X0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=oaaMquqph6o:p5wG0n9a6X0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/oaaMquqph6o" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/oaaMquqph6o/few-days-with-my-son-and-python.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/02/few-days-with-my-son-and-python.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-3166751640195640113</guid><pubDate>Sun, 24 Jan 2010 16:19:00 +0000</pubDate><atom:updated>2010-03-07T16:03:11.453-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Learning</category><title>Hello World!</title><description>After listening to Scott Hanselman interview 10-year old Carter Sande and his dad Warren on a&lt;a bitly="BITLY_PROCESSED" href="http://www.hanselman.com/blog/HanselminutesPodcast194HelloWorldComputerProgrammerForKidsAndOtherBeginners.aspx"&gt; recent Hanselminutes episode&lt;/a&gt;, I skipped over to YouTube and watched him give &lt;a bitly="BITLY_PROCESSED" href="http://www.youtube.com/watch?v=HCUlkJjF1Ac"&gt;an introduction to PythonCard&lt;/a&gt; (see below). He's one precocious kid.&lt;br /&gt;
&lt;br /&gt;
&lt;a bitly="BITLY_PROCESSED" href="http://www.amazon.com/Hello-World-Computer-Programming-Beginners/dp/1933988495?ie=UTF8&amp;amp;tag=devadept-20&amp;amp;link_code=bil&amp;amp;camp=213689&amp;amp;creative=392969" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;" target="_blank"&gt;&lt;img alt="Hello World! Computer Programming for Kids and Other Beginners" src="http://ws.amazon.com/widgets/q?MarketPlace=US&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;ASIN=1933988495&amp;amp;tag=devadept-20" /&gt;&lt;/a&gt;He and his dad have written a book called &lt;i&gt;Hello World! Computer Programming for Kids and Other Beginners&lt;/i&gt;. I  decided to buy the book for my sons and see how they like it.&lt;br /&gt;
&lt;br /&gt;
We've dabbled in some programming together previously, using &lt;a bitly="BITLY_PROCESSED" href="http://scratch.mit.edu/"&gt;Scratch&lt;/a&gt;. They seemed somewhat interested, but being typical 6 or 8 year-old boys, their attention drifted and I haven't seen them working with Scratch recently. The &lt;i&gt;Hello World!&lt;/i&gt; book uses Python, which is very different from the graphics-oriented Scratch, so I have no idea how if their interest in programming will come back. We'll see.&lt;br /&gt;
&lt;br /&gt;
(Not that I necessarily want my children to follow in my computer-programming footsteps, but I think that learning basic programming concepts is important in the same way as learning basic math concepts.)&lt;br /&gt;
&lt;br /&gt;
Anyhow, I ordered the book from &lt;a bitly="BITLY_PROCESSED" href="http://www.manning.com/sande/"&gt;Manning.com&lt;/a&gt; with the 40% discount code you can find on the &lt;a bitly="BITLY_PROCESSED" href="http://www.hanselminutes.com/default.aspx?showID=212"&gt;Hanselminutes podcast page&lt;/a&gt;. It's good until January 31st.&lt;br /&gt;
&lt;br /&gt;
&lt;object&gt;&lt;param name="movie" value="http://www.youtube.com/v/HCUlkJjF1Ac&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;border=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/HCUlkJjF1Ac&amp;hl=en_US&amp;fs=1&amp;rel=0&amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="400" height="252"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-3166751640195640113?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=mEXBddQKjco:Z2CrJV2H8Og:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=mEXBddQKjco:Z2CrJV2H8Og:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=mEXBddQKjco:Z2CrJV2H8Og:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=mEXBddQKjco:Z2CrJV2H8Og:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=mEXBddQKjco:Z2CrJV2H8Og:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/mEXBddQKjco" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/mEXBddQKjco/hello-world.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/01/hello-world.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-128679647609304615</guid><pubDate>Sun, 24 Jan 2010 06:40:00 +0000</pubDate><atom:updated>2010-03-04T16:25:20.015-07:00</atom:updated><title>New Year, Fresh Start</title><description>Well, another year has rolled around, and before I know it the first month has already blown by. How &lt;a bitly="BITLY_PROCESSED" href="http://en.wikipedia.org/wiki/Tempus_fugit"&gt;time flies&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
I started blogging last year and, not being much of a writer, I decided to try to inspire some topics by inspecting and changing the code of the very tool I was using to blog. So &lt;a bitly="BITLY_PROCESSED" href="http://blog.devadept.com/2009/04/blogenginenet-experiment.html"&gt;I started using BlogEngine.net&lt;/a&gt; both as a blogging platform and as a &lt;a bitly="BITLY_PROCESSED" href="http://blog.devadept.com/search/label/BlogEngine%20Experiment"&gt;refactoring experiment&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
As you can see, I'm not doing that any more. As I delved deeper into the BlogEngine.net code, refactoring as I went, I was also learning more about &lt;a bitly="BITLY_PROCESSED" href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;SOLID&lt;/a&gt; programming principles such as the &lt;i&gt;Dependency Inversion Principle&lt;/i&gt; and the &lt;i&gt;Single Responsibility Principle&lt;/i&gt;. As I became more familiar with the BlogEngine.net codebase, I was also becoming more comfortable with &lt;a bitly="BITLY_PROCESSED" href="http://domaindrivendesign.org/resources/ddd_terms"&gt;Domain Driven Design&lt;/a&gt; concepts such as Entities and Repositories. &lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The result was that, over time, I could see that BlogEngine.net was not written in a manner that accommodates SOLID or DDD strategies. Short of completely gutting the project and rewriting core components from scratch, there was not going to be any Inversion of Control. Unit testing is next to impossible.In the meantime, ASP.NET MVC was released, and is now closing in on a v.2 release. I have a couple of side-projects I'd like to build, and I guess I'm just ready to move on.&lt;br /&gt;
&lt;br /&gt;
So, as of this post, I've moved over to Blogger, at least for now. :-) I don't feel that my experiment with BlogEngine.net was a failure, though. On the contrary; I learned a lot. Being exposed to different programming styles is a good thing, and I feel a greater appreciation for the styles I've chosen. And while BlogEngine.net works great for those who've written it, it's ultimately not for me. &lt;br /&gt;
&lt;br /&gt;
(For the record, this is my 3rd blogging platform in 3 years, spanning a total of 14 posts. Note to self: write more.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-128679647609304615?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=UieV_T7IFyE:olrFnLdAwwU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=UieV_T7IFyE:olrFnLdAwwU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=UieV_T7IFyE:olrFnLdAwwU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=UieV_T7IFyE:olrFnLdAwwU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=UieV_T7IFyE:olrFnLdAwwU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/UieV_T7IFyE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/UieV_T7IFyE/new-year-fresh-start.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2010/01/new-year-fresh-start.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-5627139490169113671</guid><pubDate>Sun, 06 Sep 2009 18:48:00 +0000</pubDate><atom:updated>2010-03-04T16:27:34.171-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><title>Tickle Me ELMAH</title><description>I came across a utility the other day that, in my opinion, just&lt;i&gt; Gets It Right&lt;/i&gt;™. It’s easy to install, easy to configure, easy to use, and it’s got just the features you need, nothing more. It gets out of your way, and unobtrusively does its work. It’s free and open source. What more can you ask for?&lt;br /&gt;
&lt;br /&gt;
The utility is called ELMAH. It’s an exception logging tool, and it’s unfortunate name is an acronym for “Error Logging Modules And Handlers”. Its Google Code site at &lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/" title="http://code.google.com/p/elmah/"&gt;http://code.google.com/p/elmah/&lt;/a&gt; describes itself as:&lt;br /&gt;
&lt;blockquote&gt;ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.&lt;/blockquote&gt;&lt;blockquote&gt;Once ELMAH has been dropped into a running web application and configured appropriately, you get the following facilities without changing a single line of your code:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Logging of nearly all unhandled exceptions. &lt;/li&gt;
&lt;li&gt;A web page to remotely view the entire log of recoded exceptions. &lt;/li&gt;
&lt;li&gt;A web page to remotely view the full details of any one logged exception. &lt;/li&gt;
&lt;li&gt;In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with &lt;tt&gt;customErrors&lt;/tt&gt; mode turned off. &lt;/li&gt;
&lt;li&gt;An e-mail notification of each error at the time it occurs. &lt;/li&gt;
&lt;li&gt;An RSS feed of the last 15 errors from the log.&lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;I remember first reading about ELMAH a few months ago &lt;a bitly="BITLY_PROCESSED" href="http://www.hanselman.com/blog/ELMAHErrorLoggingModulesAndHandlersForASPNETAndMVCToo.aspx" target="_blank" title="ELMAH: Error Logging Modules and Handlers for ASP.NET (and MVC too!)"&gt;on Scott Hanselman’s blog&lt;/a&gt;, which led me to &lt;a bitly="BITLY_PROCESSED" href="http://haacked.com/archive/2007/07/24/securely-implement-elmah-for-plug-and-play-error-logging.aspx" target="_blank" title="Securely Implement ELMAH For Plug And Play Error Logging"&gt;a Phil Haack blog post&lt;/a&gt; and then to &lt;a bitly="BITLY_PROCESSED" href="http://www.codinghorror.com/blog/archives/001239.html" target="_blank" title="Exception-Driven Development"&gt;Jeff Atwood’s Coding Horror&lt;/a&gt;. All of them have nothing but good things to say about ELMAH, and how easy it is to get up and running.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
A couple of weeks ago I decided to get off my rump and see what all of the hoopla was about. Since I’ve been &lt;a bitly="BITLY_PROCESSED" href="http://devadept.com/category/BlogEngine-Experiment.aspx" target="_blank" title="posts about my BlogEngine refatoring experiment"&gt;refactoring&lt;/a&gt; the &lt;a bitly="BITLY_PROCESSED" href="http://www.dotnetblogengine.net/" target="_blank" title="go to the BlogEngine.NET home page"&gt;BlogEngine.NET&lt;/a&gt; engine that runs this site, I’ve often been frustrated with the lack of error logging (and unit tests, but that’s another post). I’ve used &lt;a bitly="BITLY_PROCESSED" href="http://logging.apache.org/log4net/" target="_blank" title="Apache log4net home"&gt;log4net&lt;/a&gt; before, but I have never liked the effort it takes to integrate it into an existing codebase. ELMAH, however, seems to be a perfect fit with the “easy to install, easy to use” attitude of BlogEngine.&lt;br /&gt;
&lt;br /&gt;
The &lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/wiki/WebBase" target="_blank"&gt;ELMAH help pages&lt;/a&gt; along with Scott Hanselman’s and Phil Haack’s posts above give a lot of step-by-step installation instructions, so I’m not going to rehash them here. But, here’s a quick overview of what to expect if you want a basic, fully functional ELMAH installation:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;a bitly="BITLY_PROCESSED" href="http://code.google.com/p/elmah/downloads/list" target="_blank"&gt;Download&lt;/a&gt; the ELMAH binaries&lt;/li&gt;
&lt;li&gt;Copy the ELMAH dll into your &lt;i&gt;bin&lt;/i&gt; directory&lt;/li&gt;
&lt;li&gt;Add a few entries to your web.config file&lt;/li&gt;
&lt;li&gt;That’s it. There is no step 4.&lt;/li&gt;
&lt;/ol&gt;Since I’m still using the out-of-the-box XML provider for BlogEngine, I simply added an “errors” folder in the App_Data directory. (I guess that can be your step 4.) I pointed my ELMAH configuration to save the XML log files in that directory, and everything just works.&lt;br /&gt;
&lt;br /&gt;
I secured the log viewer page as described in Phil Haack’s post, and I then edited the web.sitemap file to add a new admin link pointing to it. That way, when I’m logged in, I can go straight to the errors page with a single click.&lt;br /&gt;
&lt;br /&gt;
Less than 10 minutes later, and I have a pretty good, basic level of exception logging for BlogEngine, without having to add a single line of code. But, for a little context, be sure to read &lt;a bitly="BITLY_PROCESSED" href="http://haacked.com/archive/2007/07/24/securely-implement-elmah-for-plug-and-play-error-logging.aspx#46663" target="_blank"&gt;Atif Aziz’s response&lt;/a&gt; to Phil Haack’s post. Atif is the developer of ELMAH, and among other things, he says:&lt;br /&gt;
&lt;blockquote&gt;It's definitely not a general-purpose logging framework nor one for instrumentation. It only logs unhandled exceptions in a non-invasive way (speaking code-wise). I usually discourage people from using it to log errors in their &lt;code&gt;catch&lt;/code&gt; blocks because that purpose is served better by existing tracing facilities and frameworks and often by actually handling the offending case gracefully in code.&lt;/blockquote&gt;Even so, I think it’s a great tool to have in your ASP.NET toolbox.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-5627139490169113671?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=eUq97ikF52o:DvoZ2yVXuiE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=eUq97ikF52o:DvoZ2yVXuiE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=eUq97ikF52o:DvoZ2yVXuiE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=eUq97ikF52o:DvoZ2yVXuiE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=eUq97ikF52o:DvoZ2yVXuiE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/eUq97ikF52o" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/eUq97ikF52o/tickle-me-elmah.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/09/tickle-me-elmah.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-2834407742893574104</guid><pubDate>Sun, 23 Aug 2009 04:33:00 +0000</pubDate><atom:updated>2010-03-04T16:27:54.853-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Refactoring</category><title>Solo refactoring</title><description>In my &lt;a bitly="BITLY_PROCESSED" href="http://devadept.com/post/2009/08/19/Intention-Revealing-Code.aspx" target="_blank" title="Intention Revealing Code"&gt;most recent post&lt;/a&gt; I described a recent refactoring exercise. Refactoring can be a dangerous exercise, if not done properly. Any time you alter code, there is a risk that a bug or performance issue can be introduced. Hence the strong attraction to the “&lt;a bitly="BITLY_PROCESSED" href="http://c2.com/cgi/wiki?IfItIsWorkingDontChange" target="_blank" title="c2.com : IfItIsWorkingDontChange"&gt;if it ain’t broke, don’t fix it&lt;/a&gt;” rule of thumb.&lt;br /&gt;
&lt;br /&gt;
But if done correctly, &lt;a bitly="BITLY_PROCESSED" href="http://c2.com/cgi/wiki?RefactorMercilessly" target="_blank" title="c2.com : RefactorMercilessly"&gt;refactoring mercilessly&lt;/a&gt; is a very strong practice. According to &lt;a bitly="BITLY_PROCESSED" href="http://www.refactoring.com/" target="_blank" title="refactoring.com"&gt;Martin Fowler&lt;/a&gt;:&lt;br /&gt;
&lt;blockquote&gt;Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior. Its heart is a series of small behavior preserving transformations. Each transformation (called a 'refactoring') does little, but a sequence of transformations can produce a significant restructuring. Since each refactoring is small, it's less likely to go wrong. The system is also kept fully working after each small refactoring, reducing the chances that a system can get seriously broken during the restructuring.&lt;/blockquote&gt;My intent in refactoring the code was to make it more readable and understandable, without changing its external behavior. No adding features, no removing features, no bug fixes. And certainly no &lt;i&gt;new&lt;/i&gt; bugs.&lt;br /&gt;
I think I was pretty successful with the code cleanup part, but I was not careful enough. Just a handful of hours after I posted, a reader named Ivan &lt;a bitly="BITLY_PROCESSED" href="http://devadept.com/post/2009/08/19/Intention-Revealing-Code.aspx#comment" target="_blank" title="read Ivan's comment"&gt;submitted a comment&lt;/a&gt; pointing out a case I had neglected to handle.&lt;br /&gt;
&lt;br /&gt;
A case which &lt;i&gt;was&lt;/i&gt; &lt;i&gt;handled&lt;/i&gt; in the code I changed during my refactoring. I had broken the cardinal rule: I had introduced a bug.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;Ivan, My New Pair&lt;/h2&gt;&lt;br /&gt;
So why did this happen? It would be easy to say that I was just too careless. I worked alone, and didn’t ask for my code to be reviewed. Some would say I shouldn’t have refactored otherwise working code, anyway. I think these things just happen; &lt;i&gt;bugs happen, even to the best of us&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
But there are things we can do to minimize the chance of these bugs seeing the light of day. One of the things our group has been doing more of in the last year or two is &lt;a bitly="BITLY_PROCESSED" href="http://www.extremeprogramming.org/rules/pair.html" target="_blank" title="ExtremeProgramming.org : Pair Programming"&gt;pair programming&lt;/a&gt;. Having a second programmer next to you, keeping you on track by thinking strategically while you’re in tactical mode, helps to keep little errors from sneaking in. On the day I did this refactoring, my programmer pair was unavailable. Rather than try to implement a new feature solo, I thought it would be safer to &lt;a bitly="BITLY_PROCESSED" href="http://www.codinghorror.com/blog/archives/001230.html" target="_blank" title="Coding Horror: Paying Down Your Technical Debt"&gt;pay down some technical debt&lt;/a&gt; with some small refactorings.&lt;br /&gt;
&lt;br /&gt;
Anyway, long story short, the small oversight I made would probably have been caught nearly immediately if I had been &lt;i&gt;pair programming&lt;/i&gt; at the time. In this case, Ivan from the Ukraine, across time and space, was my virtual pair for a few minutes. He noticed one small thing, made one small comment, and put me back on track. Thanks Ivan.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Test, Test, Test&lt;/h2&gt;&lt;br /&gt;
Another way to severely reduce the risk of making breaking changes is with a good set of unit tests. If you have intention revealing code, and those intentions are explicitly asserted by your tests, it’s very hard to unknowingly break things by refactoring. That big red “test failed” indicator stares you right in the face.&lt;br /&gt;
Our group, as are most (I suspect), is still maturing in our unit testing methodology. I personally am still not very comfortable with &lt;a bitly="BITLY_PROCESSED" href="http://c2.com/cgi/wiki?TestDrivenDevelopment" target="_blank" title="c2.com : TestDrivenDevelopment"&gt;Test Driven Development&lt;/a&gt;, but I try to keep all of my code as much under test as possible. In this particular case, there was no test wrapped around the particular situation I had missed and Ivan had pointed out. There is now, though. The next person (pair) who decides to refactor this particular code will have the benefit of a test explicitly reminding them of this case, and each of the other rules the class must follow. The tests are the &lt;a bitly="BITLY_PROCESSED" href="http://www.agilemodeling.com/essays/executableSpecifications.htm" target="_blank" title="agilemodeling.com"&gt;executable specification&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;He can be taught&lt;/h2&gt;&lt;br /&gt;
So what I have learned? I learned that I need to be more careful when changing other people’s code. :-) I learned that pair programming is valuable even for simple code, and even &lt;a bitly="BITLY_PROCESSED" href="http://www.convertunits.com/distance/from/Kiev,+Ukraine/to/Phoenix,+AZ" target="_blank" title="distance from Kiev to Phoenix"&gt;across 10,000 kilometers&lt;/a&gt;. I learned that good tests help not only when first writing the code under test, but perhaps even more when someone else comes along to refactor it. I learned to triple-check any code I post on my blog. And I learned there are some very nice people out there willing to spend a few moments to help a stranger.&lt;br /&gt;
&lt;br /&gt;
To be honest, I thought I knew all of these things before, but I guess it takes a little reminder now and then to refresh one’s memory. That’s probably the most important lesson of the day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-2834407742893574104?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=eNwZlNdU_YA:5JCMFvGdZp4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=eNwZlNdU_YA:5JCMFvGdZp4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=eNwZlNdU_YA:5JCMFvGdZp4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=eNwZlNdU_YA:5JCMFvGdZp4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=eNwZlNdU_YA:5JCMFvGdZp4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/eNwZlNdU_YA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/eNwZlNdU_YA/solo-refactoring.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/08/solo-refactoring.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-5645942647959183947</guid><pubDate>Thu, 20 Aug 2009 00:24:00 +0000</pubDate><atom:updated>2010-03-04T16:28:45.760-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Refactoring</category><category domain="http://www.blogger.com/atom/ns#">Clean Code</category><title>Intention Revealing Code</title><description>I just watched &lt;a bitly="BITLY_PROCESSED" href="http://weblogs.asp.net/rosherove/archive/2009/08/19/ndc-video-robert-martin-clean-code-iii-functions.aspx" target="_blank" title="View the video on Roy Osherove's blog"&gt;the video of Robert Martin’s Norwegian Developers Conference presentation titled “Clean Code III - Functions”&lt;/a&gt;. In his hour-long talk, he talks about methods you can use and principles you should follow to make your code more understandable and more readable. He also show some sample code that is difficult to understand at first reading, and then some refactorings of that code that increase its understandability.&lt;br /&gt;
&lt;br /&gt;
I won’t go into the details of his talk; you should watch it yourself. It’s well worth the hour-long investment. But his refactoring example reminded me of a refactoring exercise that I recently did.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The code in question is a class that provides date-based services such as calculating X number of business days before or after a given date, and determining whether a specific calendar date is a business date or a holiday. To do so, the service must follow these rules for determining holidays:&lt;br /&gt;
&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;Independence Day, July 4 &lt;/li&gt;
&lt;li&gt;Labor Day, first Monday in September &lt;/li&gt;
&lt;li&gt;Thanksgiving Day, fourth Thursday in November &lt;/li&gt;
&lt;li&gt;Day after Thanksgiving Day, fourth Friday in November &lt;/li&gt;
&lt;li&gt;Christmas Day, December 25 &lt;/li&gt;
&lt;li&gt;New Year's Day, January 1 &lt;/li&gt;
&lt;li&gt;Martin Luther King, Jr. Day, third Monday in January &lt;/li&gt;
&lt;li&gt;President's Day, third Monday in February &lt;/li&gt;
&lt;li&gt;Memorial Day, last Monday in May &lt;/li&gt;
&lt;/ul&gt;&lt;/blockquote&gt;&lt;blockquote&gt;Holidays falling on Saturday will be observed on Friday and holidays falling on Sunday will be observed on Monday.&lt;/blockquote&gt;We’ve got nine holidays, some determined by a particular position within a month (i.e. “fourth Thursday in November”), and some determined by a particular calendar date (i.e. “July 4th”). The holidays determined by calendar date may need to be adjusted by a day if the date falls on a weekend. The list of holidays is static; it’s not likely to change anytime soon.&lt;br /&gt;
&lt;br /&gt;
The basic interface of the class is:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;namespace Your.Namespace.Here&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;public interface IDateService&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;DateTime CalculatePriorBusinessDate(DateTime startDate, int numberOfBusinessDays);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;DateTime CalculateSubsequentBusinessDate(DateTime startDate, int numberOfBusinessDays);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;bool IsBusinessDate(DateTime calendarDate);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;bool IsHolidayDate(DateTime calendarDate);&lt;/pre&gt;&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;The implementation of the class is about 270 lines of code, including comments. You know &lt;a bitly="BITLY_PROCESSED" href="http://devadept.com/post/2009/04/26/Unnecessary-comments-must-go.aspx" target="_blank" title="unnecessary comments must go"&gt;how I feel about comments&lt;/a&gt;. Subtract them out, and you’re left with about 230 lines.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;&lt;span id="lnum1"&gt;   1:&lt;/span&gt; namespace Your.Namespace.Here&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum3"&gt;   3:&lt;/span&gt;     public class  DateService : IDateService&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum5"&gt;   5:&lt;/span&gt;         private string error = string.Empty;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum6"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum7"&gt;   7:&lt;/span&gt;         public DateService()&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum8"&gt;   8:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum9"&gt;   9:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum10"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum11"&gt;  11:&lt;/span&gt;         /// &amp;lt;summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum12"&gt;  12:&lt;/span&gt;         ///  Determines if a calendar date is a valid business date.&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum13"&gt;  13:&lt;/span&gt;         /// &amp;lt;/summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum14"&gt;  14:&lt;/span&gt;         /// &amp;lt;param name="calendarDate"&amp;gt;This is any calendar date&amp;lt;/param&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum15"&gt;  15:&lt;/span&gt;         /// &amp;lt;returns&amp;gt;returns true, if calendar date is a valid business date, else returns false&amp;lt;/returns&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum16"&gt;  16:&lt;/span&gt;         /// &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum17"&gt;  17:&lt;/span&gt;         public bool IsBusinessDate(DateTime calendarDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum18"&gt;  18:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum19"&gt;  19:&lt;/span&gt;             bool isBusinessDate = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum20"&gt;  20:&lt;/span&gt;             // Weekends and Holidays are not business days&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum21"&gt;  21:&lt;/span&gt;             if (IsWeekend(calendarDate) || IsHoliday(calendarDate))&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum22"&gt;  22:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum23"&gt;  23:&lt;/span&gt;                 isBusinessDate = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum24"&gt;  24:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum25"&gt;  25:&lt;/span&gt;             else&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum26"&gt;  26:&lt;/span&gt;                 isBusinessDate = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum27"&gt;  27:&lt;/span&gt;             return isBusinessDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum28"&gt;  28:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum29"&gt;  29:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum30"&gt;  30:&lt;/span&gt;         /// &amp;lt;summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum31"&gt;  31:&lt;/span&gt;         ///  Determines if a calendar date is a valid Holiday.&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum32"&gt;  32:&lt;/span&gt;         /// &amp;lt;/summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum33"&gt;  33:&lt;/span&gt;         /// &amp;lt;param name="calendarDate"&amp;gt;This is any calendar date&amp;lt;/param&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum34"&gt;  34:&lt;/span&gt;         /// &amp;lt;returns&amp;gt;returns true, if calendar date is a valid holiday, else returns false&amp;lt;/returns&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum35"&gt;  35:&lt;/span&gt;         /// &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum36"&gt;  36:&lt;/span&gt;         public bool IsHolidayDate(DateTime calendarDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum37"&gt;  37:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum38"&gt;  38:&lt;/span&gt;             bool isHolidayDate = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum39"&gt;  39:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum40"&gt;  40:&lt;/span&gt;             if (IsHoliday(calendarDate))&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum41"&gt;  41:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum42"&gt;  42:&lt;/span&gt;                 isHolidayDate = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum43"&gt;  43:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum44"&gt;  44:&lt;/span&gt;             else&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum45"&gt;  45:&lt;/span&gt;                 isHolidayDate = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum46"&gt;  46:&lt;/span&gt;             return isHolidayDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum47"&gt;  47:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum48"&gt;  48:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum49"&gt;  49:&lt;/span&gt;         /// &amp;lt;summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum50"&gt;  50:&lt;/span&gt;         /// Calculates prior business date &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum51"&gt;  51:&lt;/span&gt;         /// &amp;lt;/summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum52"&gt;  52:&lt;/span&gt;         /// &amp;lt;param name="startDate"&amp;gt;This is the starting business date to calculate&amp;lt;/param&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum53"&gt;  53:&lt;/span&gt;         /// &amp;lt;param name="numberOfBusinessDays"&amp;gt;This is the number of prior business days requested;Must be positive integer&amp;lt;/param&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum54"&gt;  54:&lt;/span&gt;         /// &amp;lt;returns&amp;gt;The calculated business date requested based on number of business days&amp;lt;/returns&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum55"&gt;  55:&lt;/span&gt;         /// &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum56"&gt;  56:&lt;/span&gt;         public DateTime CalculatePriorBusinessDate(DateTime startDate, int numberOfBusinessDays)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum57"&gt;  57:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum58"&gt;  58:&lt;/span&gt;             if (numberOfBusinessDays &amp;lt; 0)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum59"&gt;  59:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum60"&gt;  60:&lt;/span&gt;                 error = "Prior Business Days must be a positive number";&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum61"&gt;  61:&lt;/span&gt;                 throw new Exception(string.Format("reason : {0}", error));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum62"&gt;  62:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum63"&gt;  63:&lt;/span&gt;             return CalculateBusinessDate(startDate, numberOfBusinessDays * -1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum64"&gt;  64:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum65"&gt;  65:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum66"&gt;  66:&lt;/span&gt;         /// &amp;lt;summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum67"&gt;  67:&lt;/span&gt;         /// Calculates subsequent business date &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum68"&gt;  68:&lt;/span&gt;         /// &amp;lt;/summary&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum69"&gt;  69:&lt;/span&gt;         /// &amp;lt;param name="startDate"&amp;gt;This is the starting business date to calculate&amp;lt;/param&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum70"&gt;  70:&lt;/span&gt;         /// &amp;lt;param name="numberOfBusinessDays"&amp;gt;This is the number of subsequent business days requested;Must be positive integer&amp;lt;/param&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum71"&gt;  71:&lt;/span&gt;         /// &amp;lt;returns&amp;gt;The calculated business date requested based on number of business days&amp;lt;/returns&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum72"&gt;  72:&lt;/span&gt;         /// &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum73"&gt;  73:&lt;/span&gt;         public DateTime CalculateSubsequentBusinessDate(DateTime startDate, int numberOfBusinessDays)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum74"&gt;  74:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum75"&gt;  75:&lt;/span&gt;             if (numberOfBusinessDays &amp;lt; 0)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum76"&gt;  76:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum77"&gt;  77:&lt;/span&gt;                 error = "Subsequent Business Days must be a positive number";&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum78"&gt;  78:&lt;/span&gt;                 throw new Exception(string.Format("reason : {0}", error));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum79"&gt;  79:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum80"&gt;  80:&lt;/span&gt;             return CalculateBusinessDate(startDate, numberOfBusinessDays);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum81"&gt;  81:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum82"&gt;  82:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum83"&gt;  83:&lt;/span&gt;         private DateTime CalculateBusinessDate(DateTime startDate, int numberOfDays)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum84"&gt;  84:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum85"&gt;  85:&lt;/span&gt;             int busDays = 0;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum86"&gt;  86:&lt;/span&gt;             DateTime curDate = startDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum87"&gt;  87:&lt;/span&gt;             int incr = 1;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum88"&gt;  88:&lt;/span&gt;             if (numberOfDays &amp;lt; 0)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum89"&gt;  89:&lt;/span&gt;                 incr = -1;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum90"&gt;  90:&lt;/span&gt;             while (busDays &amp;lt; Math.Abs(numberOfDays))&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum91"&gt;  91:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum92"&gt;  92:&lt;/span&gt;                 curDate = curDate.AddDays(incr);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum93"&gt;  93:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum94"&gt;  94:&lt;/span&gt;                 // Weekends and Holidays are not business days&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum95"&gt;  95:&lt;/span&gt;                 if (IsWeekend(curDate) || IsHoliday(curDate))&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum96"&gt;  96:&lt;/span&gt;                 { }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum97"&gt;  97:&lt;/span&gt;                 else&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum98"&gt;  98:&lt;/span&gt;                     busDays = busDays + 1;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum99"&gt;  99:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum100"&gt; 100:&lt;/span&gt;             return curDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum101"&gt; 101:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum102"&gt; 102:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum103"&gt; 103:&lt;/span&gt;         private bool IsWeekend(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum104"&gt; 104:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum105"&gt; 105:&lt;/span&gt;             bool isOnWeekend = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum106"&gt; 106:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum107"&gt; 107:&lt;/span&gt;             //Check for weekend date&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum108"&gt; 108:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum109"&gt; 109:&lt;/span&gt;             if (curDate.DayOfWeek == DayOfWeek.Saturday || curDate.DayOfWeek == DayOfWeek.Sunday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum110"&gt; 110:&lt;/span&gt;                 isOnWeekend = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum111"&gt; 111:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum112"&gt; 112:&lt;/span&gt;             return isOnWeekend;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum113"&gt; 113:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum114"&gt; 114:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum115"&gt; 115:&lt;/span&gt;         private bool IsHoliday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum116"&gt; 116:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum117"&gt; 117:&lt;/span&gt;             bool returnValue = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum118"&gt; 118:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum119"&gt; 119:&lt;/span&gt;             // Check for New Year's, Christmas, and Independence Day&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum120"&gt; 120:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum121"&gt; 121:&lt;/span&gt;             if (curDate.Month == 1 &amp;amp;&amp;amp; curDate.Day == 1)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum122"&gt; 122:&lt;/span&gt;                 returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum123"&gt; 123:&lt;/span&gt;             if (curDate.Month == 7 &amp;amp;&amp;amp; curDate.Day == 4)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum124"&gt; 124:&lt;/span&gt;                 returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum125"&gt; 125:&lt;/span&gt;             if (curDate.Month == 12 &amp;amp;&amp;amp; curDate.Day == 25)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum126"&gt; 126:&lt;/span&gt;                 returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum127"&gt; 127:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum128"&gt; 128:&lt;/span&gt;             // Friday is a holiday if actual holiday falls on Saturday&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum129"&gt; 129:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum130"&gt; 130:&lt;/span&gt;             if (curDate.DayOfWeek == DayOfWeek.Friday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum131"&gt; 131:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum132"&gt; 132:&lt;/span&gt;                 if (curDate.Month == 12 &amp;amp;&amp;amp; curDate.Day == 31)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum133"&gt; 133:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum134"&gt; 134:&lt;/span&gt;                 if (curDate.Month == 7 &amp;amp;&amp;amp; curDate.Day == 3)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum135"&gt; 135:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum136"&gt; 136:&lt;/span&gt;                 if (curDate.Month == 12 &amp;amp;&amp;amp; curDate.Day == 24)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum137"&gt; 137:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum138"&gt; 138:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum139"&gt; 139:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum140"&gt; 140:&lt;/span&gt;             // Monday is a holiday if actual holiday falls on Sunday&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum141"&gt; 141:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum142"&gt; 142:&lt;/span&gt;             if (curDate.DayOfWeek == DayOfWeek.Monday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum143"&gt; 143:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum144"&gt; 144:&lt;/span&gt;                 if (curDate.Month == 1 &amp;amp;&amp;amp; curDate.Day == 2)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum145"&gt; 145:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum146"&gt; 146:&lt;/span&gt;                 if (curDate.Month == 7 &amp;amp;&amp;amp; curDate.Day == 5)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum147"&gt; 147:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum148"&gt; 148:&lt;/span&gt;                 if (curDate.Month == 12 &amp;amp;&amp;amp; curDate.Day == 26)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum149"&gt; 149:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum150"&gt; 150:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum151"&gt; 151:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum152"&gt; 152:&lt;/span&gt;             // Test for Monday Holidays&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum153"&gt; 153:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum154"&gt; 154:&lt;/span&gt;             if (curDate.DayOfWeek == DayOfWeek.Monday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum155"&gt; 155:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum156"&gt; 156:&lt;/span&gt;                 if (curDate.Month == 1 &amp;amp;&amp;amp; WhichMonday(curDate) == 3)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum157"&gt; 157:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum158"&gt; 158:&lt;/span&gt;                 if (curDate.Month == 2 &amp;amp;&amp;amp; WhichMonday(curDate) == 3)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum159"&gt; 159:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum160"&gt; 160:&lt;/span&gt;                 if (curDate.Month == 9 &amp;amp;&amp;amp; WhichMonday(curDate) == 1)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum161"&gt; 161:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum162"&gt; 162:&lt;/span&gt;                 if (curDate.Month == 5 &amp;amp;&amp;amp; LastMondayInMay(curDate) == true)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum163"&gt; 163:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum164"&gt; 164:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum165"&gt; 165:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum166"&gt; 166:&lt;/span&gt;             // Test for Thanksgiving&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum167"&gt; 167:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum168"&gt; 168:&lt;/span&gt;             if (curDate.DayOfWeek == DayOfWeek.Thursday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum169"&gt; 169:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum170"&gt; 170:&lt;/span&gt;                 if (curDate.Month == 11 &amp;amp;&amp;amp; WhichThursday(curDate) == 4)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum171"&gt; 171:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum172"&gt; 172:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum173"&gt; 173:&lt;/span&gt;             // Test for Friday after Thanksgiving&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum174"&gt; 174:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum175"&gt; 175:&lt;/span&gt;             if (curDate.DayOfWeek == DayOfWeek.Friday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum176"&gt; 176:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum177"&gt; 177:&lt;/span&gt;                 if (curDate.Month == 11 &amp;amp;&amp;amp; WhichFriday(curDate) == 4)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum178"&gt; 178:&lt;/span&gt;                     returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum179"&gt; 179:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum180"&gt; 180:&lt;/span&gt;             return returnValue;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum181"&gt; 181:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum182"&gt; 182:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum183"&gt; 183:&lt;/span&gt;         private int WhichMonday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum184"&gt; 184:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum185"&gt; 185:&lt;/span&gt;             return WhichDay(curDate, DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum186"&gt; 186:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum187"&gt; 187:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum188"&gt; 188:&lt;/span&gt;         private int WhichDay(DateTime curDate, DayOfWeek day)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum189"&gt; 189:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum190"&gt; 190:&lt;/span&gt;             int which = 0;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum191"&gt; 191:&lt;/span&gt;             DateTime firstDay = GetFirstDay(curDate, day);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum192"&gt; 192:&lt;/span&gt;             while (firstDay &amp;lt;= curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum193"&gt; 193:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum194"&gt; 194:&lt;/span&gt;                 which += 1;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum195"&gt; 195:&lt;/span&gt;                 if (curDate == firstDay)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum196"&gt; 196:&lt;/span&gt;                     break;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum197"&gt; 197:&lt;/span&gt;                 firstDay = firstDay.AddDays(7);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum198"&gt; 198:&lt;/span&gt;                 if (firstDay.Month != curDate.Month)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum199"&gt; 199:&lt;/span&gt;                 {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum200"&gt; 200:&lt;/span&gt;                     throw new Exception("WhichDayError");&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum201"&gt; 201:&lt;/span&gt;                 }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum202"&gt; 202:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum203"&gt; 203:&lt;/span&gt;             return which;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum204"&gt; 204:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum205"&gt; 205:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum206"&gt; 206:&lt;/span&gt;         private DateTime GetFirstMonday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum207"&gt; 207:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum208"&gt; 208:&lt;/span&gt;             return GetFirstDay(curDate, DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum209"&gt; 209:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum210"&gt; 210:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum211"&gt; 211:&lt;/span&gt;         private DateTime GetLastMonday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum212"&gt; 212:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum213"&gt; 213:&lt;/span&gt;             return GetLastDay(curDate, DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum214"&gt; 214:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum215"&gt; 215:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum216"&gt; 216:&lt;/span&gt;         private DateTime GetFirstDay(DateTime curDate, DayOfWeek day)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum217"&gt; 217:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum218"&gt; 218:&lt;/span&gt;             DateTime myDate = new DateTime(curDate.Year, curDate.Month, 1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum219"&gt; 219:&lt;/span&gt;             while (myDate.DayOfWeek != day)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum220"&gt; 220:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum221"&gt; 221:&lt;/span&gt;                 myDate = myDate.AddDays(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum222"&gt; 222:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum223"&gt; 223:&lt;/span&gt;             return myDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum224"&gt; 224:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum225"&gt; 225:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum226"&gt; 226:&lt;/span&gt;         private DateTime GetLastDay(DateTime curDate, DayOfWeek day)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum227"&gt; 227:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum228"&gt; 228:&lt;/span&gt;             DateTime myDateTemp = curDate.AddMonths(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum229"&gt; 229:&lt;/span&gt;             DateTime myDate = new DateTime(myDateTemp.Year, myDateTemp.Month, 1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum230"&gt; 230:&lt;/span&gt;             myDate = myDate.AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum231"&gt; 231:&lt;/span&gt;             while (myDate.DayOfWeek != day)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum232"&gt; 232:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum233"&gt; 233:&lt;/span&gt;                 myDate = myDate.AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum234"&gt; 234:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum235"&gt; 235:&lt;/span&gt;             return myDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum236"&gt; 236:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum237"&gt; 237:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum238"&gt; 238:&lt;/span&gt;         private bool LastMondayInMay(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum239"&gt; 239:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum240"&gt; 240:&lt;/span&gt;             bool rv = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum241"&gt; 241:&lt;/span&gt;             DateTime curMonday = GetLastMonday(curDate);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum242"&gt; 242:&lt;/span&gt;             if (curMonday == curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum243"&gt; 243:&lt;/span&gt;                 rv = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum244"&gt; 244:&lt;/span&gt;             return rv;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum245"&gt; 245:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum246"&gt; 246:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum247"&gt; 247:&lt;/span&gt;         private int WhichThursday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum248"&gt; 248:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum249"&gt; 249:&lt;/span&gt;             return WhichDay(curDate, DayOfWeek.Thursday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum250"&gt; 250:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum251"&gt; 251:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum252"&gt; 252:&lt;/span&gt;         private DateTime GetFirstThursday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum253"&gt; 253:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum254"&gt; 254:&lt;/span&gt;             return GetFirstDay(curDate, DayOfWeek.Thursday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum255"&gt; 255:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum256"&gt; 256:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum257"&gt; 257:&lt;/span&gt;         private int WhichFriday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum258"&gt; 258:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum259"&gt; 259:&lt;/span&gt;             return WhichDay(curDate, DayOfWeek.Friday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum260"&gt; 260:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum261"&gt; 261:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum262"&gt; 262:&lt;/span&gt;         private DateTime GetFirstFriday(DateTime curDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum263"&gt; 263:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum264"&gt; 264:&lt;/span&gt;             DateTime myDate = new DateTime(curDate.Year, curDate.Month, 1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum265"&gt; 265:&lt;/span&gt;             while (myDate.DayOfWeek != DayOfWeek.Friday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum266"&gt; 266:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum267"&gt; 267:&lt;/span&gt;                 myDate = myDate.AddDays(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum268"&gt; 268:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum269"&gt; 269:&lt;/span&gt;             return myDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum270"&gt; 270:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum271"&gt; 271:&lt;/span&gt;     }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum272"&gt; 272:&lt;/span&gt; }&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Functionally, this code is fine. It meets all of the requirements, can correctly determine if a particular calendar date is a holiday, can correctly determine a previous or subsequent business date. But… It’s not very readable. By that I mean, can we read through the code and, at a glance, determine the rules it’s implementing? Can we see that Labor Day is accounted for? Can we tell that Saturday holidays are shifted to Friday? Not without mentally debugging it, line by line. The &lt;i&gt;intent&lt;/i&gt; of the code (to meet the holiday calculation rules) is not revealed by reading the code. You’re left to figure it out yourself.&lt;br /&gt;
&lt;br /&gt;
Some of the code loses readability by being too verbose. Take, for instance, the method used to determine if a particular date is a business date:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;public bool IsBusinessDate(DateTime calendarDate)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;bool isBusinessDate = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;// Weekends and Holidays are not business days&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;if (IsWeekend(calendarDate) || IsHoliday(calendarDate))&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;isBusinessDate = false;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;else&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;isBusinessDate = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;return isBusinessDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;That’s 11 lines of code (and one in-line comment) to express what could be expressed in one:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;public bool IsBusinessDate(DateTime date)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;return !IsWeekend(date) &amp;amp;&amp;amp; !IsHoliday(date);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Not a weekend and not a holiday. Done. Smaller is &lt;i&gt;not always&lt;/i&gt; better, but in this case I think it makes the code more precise and expressive while also minimizing the potential for a bugs to creep in.&lt;br /&gt;
&lt;br /&gt;
Additionally, read through this block in the middle of the IsHoliday() method:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;if (curDate.DayOfWeek == DayOfWeek.Monday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;if (curDate.Month == 1 &amp;amp;&amp;amp; WhichMonday(curDate) == 3)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;if (curDate.Month == 2 &amp;amp;&amp;amp; WhichMonday(curDate) == 3)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;if (curDate.Month == 9 &amp;amp;&amp;amp; WhichMonday(curDate) == 1)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;if (curDate.Month == 5 &amp;amp;&amp;amp; LastMondayInMay(curDate) == true)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;returnValue = true;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;It is not immediately obvious what’s going on here. If you have the holidays memorized, you can tell that we’re checking for Martin Luther King, Jr. Day, Memorial Day, and a few other Monday holidays. But you have to stop and think about it, doing the mental calendar math to determine which holidays we’re dealing with. It would be better if the code expressed this explicitly.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Taking a step back&lt;/h2&gt;&lt;br /&gt;
Before starting any refactoring, a decided to take a step back and think about how I would go about determining if a date was a holiday. The most straightforward way is to get a list of holidays, and then check my date against that list. That list of holidays must include the nine holidays listed in the rules above, adjusted for weekends if necessary.&lt;br /&gt;
&lt;br /&gt;
I began the refactoring with that process in mind. To start with, I would need to generate the holiday list for the given year. So, I created a method to do so:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;public IList&amp;lt;DateTime&amp;gt; HolidaysForYear(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;var holidayList = new List&amp;lt;DateTime&amp;gt;();&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;holidayList.Add(NewYearsDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;holidayList.Add(MLKDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;holidayList.Add(PresidentsDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;holidayList.Add(MemorialDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;holidayList.Add(IndependenceDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;holidayList.Add(LaborDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;holidayList.Add(ThanksgivingDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;holidayList.Add(DayAfterThanksgivingDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;holidayList.Add(ChristmasDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;return holidayList;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;After reading this method, there should be no doubt which holidays are accounted for. The intention of the method is explicit.&lt;br /&gt;
&lt;br /&gt;
Since some of the holidays may fall on a Saturday or Sunday, they may need to be adjusted back a day (for Saturday) or forward a day (for Sunday). Hence:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;private DateTime AdjustForWeekend(DateTime holiday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;DateTime adjustedHoliday = holiday;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;switch (holiday.DayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;case DayOfWeek.Saturday:&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;adjustedHoliday = holiday.AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;break;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;case DayOfWeek.Sunday:&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;adjustedHoliday = holiday.AddDays(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;break;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;default:&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;break;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;return adjustedHoliday;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;We are explicitly implementing the “Holidays falling on Saturday will be observed on Friday and holidays falling on Sunday will be observed on Monday” rule. This allows us to calculate date-based holidays like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;private DateTime NewYearsDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;var januaryFirst = new DateTime(year, 1, 1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;return AdjustForWeekend(januaryFirst);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;New Year’s Day is January 1st, adjusted for weekends.&lt;br /&gt;
&lt;br /&gt;
Next we have to deal with positional holidays, like the Labor Day (first Monday in September). I kept a couple of the helper methods that the original code had, only slightly altered:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;private DateTime GetFirstDay(DateTime date, DayOfWeek dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;var dateToCheck = new DateTime(date.Year, date.Month, 1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;while (dateToCheck.DayOfWeek != dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;dateToCheck = dateToCheck.AddDays(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;return dateToCheck;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;private DateTime GetLastDay(DateTime date, DayOfWeek dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;var followingMonth = date.AddMonths(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;var dateToCheck = new DateTime(followingMonth.Year, followingMonth.Month, 1).AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;while (dateToCheck.DayOfWeek != dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;dateToCheck = dateToCheck.AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;return dateToCheck;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Now that we can get the first or last DayOfWeek of any month, we can calculate all of the other holidays. Here’s Labor Day:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;private DateTime LaborDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;var firstMondayInSeptember = GetFirstDay(new DateTime(year, 9, 1), DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;return firstMondayInSeptember;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;In this case, I used a descriptive variable (firstMondayInSeptember) to add expressiveness, even though it isn’t necessary. It’s usefulness is more obvious when calculating Thanksgiving:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;private DateTime ThanksgivingDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;var firstThursdayInNovember = GetFirstDay(new DateTime(year, 11, 1), DayOfWeek.Thursday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;var fourthThursdayInNovember = firstThursdayInNovember.AddDays(21);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;return fourthThursdayInNovember;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;}&lt;/pre&gt;&lt;pre class="alteven"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;Now that we have a list of holidays, we can check against that list to figure out if a given date is a holiday:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;public bool IsHoliday(DateTime date)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;var dateToCheckFor = new DateTime(date.Year, date.Month, date.Day);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;return HolidaysForYear(date.Year).Contains(dateToCheckFor);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;}&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;I kept much of the rest of the code the same, and I’ll leave it up to you to find other refactorings. But the end result, I hope, is &lt;i&gt;Intention Revealing&lt;/i&gt; code. It not only meets the requirements, but does so in a way that explicitly reveals the requirements it was intended for. Incidentally, the final version has about 22% fewer lines of code (although reducing lines of code was not the goal).&lt;br /&gt;
&lt;br /&gt;
Here is the final version after refactoring:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;&lt;span id="lnum1"&gt;   1:&lt;/span&gt; namespace Your.Namespace.Here&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum3"&gt;   3:&lt;/span&gt;     public class  DateService : IDateService&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum5"&gt;   5:&lt;/span&gt;         public DateProviderService()&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum6"&gt;   6:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum7"&gt;   7:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum8"&gt;   8:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum9"&gt;   9:&lt;/span&gt;         public bool IsBusinessDate(DateTime date)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum10"&gt;  10:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum11"&gt;  11:&lt;/span&gt;             return !IsWeekend(date) &amp;amp;&amp;amp; !IsHoliday(date);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum12"&gt;  12:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum13"&gt;  13:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum14"&gt;  14:&lt;/span&gt;         public bool IsWeekend(DateTime date)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum15"&gt;  15:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum16"&gt;  16:&lt;/span&gt;             var dayOfWeek = date.DayOfWeek;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum17"&gt;  17:&lt;/span&gt;             return dayOfWeek == DayOfWeek.Saturday || dayOfWeek == DayOfWeek.Sunday;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum18"&gt;  18:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum19"&gt;  19:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum20"&gt;  20:&lt;/span&gt;         public bool IsHoliday(DateTime date)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum21"&gt;  21:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum22"&gt;  22:&lt;/span&gt;             var dateToCheckFor = new DateTime(date.Year, date.Month, date.Day);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum23"&gt;  23:&lt;/span&gt;             return HolidaysForYear(date.Year).Contains(dateToCheckFor);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum24"&gt;  24:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum25"&gt;  25:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum26"&gt;  26:&lt;/span&gt;         public DateTime CalculatePriorBusinessDate(DateTime fromDate, int numberOfBusinessDays)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum27"&gt;  27:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum28"&gt;  28:&lt;/span&gt;             if (numberOfBusinessDays &amp;lt; 0)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum29"&gt;  29:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum30"&gt;  30:&lt;/span&gt;                 string error = "Prior Business Days must be a positive number";&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum31"&gt;  31:&lt;/span&gt;                 throw new Exception(string.Format("reason : {0}", error));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum32"&gt;  32:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum33"&gt;  33:&lt;/span&gt;             return CalculateBusinessDate(fromDate, numberOfBusinessDays * -1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum34"&gt;  34:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum35"&gt;  35:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum36"&gt;  36:&lt;/span&gt;         public DateTime CalculateSubsequentBusinessDate(DateTime fromDate, int numberOfBusinessDays)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum37"&gt;  37:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum38"&gt;  38:&lt;/span&gt;             if (numberOfBusinessDays &amp;lt; 0)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum39"&gt;  39:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum40"&gt;  40:&lt;/span&gt;                 string error = "Subsequent Business Days must be a positive number";&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum41"&gt;  41:&lt;/span&gt;                 throw new Exception(string.Format("reason : {0}", error));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum42"&gt;  42:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum43"&gt;  43:&lt;/span&gt;             return CalculateBusinessDate(fromDate, numberOfBusinessDays);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum44"&gt;  44:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum45"&gt;  45:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum46"&gt;  46:&lt;/span&gt;         public IList&amp;lt;DateTime&amp;gt; HolidaysForYear(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum47"&gt;  47:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum48"&gt;  48:&lt;/span&gt;             var holidayList = new List&amp;lt;DateTime&amp;gt;();&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum49"&gt;  49:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum50"&gt;  50:&lt;/span&gt;             holidayList.Add(NewYearsDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum51"&gt;  51:&lt;/span&gt;             holidayList.Add(MLKDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum52"&gt;  52:&lt;/span&gt;             holidayList.Add(PresidentsDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum53"&gt;  53:&lt;/span&gt;             holidayList.Add(MemorialDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum54"&gt;  54:&lt;/span&gt;             holidayList.Add(IndependenceDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum55"&gt;  55:&lt;/span&gt;             holidayList.Add(LaborDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum56"&gt;  56:&lt;/span&gt;             holidayList.Add(ThanksgivingDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum57"&gt;  57:&lt;/span&gt;             holidayList.Add(DayAfterThanksgivingDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum58"&gt;  58:&lt;/span&gt;             holidayList.Add(ChristmasDay(year));&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum59"&gt;  59:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum60"&gt;  60:&lt;/span&gt;             return holidayList;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum61"&gt;  61:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum62"&gt;  62:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum63"&gt;  63:&lt;/span&gt;         private DateTime CalculateBusinessDate(DateTime fromDate, int numberOfDays)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum64"&gt;  64:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum65"&gt;  65:&lt;/span&gt;             int businessDayCount = 0;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum66"&gt;  66:&lt;/span&gt;             int incrementValue = numberOfDays &amp;lt; 0 ? -1 : 1;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum67"&gt;  67:&lt;/span&gt;             DateTime finalDate = fromDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum68"&gt;  68:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum69"&gt;  69:&lt;/span&gt;             while (businessDayCount &amp;lt; Math.Abs(numberOfDays))&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum70"&gt;  70:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum71"&gt;  71:&lt;/span&gt;                 finalDate = finalDate.AddDays(incrementValue);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum72"&gt;  72:&lt;/span&gt;                 if (IsBusinessDate(finalDate))&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum73"&gt;  73:&lt;/span&gt;                 {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum74"&gt;  74:&lt;/span&gt;                     businessDayCount++;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum75"&gt;  75:&lt;/span&gt;                 }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum76"&gt;  76:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum77"&gt;  77:&lt;/span&gt;             return finalDate;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum78"&gt;  78:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum79"&gt;  79:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum80"&gt;  80:&lt;/span&gt;         private DateTime NewYearsDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum81"&gt;  81:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum82"&gt;  82:&lt;/span&gt;             var januaryFirst = new DateTime(year, 1, 1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum83"&gt;  83:&lt;/span&gt;             return AdjustForWeekend(januaryFirst);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum84"&gt;  84:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum85"&gt;  85:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum86"&gt;  86:&lt;/span&gt;         private DateTime MLKDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum87"&gt;  87:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum88"&gt;  88:&lt;/span&gt;             var firstMondayInJanuary = GetFirstDay(new DateTime(year, 1, 1), DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum89"&gt;  89:&lt;/span&gt;             var thirdMondayInJanuary = firstMondayInJanuary.AddDays(14);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum90"&gt;  90:&lt;/span&gt;             return thirdMondayInJanuary;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum91"&gt;  91:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum92"&gt;  92:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum93"&gt;  93:&lt;/span&gt;         private DateTime PresidentsDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum94"&gt;  94:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum95"&gt;  95:&lt;/span&gt;             var firstMondayInFebruary = GetFirstDay(new DateTime(year, 2, 1), DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum96"&gt;  96:&lt;/span&gt;             var thirdMondayInFebruary = firstMondayInFebruary.AddDays(14);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum97"&gt;  97:&lt;/span&gt;             return thirdMondayInFebruary;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum98"&gt;  98:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum99"&gt;  99:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum100"&gt; 100:&lt;/span&gt;         private DateTime MemorialDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum101"&gt; 101:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum102"&gt; 102:&lt;/span&gt;             var lastMondayInMay = GetLastDay(new DateTime(year, 5, 1), DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum103"&gt; 103:&lt;/span&gt;             return lastMondayInMay;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum104"&gt; 104:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum105"&gt; 105:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum106"&gt; 106:&lt;/span&gt;         private DateTime IndependenceDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum107"&gt; 107:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum108"&gt; 108:&lt;/span&gt;             var julyFourth = new DateTime(year, 7, 4);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum109"&gt; 109:&lt;/span&gt;             return AdjustForWeekend(julyFourth);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum110"&gt; 110:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum111"&gt; 111:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum112"&gt; 112:&lt;/span&gt;         private DateTime LaborDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum113"&gt; 113:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum114"&gt; 114:&lt;/span&gt;             var firstMondayInSeptember = GetFirstDay(new DateTime(year, 9, 1), DayOfWeek.Monday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum115"&gt; 115:&lt;/span&gt;             return firstMondayInSeptember;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum116"&gt; 116:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum117"&gt; 117:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum118"&gt; 118:&lt;/span&gt;         private DateTime ThanksgivingDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum119"&gt; 119:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum120"&gt; 120:&lt;/span&gt;             var firstThursdayInNovember = GetFirstDay(new DateTime(year, 11, 1), DayOfWeek.Thursday);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum121"&gt; 121:&lt;/span&gt;             var fourthThursdayInNovember = firstThursdayInNovember.AddDays(21);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum122"&gt; 122:&lt;/span&gt;             return fourthThursdayInNovember;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum123"&gt; 123:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum124"&gt; 124:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum125"&gt; 125:&lt;/span&gt;         private DateTime DayAfterThanksgivingDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum126"&gt; 126:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum127"&gt; 127:&lt;/span&gt;             return ThanksgivingDay(year).AddDays(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum128"&gt; 128:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum129"&gt; 129:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum130"&gt; 130:&lt;/span&gt;         private DateTime ChristmasDay(int year)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum131"&gt; 131:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum132"&gt; 132:&lt;/span&gt;             var decemberTwentyFifth = new DateTime(year, 12, 25);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum133"&gt; 133:&lt;/span&gt;             return AdjustForWeekend(decemberTwentyFifth);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum134"&gt; 134:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum135"&gt; 135:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum136"&gt; 136:&lt;/span&gt;         private DateTime AdjustForWeekend(DateTime holiday)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum137"&gt; 137:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum138"&gt; 138:&lt;/span&gt;             DateTime adjustedHoliday = holiday;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum139"&gt; 139:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum140"&gt; 140:&lt;/span&gt;             switch (holiday.DayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum141"&gt; 141:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum142"&gt; 142:&lt;/span&gt;                 case DayOfWeek.Saturday:&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum143"&gt; 143:&lt;/span&gt;                     adjustedHoliday = holiday.AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum144"&gt; 144:&lt;/span&gt;                     break;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum145"&gt; 145:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum146"&gt; 146:&lt;/span&gt;                 case DayOfWeek.Sunday:&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum147"&gt; 147:&lt;/span&gt;                     adjustedHoliday = holiday.AddDays(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum148"&gt; 148:&lt;/span&gt;                     break;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum149"&gt; 149:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum150"&gt; 150:&lt;/span&gt;                 default:&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum151"&gt; 151:&lt;/span&gt;                     break;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum152"&gt; 152:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum153"&gt; 153:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum154"&gt; 154:&lt;/span&gt;             return adjustedHoliday;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum155"&gt; 155:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum156"&gt; 156:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum157"&gt; 157:&lt;/span&gt;         private DateTime GetFirstDay(DateTime date, DayOfWeek dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum158"&gt; 158:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum159"&gt; 159:&lt;/span&gt;             var dateToCheck = new DateTime(date.Year, date.Month, 1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum160"&gt; 160:&lt;/span&gt;             while (dateToCheck.DayOfWeek != dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum161"&gt; 161:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum162"&gt; 162:&lt;/span&gt;                 dateToCheck = dateToCheck.AddDays(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum163"&gt; 163:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum164"&gt; 164:&lt;/span&gt;             return dateToCheck;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum165"&gt; 165:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum166"&gt; 166:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum167"&gt; 167:&lt;/span&gt;         private DateTime GetLastDay(DateTime date, DayOfWeek dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum168"&gt; 168:&lt;/span&gt;         {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum169"&gt; 169:&lt;/span&gt;             var followingMonth = date.AddMonths(1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum170"&gt; 170:&lt;/span&gt;             var dateToCheck = new DateTime(followingMonth.Year, followingMonth.Month, 1).AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum171"&gt; 171:&lt;/span&gt;  &lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum172"&gt; 172:&lt;/span&gt;             while (dateToCheck.DayOfWeek != dayOfWeek)&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum173"&gt; 173:&lt;/span&gt;             {&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum174"&gt; 174:&lt;/span&gt;                 dateToCheck = dateToCheck.AddDays(-1);&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum175"&gt; 175:&lt;/span&gt;             }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum176"&gt; 176:&lt;/span&gt;             return dateToCheck;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum177"&gt; 177:&lt;/span&gt;         }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alteven"&gt;&lt;span id="lnum178"&gt; 178:&lt;/span&gt;     }&lt;/pre&gt;&lt;br /&gt;
&lt;pre class="alt"&gt;&lt;span id="lnum179"&gt; 179:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-5645942647959183947?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=MMWJWJfJPYk:3_zieMb3_eU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=MMWJWJfJPYk:3_zieMb3_eU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=MMWJWJfJPYk:3_zieMb3_eU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=MMWJWJfJPYk:3_zieMb3_eU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=MMWJWJfJPYk:3_zieMb3_eU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/MMWJWJfJPYk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/MMWJWJfJPYk/intention-revealing-code.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/08/intention-revealing-code.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-784696725841853067</guid><pubDate>Thu, 21 May 2009 00:10:00 +0000</pubDate><atom:updated>2010-01-23T21:36:17.038-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Refactoring</category><category domain="http://www.blogger.com/atom/ns#">BlogEngine Experiment</category><title>The domain object that does everything</title><description>Continuing with my open ended series of posts whereby I conduct a &lt;a href="http://devadept.com/category/BlogEngine-Experiment.aspx" target="_blank" title="BlogEngine Experiment"&gt;refactoring experiment&lt;/a&gt; with &lt;a href="http://www.dotnetblogengine.net/" target="_blank" title="go to the BlogEngine.NET home page"&gt;BlogEngine.NET&lt;/a&gt; …&lt;br /&gt;
&lt;br /&gt;
In my previous post ( &lt;a href="http://devadept.com/post/2009/05/07/Better-readability-using-ListForEach%28%29-and-lambda-expressions.aspx" target="_blank" title="Better readability using List.ForEach() and lambda expressions"&gt;Better readability using List.ForEach() and lambda expressions&lt;/a&gt; ) I refactored the newly created Catalog class and was left with some method calls that looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;Post.PublishedPosts.ForEach(post =&amp;gt; post.AddToCatalog());&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;The method for accessing the list of posts resides in the &lt;span style="font-family: Courier New;"&gt;Post&lt;/span&gt; class itself, making the data access syntax somewhat similar to how it’s done with the &lt;a href="http://en.wikipedia.org/wiki/Active_record_pattern" target="_blank" title="ActiveRecord on wikipedia"&gt;ActiveRecord&lt;/a&gt; pattern or &lt;a href="http://www.lhotka.net/cslanet/" target="_blank" title="CSLA.NET on Rocky Lhotka's site"&gt;CSLA&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I don’t particularly like this structure, because it mixes what I consider to be two different concerns: domain (entity) logic and data persistence. It gives the Post class at least two distinct reasons to change, violating the &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank" title="look it up on Wikipedia"&gt;Single Responsibility Principle&lt;/a&gt; and making the class probably a little more complex than it could be.&lt;br /&gt;
&lt;br /&gt;
So, I decided to dive into the &lt;span style="font-family: Courier New;"&gt;Post.cs&lt;/span&gt; file and see what I could do to simplify the class and remove some of the concerns that don’t fit directly in the domain object. What exactly is in the Post class? What does it do? After a quick once-through, I could see that the Post class:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Has properties that define the “Post” entity, like Title, Author, Content, etc. &lt;/li&gt;
&lt;li&gt;Has event handlers that fire when posts are added, removed, rated, etc. &lt;/li&gt;
&lt;li&gt;Manages an in-memory list of “Post” entities &lt;/li&gt;
&lt;li&gt;Coordinates persistence to the data store by using the BlogService class &lt;/li&gt;
&lt;li&gt;Formats its own relative, absolute, trackback, and permalink URIs by accessing the Utils and BlogSettings classes &lt;/li&gt;
&lt;li&gt;Sends its own emails by calling out to the Utils class &lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
There’s a &lt;span style="text-decoration: underline;"&gt;lot&lt;/span&gt; going on in there. Personally, I think the domain object / entity class only needs to be concerned with the first two items in the list, and it should delegate out the rest of the stuff.&lt;br /&gt;
&lt;br /&gt;
For the persistence, what I would prefer to see is something more like the &lt;a href="http://martinfowler.com/eaaCatalog/repository.html" target="_blank" title="Martin Fowler on the Repository"&gt;Repository pattern&lt;/a&gt; used in &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design" target="_blank" title="Domain Driven Design on wikipedia"&gt;Domain Driven Design&lt;/a&gt;. With a repository, all of the persistence is routed through a single class that acts “like an in-memory domain object collection.” Which, coincidentally, is exactly what’s stuffed inside the Post class. I just need to let it out.&lt;br /&gt;
&lt;br /&gt;
In our case, the Post repository would be a class called &lt;span style="font-family: Courier New;"&gt;Posts&lt;/span&gt;, physically and logically separated from the domain object’s &lt;span style="font-family: Courier New;"&gt;Post&lt;/span&gt; class. We would end up with something that looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;Posts.Published.ForEach(post =&amp;gt; post.AddToCatalog());&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;From a syntax perspective, there’s only a subtle difference, but it’s an important one. We’re now treating the collection of Posts as a first-class object. And, by separating the persistence concerns out of the &lt;span style="font-family: Courier New;"&gt;Post.cs&lt;/span&gt; class, it becomes much simpler and easier to maintain. As does the repository (&lt;span style="font-family: Courier New;"&gt;Posts.cs&lt;/span&gt;) itself.&lt;br /&gt;
&lt;br /&gt;
Persistence, however, isn’t the only external concern that needs to be pulled out. The URI generation is now in a class called RoutingAgent, which is also where I placed former Utils methods that calculate the RelativeWebRoot and AbsoluteWebRoot and such. The email logic is in the MailAgent class, as an extension method:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="csharpcode-wrapper" id="codeSnippetWrapper"&gt;&lt;div class="csharpcode" id="codeSnippet"&gt;&lt;pre class="alt"&gt;public static void SendNotifications(this Comment comment, Post post)&lt;/pre&gt;&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;In the end, the Post.cs class is greatly simplified, and the post entity is no longer tightly coupled with non-post concerns like &lt;span style="font-family: Courier New;"&gt;System.Net.Mail&lt;/span&gt;, &lt;span style="font-family: Courier New;"&gt;BlogEngine.Core.Providers&lt;/span&gt;, &lt;span style="font-family: Courier New;"&gt;System.Globalization&lt;/span&gt;, etc.&lt;br /&gt;
&lt;br /&gt;
Next I’ll have to do the same type of refactoring with the other domain objects (Page, Comment, etc.).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-784696725841853067?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=6qRWe15eErg:ZsGIOGWvdNo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=6qRWe15eErg:ZsGIOGWvdNo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=6qRWe15eErg:ZsGIOGWvdNo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=6qRWe15eErg:ZsGIOGWvdNo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=6qRWe15eErg:ZsGIOGWvdNo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/6qRWe15eErg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/6qRWe15eErg/domain-object-that-does-everything.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/05/domain-object-that-does-everything.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-6486011715329607894</guid><pubDate>Wed, 13 May 2009 16:38:00 +0000</pubDate><atom:updated>2010-01-23T21:35:21.757-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Book Review</category><title>Book Review: Dreaming In Code</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_R9uCU3ijWHE/S1vI_hvKgxI/AAAAAAAAABU/AyrM4S_26A4/s1600-h/dreaming_in_code_cover.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_R9uCU3ijWHE/S1vI_hvKgxI/AAAAAAAAABU/AyrM4S_26A4/s320/dreaming_in_code_cover.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;h2&gt;Dreaming In Code: Two Dozen Programmers, Three Years, 4,732 Bugs, And One Quest For Transcendent Software&lt;/h2&gt;I found &lt;a href="http://www.dreamingincode.com/" target="_blank" title="Dreaming In Code"&gt;&lt;span style="text-decoration: underline;"&gt;Dreaming In Code&lt;/span&gt;&lt;/a&gt; to be a fascinating book. On the surface it’s a narrative of a software development project, with some interesting industry history sprinkled throughout for context. But by telling it’s story, author &lt;a href="http://www.dreamingincode.com/about-the-author/" target="_blank" title="About the author"&gt;Scott Rosenberg&lt;/a&gt; reveals two underlying truths about software development: producing quality, useful, non-trivial software applications is hard. And no team, no matter how good the members are, is immune to the inevitable setbacks and pitfalls.&lt;br /&gt;
&lt;br /&gt;
Rosenberg, cofounder of the news and entertainment site &lt;a href="http://www.salon.com/" target="_blank" title="go to Salon.com"&gt;Salon.com&lt;/a&gt;, does a great job detailing much of the early development of the &lt;a href="http://chandlerproject.org/" target="_blank" title="go to the Chandler Project website"&gt;Chandler Project&lt;/a&gt;, a “Note-to-Self Organizer”. The brainchild of &lt;a href="http://www.kapor.com/bio/index.html" target="_blank" title="see Mitch Kapro's bio"&gt;Mitch Kapor&lt;/a&gt; (co-founder of Lotus Development Corp.), Chandler was intended to be the free, flexible, useable, everyman’s replacement for the expensive, corporate, stiff, hard to use Microsoft Outlook as a personal organization and communication tool.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;“Chandler is an open source Note-to-Self Organizer. It features calendaring, task and note management and consists of a desktop application, web application and a free sharing and back-up service called Chandler Hub.&lt;br /&gt;
Our goal is to serve the way people actually work, independently and together, particularly in small groups, a market segment we believe is underserved. Our belief is that personal and collaborative information work is by nature iterative and that the existing binary Done/Not-Done, Read/Unread, Flagged/Unflagged paradigm in productivity software poorly accommodates the reality of how people work.”&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;Dreaming In Code&lt;/span&gt; is largely the story of how the grand vision of the birth of a new paradigm in personal organization software was slowly brought down to earth by the realities every programmer team faces, despite being helmed by a successful software visionary and staffed by some of the best and brightest in the industry. Faced with a lack of consistent direction, personality conflicts, time constraints, and sometimes simply biting off more than they could chew, the team struggled to find the success they were looking for.&lt;br /&gt;
&lt;br /&gt;
Throughout the book, Rosenberg deftly helps the reader understand the motivation and principles that drove the team to try and create something new and different. To them, it wasn’t just a product, it was the beginning of a movement. But, there was no escaping the fact that it was also a software engineering project, lofty ambitions and altruistic motivations notwithstanding. We, through the author, are there in the meetings and celebrations, the good times and the frustrating times, riding the roller coaster along with everybody else.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the book ends too soon. Rosenberg spends three years intimately involved with the project, but has to leave to publish it before the product is even close to being shipped. As a matter of fact, as the book comes to a close, we don’t even know if Chandler 1.0 ever shipped at all (&lt;a href="http://www.wordyard.com/2008/08/10/chandler-10-ships/" target="_blank" title="Chandler 1.0 Ships"&gt;it did&lt;/a&gt;). From the author’s blog:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;It’s been close to six years since Mitch Kapor first announced plans for Chandler, and the application today is quite different from what was envisioned then. But it does fulfill at least a portion of the ambitious agenda Kapor set: It’s fully cross-platform, and, from the user side, it takes a very flexible approach to data. The program was once positioned as a calendar with email and task capabilities, and it’s still got those features, but it’s now presented as a notebook program — it’s “The Note-To-Self Organizer.” You store information free-form and then can organize it according to now/later/done triaging, turn items into tasks and schedule them on the calendar, group data in multiple collections, and share it across the web via the Hub server. I’m looking forward to experimenting more with it.&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
Aside from the missing end to the story, which can be found online anyway, the book is a great read.&lt;br /&gt;
&lt;br /&gt;
The book jacket says that &lt;span style="text-decoration: underline;"&gt;Dreaming In Code&lt;/span&gt; is “Not just for technophiles but for anyone captivated by the drama of invention.” I don’t think anybody who’s not at least somewhat related to software project management would find much interest in it. For those of us who are, though, it’s highly recommended.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-6486011715329607894?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=_E3oDnFhnYc:6aOWGxptUjU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=_E3oDnFhnYc:6aOWGxptUjU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=_E3oDnFhnYc:6aOWGxptUjU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=_E3oDnFhnYc:6aOWGxptUjU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=_E3oDnFhnYc:6aOWGxptUjU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/_E3oDnFhnYc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/_E3oDnFhnYc/book-review-dreaming-in-code.html</link><author>noreply@blogger.com (Eric King)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_R9uCU3ijWHE/S1vI_hvKgxI/AAAAAAAAABU/AyrM4S_26A4/s72-c/dreaming_in_code_cover.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/05/book-review-dreaming-in-code.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-8911872409000547454</guid><pubDate>Fri, 08 May 2009 04:30:00 +0000</pubDate><atom:updated>2010-02-06T18:53:14.593-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Refactoring</category><category domain="http://www.blogger.com/atom/ns#">BlogEngine Experiment</category><category domain="http://www.blogger.com/atom/ns#">Clean Code</category><title>Using List.ForEach() and lambda expressions</title><description>In my previous post, I refactored a small bit of the &lt;span style="font-family: 'Courier New';"&gt;&lt;b&gt;BuildCatalog()&lt;/b&gt;&lt;/span&gt; method, removing the need for the Catalog to know how to filter out the published posts and pages, and the approved comments.&lt;br /&gt;
&lt;br /&gt;
What we were left with was a pretty simple method, but I think it could be made even more readable with a few tweaks. Here’s the code as it is after my changes:&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; BuildCatalog()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilding();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;bool&lt;/span&gt; commentsEnabled = BlogSettings.Instance.EnableCommentSearch;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;lock&lt;/span&gt; (_SyncRoot)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;_Catalog.Clear();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Post post &lt;span style="color: blue;"&gt;in&lt;/span&gt; Post.PublishedPosts)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(post);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (commentsEnabled)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Comment comment &lt;span style="color: blue;"&gt;in&lt;/span&gt; post.ApprovedComments)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(comment);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Page page &lt;span style="color: blue;"&gt;in&lt;/span&gt; Page.PublishedPages)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(page);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuild();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
There are a three &lt;span style="font-family: 'Courier New';"&gt;&lt;b&gt;foreach()&lt;/b&gt;&lt;/span&gt; blocks working on &lt;span style="font-family: 'Courier New';"&gt;&lt;b&gt;List&amp;lt;&amp;gt;&lt;/b&gt;&lt;/span&gt; objects, and within each block there’s a single line of code. That kind of code is just begging to be made a bit more elegant.&lt;br /&gt;
&lt;br /&gt;
The .NET Framework 2.0 added the &lt;span style="font-family: 'Courier New';"&gt;&lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bwabdf9z%28VS.80%29.aspx" target="_blank" title="Go to the MSDN Library article"&gt;List.ForEach()&lt;/a&gt;&lt;/b&gt;&lt;/span&gt; method, which allowed for something like:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;post.ApprovedComments.ForEach(&lt;span style="color: blue;"&gt;delegate&lt;/span&gt;(Comment comment)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(comment);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Using a delegate, this syntax isn’t substantially better nor easier to read. However, toss in a &lt;a href="http://msdn.microsoft.com/en-us/library/bb308966.aspx#csharp3.0overview_topic7" target="_blank" title="Go to MSDN Library article"&gt;lambda expression&lt;/a&gt; instead (introduced by .NET Framework 3.0), and &lt;span style="font-family: 'Courier New';"&gt;&lt;b&gt;ForEach()&lt;/b&gt;&lt;/span&gt; suddenly becomes juicily delicious:&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;post.ApprovedComments.ForEach(comment =&amp;gt; AddItem(comment));&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Yummy. All that blocky wordiness condensed to a simple, readable, one-line statement. Once we sprinkle those into our BuildCatalog() method, we may end up with something like:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; BuildCatalog()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilding();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;lock&lt;/span&gt; (_SyncRoot)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;_Catalog.Clear();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (BlogSettings.Instance.EnableCommentSearch)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Post.PublishedPosts.ForEach(post =&amp;gt; AddPostAndComments(post));&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Post.PublishedPosts.ForEach(post =&amp;gt; AddItem(post));&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Page.PublishedPages.ForEach(page =&amp;gt; AddItem(page));&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuild();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Much cleaner code, I think. My final version of the Catalog class, after extracting it from the Search.cs file and adding a few more refactorings (like an &lt;a href="http://msdn.microsoft.com/en-us/library/bb308966.aspx#csharp3.0overview_topic3" target="_blank" title="Go to MSDN Library article"&gt;extension method&lt;/a&gt; or two), looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; Catalog&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; List&amp;lt;Entry&amp;gt; entries = &lt;span style="color: blue;"&gt;new&lt;/span&gt; List&amp;lt;Entry&amp;gt;();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;object&lt;/span&gt; syncRoot = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: blue;"&gt;object&lt;/span&gt;();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; List&amp;lt;Entry&amp;gt; Entries&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;get { &lt;span style="color: blue;"&gt;return&lt;/span&gt; entries; }&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddItem(IPublishable item)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;item.AddToCatalog();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Build()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilding();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;lock&lt;/span&gt; (syncRoot)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;entries.Clear();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Page.PublishedPages.ForEach(page =&amp;gt; page.AddToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (BlogSettings.Instance.EnableCommentSearch)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Post.PublishedPosts.ForEach(post =&amp;gt; post.AddSelfAndCommentsToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Post.PublishedPosts.ForEach(post =&amp;gt; post.AddToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}        &lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilt();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddSelfAndCommentsToCatalog(&lt;span style="color: blue;"&gt;this&lt;/span&gt; Post post)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;post.AddToCatalog();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;post.ApprovedComments.ForEach(c =&amp;gt; c.AddToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddToCatalog(&lt;span style="color: blue;"&gt;this&lt;/span&gt; IPublishable item)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;var entry = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Entry&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Item = item,&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Title = TextAgent.CleanContent(item.Title, &lt;span style="color: blue;"&gt;false&lt;/span&gt;),&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Content = HttpUtility.HtmlDecode(TextAgent.CleanContent(item.Content, &lt;span style="color: blue;"&gt;true&lt;/span&gt;))&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;};&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (item &lt;span style="color: blue;"&gt;is&lt;/span&gt; Comment)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;entry.Content += HttpUtility.HtmlDecode(TextAgent.CleanContent(item.Author, &lt;span style="color: blue;"&gt;false&lt;/span&gt;));&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;entries.Add(entry);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; EventHandler&amp;lt;EventArgs&amp;gt; IndexBuilding;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnIndexBuilding()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (IndexBuilding != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;IndexBuilding(&lt;span style="color: blue;"&gt;null&lt;/span&gt;, EventArgs.Empty);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; EventHandler&amp;lt;EventArgs&amp;gt; IndexBuilt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnIndexBuilt()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (IndexBuilt != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;IndexBuilt(&lt;span style="color: blue;"&gt;null&lt;/span&gt;, EventArgs.Empty);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-8911872409000547454?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=bNUmdFEqEoo:rRiYq9hk0Bg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=bNUmdFEqEoo:rRiYq9hk0Bg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=bNUmdFEqEoo:rRiYq9hk0Bg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=bNUmdFEqEoo:rRiYq9hk0Bg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=bNUmdFEqEoo:rRiYq9hk0Bg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/bNUmdFEqEoo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/bNUmdFEqEoo/better-readability-using-listforeach.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/05/better-readability-using-listforeach.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-6737869159000607214</guid><pubDate>Tue, 05 May 2009 06:13:00 +0000</pubDate><atom:updated>2010-01-23T21:36:17.038-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Refactoring</category><category domain="http://www.blogger.com/atom/ns#">BlogEngine Experiment</category><title>My little baby’s all grown up</title><description>In &lt;a href="http://devadept.blogspot.com/2009/05/put-functionality-where-it-belongs.html" title="Put functionality where it belongs"&gt;my previous post&lt;/a&gt; I began refactoring the &lt;a href="http://www.dotnetblogengine.net/" target="_blank" title="go to the BlogEngine.NET home page"&gt;BlogEngine.NET&lt;/a&gt; Search.cs file, specifically a portion of the “catalog” functionality. I’m going to continue my refactoring here …&lt;br /&gt;
&lt;br /&gt;
But first, a little context. It seems that the searching algorithm (a method called &lt;span style="font-family: Courier New;"&gt;BuildResultSet()&lt;/span&gt; ) works on “entries” in a collection called “catalog”, returning a set of “results”. An Entry is a struct defined right in the Search.cs file:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// A search optimized post object cleansed from HTML and stop words.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;struct&lt;/span&gt; Entry&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;The post object reference&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; IPublishable Item;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;The title of the post cleansed for stop words&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; Title;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;The content of the post cleansed for stop words and HTML&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; Content;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
A Result is actually a completely separate class, contained also in the Search.cs file:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// A result is a search result which contains a post and its ranking.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; Result : IComparable&amp;lt;Result&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// The rank of the post based on the search term. The higher the rank, the higher the post is in the result set.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;int&lt;/span&gt; Rank;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// The post of the result.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; IPublishable Item;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// Compares the current object with another object of the same type.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;param name="other"&amp;gt;An object to compare with this object.&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value &lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// has the following meanings: Value Meaning Less than zero This object is less than the other parameter.Zero &lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// This object is equal to other. Greater than zero This object is greater than other.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;int&lt;/span&gt; CompareTo(Result other)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; other.Rank.CompareTo(Rank);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;int&lt;/span&gt; GetHashCode()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; Item.Id.GetHashCode();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Catalog, meanwhile, is defined as a local variable:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; Collection&amp;lt;Entry&amp;gt; _Catalog = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Collection&amp;lt;Entry&amp;gt;();&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Each of these items have a few methods set aside for them, such as “&lt;span style="font-family: Courier New;"&gt;BuildCatalog()&lt;/span&gt;”, “&lt;span style="font-family: Courier New;"&gt;AddItem()&lt;/span&gt;”, “&lt;span style="font-family: Courier New;"&gt;CleanContent()&lt;/span&gt;”, and so forth. These pieces of code are all &lt;a href="http://en.wikipedia.org/wiki/Code_folding" target="_blank" title="Code Folding on Wikipedia"&gt;folded up&lt;/a&gt; and hidden away within regions in the Search.cs file.&lt;br /&gt;
&lt;br /&gt;
The searching itself is done in a few methods, primarily &lt;span style="font-family: Courier New;"&gt;BuildResultSet()&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// Builds the results set and ranks it.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: green;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; List&amp;lt;Result&amp;gt; BuildResultSet(&lt;span style="color: blue;"&gt;string&lt;/span&gt; searchTerm, &lt;span style="color: blue;"&gt;bool&lt;/span&gt; includeComments)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;List&amp;lt;Result&amp;gt; results = &lt;span style="color: blue;"&gt;new&lt;/span&gt; List&amp;lt;Result&amp;gt;();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;string&lt;/span&gt; term = CleanContent(searchTerm.ToLowerInvariant().Trim(), &lt;span style="color: blue;"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;[] terms = term.Split(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: blue;"&gt;char&lt;/span&gt;[] { &lt;span style="color: #006080;"&gt;' '&lt;/span&gt; }, StringSplitOptions.RemoveEmptyEntries);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;string&lt;/span&gt; regex = &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Format(System.Globalization.CultureInfo.InvariantCulture, &lt;span style="color: #006080;"&gt;"({0})"&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Join(&lt;span style="color: #006080;"&gt;"|"&lt;/span&gt;, terms));&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Entry entry &lt;span style="color: blue;"&gt;in&lt;/span&gt; _Catalog)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Result result = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Result();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (!(entry.Item &lt;span style="color: blue;"&gt;is&lt;/span&gt; Comment))&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt; titleMatches = Regex.Matches(entry.Title, regex).Count;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;result.Rank = titleMatches * 20;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt; postMatches = Regex.Matches(entry.Content, regex).Count;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;result.Rank += postMatches;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt; descriptionMatches = Regex.Matches(entry.Item.Description, regex).Count;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;result.Rank += descriptionMatches * 2;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;else&lt;/span&gt; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (includeComments)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;int&lt;/span&gt; commentMatches = Regex.Matches(entry.Content + entry.Title, regex).Count;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;result.Rank += commentMatches;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (result.Rank &amp;gt; 0)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;result.Item = entry.Item;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;results.Add(result);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;results.Sort();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; results;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
So, where am I going with this? I’m glad you asked. :-)&lt;br /&gt;
&lt;br /&gt;
It seems to me that this one file, Search.cs, is trying to do too many complex things. It’s defining several entities (&lt;span style="font-family: Courier New;"&gt;Entry, Result, Catalog&lt;/span&gt;), managing them (&lt;span style="font-family: Courier New;"&gt;BuildCatalog(), BuildResultSet()&lt;/span&gt;), searching them (&lt;span style="font-family: Courier New;"&gt;APMLMatches(), Hits()&lt;/span&gt;), manipulating them (&lt;span style="font-family: Courier New;"&gt;CleanContent(), FindRelatedItems(), ResultToPost()&lt;/span&gt;), and handling events (&lt;span style="font-family: Courier New;"&gt;Post_Saved(), Post_CommentAdded(), OnSearching()&lt;/span&gt;). It’s probable that the search functionality started out pretty simple, and grew more complex over time.&lt;br /&gt;
&lt;br /&gt;
When that happens to our code, we should practice a little “ruthless refactoring” and extract these groups of functionality into their own classes where appropriate. In other words, when your baby methods grow up, make them move out and get their own home. In this way, we can keep the “Search” class concerned with searching, not maintaining the content catalog or sanitizing the result’s text. I don’t think enough of that was done here, so I’m going to do it.&lt;br /&gt;
&lt;br /&gt;
The first thing I did when I opened up this file (even before what I did in the previous post), was extract the “catalog”, and give it some freedom. My new Catalog.cs, all grown up now (and with a few more refactorings which I’ll explain later), looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; Catalog&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; List&amp;lt;Entry&amp;gt; entries = &lt;span style="color: blue;"&gt;new&lt;/span&gt; List&amp;lt;Entry&amp;gt;();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;object&lt;/span&gt; syncRoot = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: blue;"&gt;object&lt;/span&gt;();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; List&amp;lt;Entry&amp;gt; Entries&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;get { &lt;span style="color: blue;"&gt;return&lt;/span&gt; entries; }&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddItem(IPublishable item)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;item.AddToCatalog();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;internal&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Build()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilding();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;lock&lt;/span&gt; (syncRoot)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;entries.Clear();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Page.PublishedPages.ForEach(page =&amp;gt; page.AddToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;bool&lt;/span&gt; commentSearchEnabled = BlogSettings.Instance.EnableCommentSearch;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (commentSearchEnabled)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Post.PublishedPosts.ForEach(post =&amp;gt; post.AddSelfAndCommentsToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Post.PublishedPosts.ForEach(post =&amp;gt; post.AddToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilt();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddSelfAndCommentsToCatalog(&lt;span style="color: blue;"&gt;this&lt;/span&gt; Post post)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;post.AddToCatalog();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;post.ApprovedComments.ForEach(c =&amp;gt; c.AddToCatalog());&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddToCatalog(&lt;span style="color: blue;"&gt;this&lt;/span&gt; IPublishable item)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;var entry = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Entry&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Item = item,&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Title = TextAgent.CleanContent(item.Title, &lt;span style="color: blue;"&gt;false&lt;/span&gt;),&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;Content = HttpUtility.HtmlDecode(TextAgent.CleanContent(item.Content, &lt;span style="color: blue;"&gt;true&lt;/span&gt;))&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;};&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (item &lt;span style="color: blue;"&gt;is&lt;/span&gt; Comment)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;entry.Content += HttpUtility.HtmlDecode(TextAgent.CleanContent(item.Author, &lt;span style="color: blue;"&gt;false&lt;/span&gt;));&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;entries.Add(entry);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; EventHandler&amp;lt;EventArgs&amp;gt; IndexBuilding;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnIndexBuilding()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (IndexBuilding != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;IndexBuilding(&lt;span style="color: blue;"&gt;null&lt;/span&gt;, EventArgs.Empty);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; EventHandler&amp;lt;EventArgs&amp;gt; IndexBuilt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnIndexBuilt()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (IndexBuilt != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;IndexBuilt(&lt;span style="color: blue;"&gt;null&lt;/span&gt;, EventArgs.Empty);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Similarly, I’ll do the same type of extraction to other pieces of Search.cs, leaving each of the individual pieces simpler, more single-purpose, and ultimately (I hope) easier to understand and manipulate.&lt;br /&gt;
&lt;br /&gt;
Coming up next, I take advantage of some .NET 3+ functionality to further refine the code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-6737869159000607214?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=vX4vgNhSiK8:HMXFyexKm8E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=vX4vgNhSiK8:HMXFyexKm8E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=vX4vgNhSiK8:HMXFyexKm8E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=vX4vgNhSiK8:HMXFyexKm8E:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=vX4vgNhSiK8:HMXFyexKm8E:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/vX4vgNhSiK8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/vX4vgNhSiK8/my-little-babys-all-grown-up.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/05/my-little-babys-all-grown-up.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-4234347557302975420.post-7174815954904927021</guid><pubDate>Sat, 02 May 2009 22:04:00 +0000</pubDate><atom:updated>2010-01-23T21:36:17.039-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Refactoring</category><category domain="http://www.blogger.com/atom/ns#">BlogEngine Experiment</category><title>Put functionality where it belongs</title><description>In one of my recent &lt;a href="http://www.dotnetblogengine.net/" target="_blank" title="go to the BlogEngine.NET home page"&gt;BlogEngine.Net&lt;/a&gt; Experiment refactoring sessions, I found myself working on the BlogEngine.Core Search.cs file. Very quickly I noticed that the search functionality works on a “catalog” object, which is a local Collection&amp;lt;Post&amp;gt; type variable. Various methods work on this collection, “building" it, adding to it, and so forth.&lt;br /&gt;
&lt;br /&gt;
The BuildCatalog() method looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; BuildCatalog()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilding();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;lock&lt;/span&gt; (_SyncRoot)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;_Catalog.Clear();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Post post &lt;span style="color: blue;"&gt;in&lt;/span&gt; Post.Posts)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (!post.IsPublished)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;continue&lt;/span&gt;;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(post);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (BlogSettings.Instance.EnableCommentSearch)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Comment comment &lt;span style="color: blue;"&gt;in&lt;/span&gt; post.Comments)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (comment.IsApproved)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(comment);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Page page &lt;span style="color: blue;"&gt;in&lt;/span&gt; Page.Pages)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (page.IsPublished)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(page);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuild();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
Notice how, in the first ForEach, all of the posts are requested (Post.Posts), but we only want to work on the published ones. So, we open up and inspect each post to see if it’s published before continuing.&lt;br /&gt;
&lt;br /&gt;
We then do the same thing for Comments, getting them all but only working with the approved ones. And we do it yet again with Pages, getting them all when we only want the published ones.&lt;br /&gt;
&lt;br /&gt;
There’s obviously some extra work going on here, but how should we refactor it?&lt;br /&gt;
&lt;br /&gt;
One of the problems with this code is that the Catalog needs to know too much about the internals of a Post, a Comment, and a Page to do its work. The Catalog &lt;i&gt;shouldn’t need to know&lt;/i&gt; that a Post and a Page will have an IsPublished property, nor that a Comment will have an IsApproved property. (See the definition of the &lt;a href="http://c2.com/cgi/wiki?InappropriateIntimacy" target="_blank" title="Inappropriate Intimacy on the c2 wiki"&gt;Inappropriate Intimacy&lt;/a&gt; code smell.) It should simply be able to ask for published posts, approved comments, and published pages from the appropriate provider.&lt;br /&gt;
&lt;br /&gt;
But who can the Catalog ask? Neither the Post class nor the Page class can provide the answer, so the Catalog does the best it can. The solution, then, is to fix the Post and Page classes so that they can provide the Published and Approved content themselves.&lt;br /&gt;
&lt;br /&gt;
Once done, the BuildCatalog() method will look more like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div id="codeSnippetWrapper" style="background-color: #f4f4f4; border: 1px solid silver; cursor: text; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 20px 0px 10px; max-height: 200px; overflow: auto; padding: 4px; text-align: left; width: 97.5%;"&gt;&lt;div id="codeSnippet" style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; BuildCatalog()&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuilding();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;bool&lt;/span&gt; commentsEnabled = BlogSettings.Instance.EnableCommentSearch;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;lock&lt;/span&gt; (_SyncRoot)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;_Catalog.Clear();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Post post &lt;span style="color: blue;"&gt;in&lt;/span&gt; Post.PublishedPosts)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(post);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (commentsEnabled)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Comment comment &lt;span style="color: blue;"&gt;in&lt;/span&gt; post.ApprovedComments)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(comment);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (Page page &lt;span style="color: blue;"&gt;in&lt;/span&gt; Page.PublishedPages)&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;{&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;AddItem(page);&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: white; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;OnIndexBuild();&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #f4f4f4; border-style: none; color: black; direction: ltr; font-family: 'Courier New',courier,monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding: 0px; text-align: left; width: 100%;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
The BuildCatalog() method is simpler and more straightforward. It’s also decoupled from the internals of the Post, Comment, and Page classes, in the sense that it doesn’t need to know how to determine if a post or page is published, it just asks for them.&lt;br /&gt;
&lt;br /&gt;
In the next couple of posts I’ll walk through a few more refactorings of the ‘catalog’ functionality.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4234347557302975420-7174815954904927021?l=blog.devadept.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devadept?a=DmJmRMtIF0I:ttI-7irLvXo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=DmJmRMtIF0I:ttI-7irLvXo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=DmJmRMtIF0I:ttI-7irLvXo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devadept?a=DmJmRMtIF0I:ttI-7irLvXo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devadept?i=DmJmRMtIF0I:ttI-7irLvXo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devadept/~4/DmJmRMtIF0I" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/devadept/~3/DmJmRMtIF0I/put-functionality-where-it-belongs.html</link><author>noreply@blogger.com (Eric King)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.devadept.com/2009/05/put-functionality-where-it-belongs.html</feedburner:origLink></item></channel></rss>

