<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.stevesmithblog.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.stevesmithblog.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0"><channel><title>Steve Smith's Blog</title><link>http://stevesmithblog.com/</link><description>Musings on Software and the Developer Community</description><generator>Graffiti CMS 1.1 (build 1.1.0.1114)</generator><lastBuildDate>Wed, 08 Oct 2008 02:30:31 GMT</lastBuildDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.stevesmithblog.com/StevenSmith" type="application/rss+xml" /><item><title>Search Trends October 2008</title><link>http://stevesmithblog.com/blog/search-trends-october-2008/</link><pubDate>Wed, 08 Oct 2008 02:30:31 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/search-trends-october-2008/</guid><dc:creator>ssmith</dc:creator><slash:comments>0</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;PDC is fast approaching and Cloud Computing is the theme - and all the rage for everyone else in the Industry media.&amp;nbsp; Amazon recently announced they'll be extending their compute cloud to support Windows and real databases.&amp;nbsp; Here's a look at some recent trends in the tech industry, using &lt;a href="http://google.com/trends"&gt;Google Trends&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Daylight Savings Time&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The topic of DST is likely of at least marginal interest to most software developers, as working with DateTime constructs is a frequent requirement for us (and often a source of frustration).&amp;nbsp; I wanted to confirm when it was this year and that led to the rest of these trend searches (I once missed a flight due to a change in the date of DST that my alarm clock's auto adjustment failed to pick up).&amp;nbsp; FYI: Daylight Savings Time in 2008 will Fall Back the first Sunday in November.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.google.com/trends?q=daylight+savings+time%2C+daylight+saving+time&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="299" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_3.png" width="594" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Interesting (and expected) that twice a year folks become interested in this topic.&amp;nbsp; Note that the main regions who care are US, Canada, Australia, and the UK.&amp;nbsp; Most of the world doesn't observe DST.&amp;nbsp; And contrary to what I thought I knew, &lt;a href="http://en.wikipedia.org/wiki/Daylight_saving_time"&gt;Ben Franklin didn't invent DST and it only started in the early 1900s&lt;/a&gt; (according to the Source Of All Knowledge: &lt;a href="http://en.wikipedia.org/wiki/Main_Page"&gt;Wikipedia&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Cloud Computing&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.google.com/trends?q=cloud+computing&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="300" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_6.png" width="600" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;If I were a betting man, I'd bet on cloud computing to be a big upcoming trend in the next several years.&amp;nbsp; It first hit the search term scene a little over a year ago, and it's gone up rather drastically since then.&amp;nbsp; I'd look for it to peak in November this year after PDC and then to plateau or rise gently after that.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Amazon's S3 and EC2 services have been around for a while - let's see how Microsoft compares thus far.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Amazon Cloud vs. Microsoft Cloud&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.com/trends?q=amazon+cloud%2C+microsoft+cloud&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="295" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_30.png" width="595" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;em&gt;I'd say Microsoft is going to catch and surpass Amazon by PDC time.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Looking at another Microsoft event and announcement, let's see how Silverlight is doing in terms of interest.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Silverlight&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.google.com/trends?q=silverlight&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="301" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_9.png" width="597" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;em&gt;Silverlight is still going strong.&amp;nbsp; I predict it will go up steadily once Silverlight 2 is released, slated for later this year and most likely at PDC, I would say.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;So what about hosting?&amp;nbsp; Is anyone looking for cloud hosting solutions?&amp;nbsp; Compared to what?&amp;nbsp; Let's look at two comparably small sets of terms.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Cloud vs. Ruby Hosting&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.com/trends?q=cloud+hosting%2Cruby+hosting&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=1"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="298" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_12.png" width="596" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Cloud hosting didn't exist as a trend before 2008 Q3 and now it's nearly as popular a search term as ruby hosting.&amp;nbsp; Clearly Ruby Hosting isn't all that popular, but just how does it compare to say ASP.NET and PHP?&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Ruby vs. ASP.NET vs. PHP Hosting&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.com/trends?q=ruby+hosting%2C+asp.net+hosting%2C+php+hosting&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=1"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="297" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_11.png" width="595" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Clearly the trends for all three of these are heading downward, as I think the hosting marketplace has largely shaken out and become somewhat commoditized.&amp;nbsp; With sites like &lt;a href="http://godaddy.com/"&gt;GoDaddy&lt;/a&gt; offering cheap hosting along with about a million easy to use web publishing and blogging platforms, the need for hosting is obviously in decline.&lt;/p&gt; &lt;p&gt;So what else is new?&amp;nbsp; What about ASP.NET?&amp;nbsp; Remember when it was Atlas?&amp;nbsp; And what about this new jQuery thing that's not really new but is now going to ship with Visual Studio?&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Atlas vs. ASP.NET AJAX&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.com/trends?q=asp.net+atlas%2C+asp.net+ajax&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=1"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="297" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_15.png" width="594" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;... and jQuery&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.com/trends?q=asp.net+atlas%2C+asp.net+ajax%2C+jQuery&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=1"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="200" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_18.png" width="604" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;How about data access technologies?&amp;nbsp; Would it surprise you to learn that NHibernate has been a search trend since late 2004, with greater popularity than either LINQ to SQL or Entity Framework's high water mark since 2006 (that is, NH's 2006 and later popularity exceeds the best the others have ever achieved).&amp;nbsp; I doubt this reflects adoption, but it's interesting nonetheless.&amp;nbsp; Perhaps it reflects people searching for documentation...&lt;/p&gt; &lt;p&gt;&lt;strong&gt;NHibernate vs. LINQ to SQL vs. Entity Framework&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="293" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_21.png" width="593" border="0"&gt; &lt;/p&gt; &lt;p&gt;How is interest in ASP.NET MVC coming along, with its hopeful release some time in 2008 as well?&lt;/p&gt; &lt;p&gt;&lt;strong&gt;ASP.NET MVC&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.com/trends?q=asp.net+mvc&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="296" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_24.png" width="594" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Lastly, in the self-fulfilling prophecy department, how many people have been looking for a recession, since about a year ago?&amp;nbsp; It certainly appears the popularity of a recession has gone up dramatically in the last 12 months.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Recession&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.com/trends?q=recession&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="293" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/SearchTrendsOctober2008_135BB/image_27.png" width="599" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Look up &lt;a href="http://google.com/trends?q=bailout&amp;amp;ctab=0&amp;amp;geo=all&amp;amp;date=all&amp;amp;sort=0"&gt;bailout&lt;/a&gt; as well, though the graph isn't terribly interesting since it's almost asymptotic...&amp;nbsp; Fun times in the financial industry.&amp;nbsp; Now back to more regularly scheduled geekdom.&lt;/p&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/414386650" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Fsearch-trends-october-2008%2F</feedburner:awareness></item><item><title>Reducing SQL Lookup Tables and Function Properties in NHibernate</title><link>http://stevesmithblog.com/blog/reducing-sql-lookup-tables-and-function-properties-in-nhibernate/</link><pubDate>Mon, 06 Oct 2008 15:17:15 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/reducing-sql-lookup-tables-and-function-properties-in-nhibernate/</guid><dc:creator>ssmith</dc:creator><slash:comments>6</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;One of the points made in &lt;a href="http://jeffreypalermo.com/"&gt;Jeffrey's&lt;/a&gt; &lt;a href="http://www.headspringsystems.com/training"&gt;agile development boot camp&lt;/a&gt; last week that struck a chord with me was that many database-centric designs have lookup tables that aren't really just data.&amp;nbsp; That is, tables that hold values such as statuses that, if modified, can easily break existing code or won't function as expected without the addition of code.&amp;nbsp; We have a lot of these in our codebase, and we've been struggling with the questions of how to address these values in our system.&amp;nbsp; Do we use Enums?&amp;nbsp; If so, do we try and keep the enums in sync with the database values?&amp;nbsp; If not, do we want to use magic numbers/strings to refer to these codes?&amp;nbsp; It's a real PITA to work with these things and really the only reason they're in the database at all is so we have some referential integrity locking down the allowable values of the status column(s).&lt;/p&gt; &lt;p&gt;You can avoid this problem if you push the status logic into objects and don't rely on the database to implement referential integrity for you.&amp;nbsp; Create a Status class that has all of the logic necessary for rendering a status code in a variety of ways (for instance a short code, a long name, and a description, all of which are difficult to implement on Enums without attributes or other extension approaches).&amp;nbsp; Have your primary class reference the status via composition (e.g. a property).&amp;nbsp; Then, in your persistence layer, you can store just the short code value (or integer key) of the class, but without the requirement that there be a lookup table involved.&amp;nbsp; If referential integrity is of great importance, a constraint can easily be applied to the database.&amp;nbsp; The constraint would then be updated with the build at the same time as new values are added to the Status class.&amp;nbsp; The status can also be used similarly to an Enum assuming it has some static properties representing its value instances, like so:&lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; WorkOrderStatus&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; WorkOrderStatus Assigned = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WorkOrderStatus(&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         &lt;span style="color: #006080"&gt;"ASD"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Assigned"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Assigned"&lt;/span&gt;, 2, &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; WorkOrderStatus Cancelled = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WorkOrderStatus(&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &lt;span style="color: #006080"&gt;"CAN"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Cancelled"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Cancelled"&lt;/span&gt;, 5, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; WorkOrderStatus Complete = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; WorkOrderStatus(&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #006080"&gt;"CMP"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Complete"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Complete"&lt;/span&gt;, 4, &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; ...&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;NHibernate can map this status directly if you create a WorkOrderStatusType class that inherits from NHibernate.Type.PrimitiveType and overrides its methods.&amp;nbsp; The mapping then is simply:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;class&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="WorkOrder"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;property&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Status"&lt;/span&gt; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="WorkOrderStatusType, Infrastructure"&lt;/span&gt; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #ff0000"&gt;not-null&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="true"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; ...&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;One very common pattern I've noticed as software evolves is the migration from simple boolean state codes on objects to multi-value states and eventually to the need for some kind of an event log.&amp;nbsp; In the example above, perhaps originally we started with a WorkOrderStatus that was simply a boolean with states for Complete and Incomplete, and it has since moved on to include the states listed above (and several others).&amp;nbsp; Now the customer wants to know when the status changed, and by whom, so they can track the WorkOrder through its workflow.&lt;/p&gt;
&lt;p&gt;Typically this requires a bunch of changes in the database and some application logic to get the current status from the event log as the most recent one.&amp;nbsp; Further, the WorkOrder might expose dates for LastUpdated and CompletedDate which should be tied to this same event log, though prior to adding the event log they were set in application code when these state transformations occurred.&amp;nbsp; This is an example wherein NHibernate's support for functions can be very helpful (see also &lt;a href="http://ayende.com/Blog/archive/2006/10/01/UsingSQLFunctionsInNHibernate.aspx"&gt;this post by Ayende&lt;/a&gt;).&amp;nbsp; Assuming there is an Event table which has columns for BeginStatus and EndStatus as well was a DateTime column, date properties for the WorkOrder could be mapped like so:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;class&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="WorkOrder"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;property&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="LastAssignedDate"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;formula&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="(&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; select max(e.DateTime) &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; from Event e &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; where (e.WorkOrderId = Id)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; and (e.EndStatus = 'ASD'))"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;property&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="LastUpdatedDate"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;formula&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="(&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; select max(e.DateTime) &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; from Event e &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; where (e.WorkOrderId = Id))"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; ...&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;The nice thing about this approach is that there are fewer tables in the database that are dedicated to mere lookup data.&amp;nbsp; In this case, we've eliminated the need for a WorkOrderStatus table that might have had columns like ID, Name, Description, ShortCode, SortBy, and perhaps other properties.&amp;nbsp; Keeping the database more streamlined makes it easier to comprehend and easier to change, and keeping this logic in our classes rather than in the database makes our code easier to change and easier to test.&amp;nbsp; If the raw SQL in the mapping file is a red flag for you, replace them with SQL Functions (which Ayende &lt;a href="http://ayende.com/Blog/archive/2006/10/01/UsingSQLFunctionsInNHibernate.aspx"&gt;covers in his post&lt;/a&gt;).&lt;/div&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/412893188" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Freducing-sql-lookup-tables-and-function-properties-in-nhibernate%2F</feedburner:awareness></item><item><title>Installing VisualSVN Subversion</title><link>http://stevesmithblog.com/blog/installing-visualsvn-subversion/</link><pubDate>Fri, 03 Oct 2008 20:47:20 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/installing-visualsvn-subversion/</guid><dc:creator>ssmith</dc:creator><slash:comments>1</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;Wrapping up &lt;a href="http://www.headspringsystems.com/training/"&gt;HeadSpring's Agile Boot Camp&lt;/a&gt; class this week, we're installing &lt;a href="http://www.visualsvn.com/"&gt;VisualSVN&lt;/a&gt; Server locally.&amp;nbsp; Running the setup is just a matter of hitting Next three times - it's very simple.&amp;nbsp; Running the visual server window yields this opening screen:&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_2.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="438" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb.png" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Next, right click on VisualSVN Server and select Properties:&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_4.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_1.png" width="439" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;These are basically the same settings you had available from the installer.&amp;nbsp; Assuming these settings are fine, the next step is to create a user.&amp;nbsp; Go back to the main screen and right click on Users, Create User.&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_6.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="224" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_2.png" width="379" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Once a user is created, the next step is to create a repository.&amp;nbsp; Be sure to check the box to set up the default structure.&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_10.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="213" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_4.png" width="451" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;At this point, the server end of things is done.&amp;nbsp; If you want to set up a working folder on your local machine to point to this, go to a folder (like C:\working\) and assuming you already have TortoiseSVN installed, right click and select in the folder and select SVN Checkout:&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_16.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_7.png" width="185" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Configure the URL and local directory:&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_18.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="335" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_8.png" width="478" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Once this is done, you can also see at any time how the folder is mapped to its subversion location by looking at the folder's properties.&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_20.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="484" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_9.png" width="346" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;At this point you're ready to create your initial sub folders and work on your project.&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_22.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="235" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_10.png" width="498" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Too easy.&amp;nbsp; And oh by the way this also just installed Apache Server, so if you've ever wanted to do that but weren't sure how difficult it would be - you just did it.&lt;/p&gt; &lt;p&gt;&lt;a href="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_24.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="282" alt="image" src="http://stevesmithblog.com/files/media/image/WindowsLiveWriter/InstallingVisualSVNSubversion_EB91/image_thumb_11.png" width="644" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;If you're moving an existing project into this working folder and you want to add it to source control, you're best off using VisualSVN from within Visual Studio to do so.&amp;nbsp; Open the solution in Visual Studio, and then assuming you have VisualSVN client installed, you should be able to right click on the solution and select Add to Subversion.&lt;/p&gt; &lt;p&gt;If you don't see that option on the solution, you'll want to delete the .svn folder from the working folder and then go through the process, stating that you'll set the working folder manually.&lt;/p&gt; &lt;p&gt;Now right click on the folder in Windows Explorer and SVN Commit.&amp;nbsp; Your code is now in a local copy of subversion.&amp;nbsp; Note that you can use this to version any files!&amp;nbsp; If you want to version your word documents or graphic files you're editing or anything you like, this will let you do it.&amp;nbsp; Just be sure you're backing up your hard drive, since this isn't a substitute for backing up your disk.&amp;nbsp; But it will give you local revision history so you can undo changes to any document.&lt;/p&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/410582072" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Finstalling-visualsvn-subversion%2F</feedburner:awareness></item><item><title>Monty Hall Envelope Puzzle</title><link>http://stevesmithblog.com/blog/monty-hall-envelope-puzzle/</link><pubDate>Fri, 26 Sep 2008 15:20:30 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/monty-hall-envelope-puzzle/</guid><dc:creator>ssmith</dc:creator><slash:comments>8</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;&lt;a href="http://imgs.xkcd.com/comics/labyrinth_puzzle.png"&gt;&lt;img style="margin: 0px 0px 10px 10px" height="218" src="http://imgs.xkcd.com/comics/labyrinth_puzzle.png" width="240" align="right"&gt;&lt;/a&gt; So, recently I wrote about my &lt;a href="http://stevesmithblog.com/blog/probability-puzzle/"&gt;introduction to the Monty Hall problem&lt;/a&gt; and &lt;a href="http://stevesmithblog.com/blog/probability-puzzle-answered/"&gt;its solution&lt;/a&gt;.&amp;nbsp; However, in the course of thinking about this problem, I came up with a related one that is pretty tricky as well, and builds on the insight gained from the Monty Hall problem.&amp;nbsp; That is, given three random chances to win a prize, if you pick one and another is revealed as a non-winner, you are better off switching with the remaining chance you didn't originally pick than sticking with the original selection (with 1/3 - 2/3 odds).&amp;nbsp; With this in mind, consider the following problem.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Steve's Monty Hall Envelope Puzzle&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I take 3 plain envelopes and put a $100 bill inside one of them, seal them, and give one to you, one to Bob, and one to Carrie, at random.&amp;nbsp; Then I randomly ask one of you to open an envelope - for the sake of argument let's say I choose Carrie.&amp;nbsp; Carrie opens her envelope to reveal that it is empty.&amp;nbsp; Now I offer you the choice to trade envelopes with Bob - should you trade?&lt;/p&gt; &lt;p&gt;And now I ask Bob the exact same question.&amp;nbsp; Should &lt;strong&gt;he&lt;/strong&gt; trade?&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;If the logic of the original Monty Hall problem holds, then you had a 1/3 chance of choosing the right envelope to begin with, meaning that the set of Bob/Carrie envelopes had a 2/3 chance, and therefore with Carrie eliminated you should switch with Bob because his envelope now has a 2/3 chance while yours has retained its 1/3 chance.&amp;nbsp; Clear so far, I hope.&amp;nbsp; You naturally want to trade.&lt;/p&gt; &lt;p&gt;However, &lt;strong&gt;Bob sees the exact same odds from his point of view!&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Bob had a 1/3 chance at the outset, and saw you and Carrie as having a combined 2/3 chance, and with Carrie removed, that leaves &lt;strong&gt;you&lt;/strong&gt; with a 2/3 chance to his 1/3.&amp;nbsp; Bob definitely wants to trade with you as well!&lt;/p&gt; &lt;p&gt;The question is, how can it be in both of your best interests to trade?&amp;nbsp; How can you both now have a 2/3 chance (relative to the other one)?&amp;nbsp; And what is the actual likelihood that either of you is now holding the $100 in your envelope?&lt;/p&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/403874328" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Fmonty-hall-envelope-puzzle%2F</feedburner:awareness></item><item><title>Favorite Developer Books</title><link>http://stevesmithblog.com/blog/favorite-developer-books/</link><pubDate>Fri, 26 Sep 2008 13:59:11 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/favorite-developer-books/</guid><dc:creator>ssmith</dc:creator><slash:comments>1</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;I've written a few posts recently about various books, and recently while interviewing a candidate for &lt;a href="http://nimblepros.com/"&gt;Nimble Software&amp;nbsp; Professionals&lt;/a&gt; it occurred to me that for an experienced developer (e.g. not a new grad out of college), asking what their favorite (or most recently read) programming book is could tell a lot about them as a developer.&amp;nbsp; If their favorite book is something like Expert Programming in 21 Hours (not a real title) that paints a very different picture than if their favorite book is &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201633612/aspalliancecom"&gt;Design Patterns&lt;/a&gt; or a similarly respected title.&lt;/p&gt; &lt;p&gt;Of course, flipping the question around, I started to think about what I would list among my own favorites, and naturally that seemed like a reasonable blog post, so here goes.&amp;nbsp; Anyone interested in a wider poll of favorites should check out &lt;a href="http://stackoverflow.com/questions/72406/what-development-book-made-the-most-impact-on-you-as-a-developer"&gt;this StackOverflow thread&lt;/a&gt; (and &lt;a href="http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read"&gt;this one&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Steve's Top 2 For Developers&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:c98bc134-a502-4248-8b7d-b1e9bb9e9a3a" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="Working Effectively with Legacy Code (Robert C. Martin Series)" href="http://www.amazon.com/exec/obidos/ASIN/0131177052/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/0131177052.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;Working Effectively with Legacy Code (Robert C. Martin Series)&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 0131177052&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780131177055&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;In the #1 spot is Feathers' book, which I read early this year.&amp;nbsp; This book is now required reading for all of my developers.&amp;nbsp; I really wish I had read it about four years ago when it was first published (and sooner than that if he'd written it sooner) as it fundamentally changed my approach to developing flexible and maintainable software.&amp;nbsp; I've &lt;a href="http://aspadvice.com/blogs/ssmith/archive/2008/05/13/Book_3A00_-Working-Effectively-With-Legacy-Code.aspx"&gt;reviewed it&lt;/a&gt; elsewhere more completely, but it's good.&amp;nbsp; The title stinks, though - don't let that throw you.&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:222f1100-8795-4e97-934c-b542ab2db9d7" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="Code Complete: A Practical Handbook of Software Construction" href="http://www.amazon.com/exec/obidos/ASIN/0735619670/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/0735619670.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;Code Complete: A Practical Handbook of Software Construction&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 0735619670&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780735619678&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;A classic.&amp;nbsp; Should be a companion text in intro to programming courses around the country, I think.&amp;nbsp; This book will help you to write better code at the method level and below.&amp;nbsp; It's low level but extremely practical and while you may not agree with or adopt 100% of the practices it recommends, you'll be a better programmer for having read McConnel's analysis and then made an informed choice about how you do things.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Note that I don't really care what language you're writing in - these two books are just fantastic for any software developer.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Steve's Top 2 For Project Managers&lt;/strong&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:06127abb-a698-4db3-99e8-44a64c21b73b" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="Lean Software Development: An Agile Toolkit (Agile Software Development Series)" href="http://www.amazon.com/exec/obidos/ASIN/0321150783/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/0321150783.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;Lean Software Development: An Agile Toolkit (Agile Software Development Series)&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 0321150783&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780321150783&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;I've written &lt;a href="http://stevesmithblog.com/search/?q=lean+software"&gt;a few blog posts based on this book&lt;/a&gt; recently, and I have a few more notes that will turn into future blog posts.&amp;nbsp; I think this book has given me more blog fodder than any other I've read recently.&amp;nbsp; I still need to write a full review, but it's definitely worth a read if you're interested in improving the overall productivity of your development team.&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:da22c0cb-f908-4441-ad97-e44f95176286" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="Peopleware: Productive Projects and Teams   (Second Edition)" href="http://www.amazon.com/exec/obidos/ASIN/0932633439/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/0932633439.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;Peopleware: Productive Projects and Teams   (Second Edition)&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 0932633439&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780932633439&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Another classic title, this one is great for technical managers of all sorts who want to have productive teams.&amp;nbsp; If your organization is one in which people say (or believe) they like working early in the morning / late at night / on weekends because "it's the only time they can get real work done" then you really should read (and act on) this book.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Reading Now or in the Queue&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:492bfdc6-199d-4373-b732-c0d9995de7aa" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="Domain-Driven Design: Tackling Complexity in the Heart of Software" href="http://www.amazon.com/exec/obidos/ASIN/0321125215/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/0321125215.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;Domain-Driven Design: Tackling Complexity in the Heart of Software&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 0321125215&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780321125217&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;I'm in the process of reading Evans' book, which I've previously skimmed.&amp;nbsp; I suspect I'm going to read this one more than once, as it has a lot of interesting concepts that one needs to practice in order to master.&amp;nbsp; There's a Yahoo group dedicated to DDD that I'm lurking on as well.&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:a6cb4b8c-4c4d-4062-a024-5232bba7be93" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="The Art of Agile Development" href="http://www.amazon.com/exec/obidos/ASIN/0596527675/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/0596527675.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;The Art of Agile Development&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 0596527675&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780596527679&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;I'm about halfway through this one - it's a larger book than Lean Software Development and covers some of the same ground.&amp;nbsp; I'm not finding it quite as compelling, but it's got its share of gems.&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:3b907017-1d81-4c9d-88f6-51da51e0770b" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="Head First Design Patterns (Head First)" href="http://www.amazon.com/exec/obidos/ASIN/0596007124/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/0596007124.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;Head First Design Patterns (Head First)&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 0596007124&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780596007126&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;I've read chapters of this from others' copies of the book and it's a very approachable and entertaining book (which says a lot given what's out there).&amp;nbsp; It's on my list to give a full reading to when I get a chance.&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:7dc1bd33-94bd-46fd-a20b-0131235bcd47:a7d2d493-1d8c-48d5-bc16-2e16602cc089" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0" unselectable="on"&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td valign="top" width="400"&gt;
&lt;p&gt;&lt;a title="The Pragmatic Programmer: From Journeyman to Master" href="http://www.amazon.com/exec/obidos/ASIN/020161622X/aspalliancecom"&gt;&lt;img src="http://images.amazon.com/images/P/020161622X.01.MZZZZZZZ.jpg" border="0" align="left" style="float:left"&gt;The Pragmatic Programmer: From Journeyman to Master&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;ISBN&lt;/b&gt;: 020161622X&lt;br&gt;&lt;b&gt;ISBN-13&lt;/b&gt;: 9780201616224&lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Also on my list.&amp;nbsp; I don't have much to say about it beyond that I've heard it's great and I should read it.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Worth Mentioning&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201485672/aspalliancecom"&gt;Refactoring&lt;/a&gt; and &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0201633612/aspalliancecom"&gt;Design Patterns&lt;/a&gt; are both on my shelf (having been read first!) and are certainly worth mentioning.&amp;nbsp; I think Feathers' book is much more important than either of these as it did a much better job of bringing it all together and helping me to "get" why some of these techniques were useful, and in which situations.&amp;nbsp; Another one I read early on in University of Chicago's introduction to programming course is Abelson/Sussman's &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0262510871/aspalliancecom"&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;, which is another classic.&amp;nbsp; I need to pick up the 2nd edition of this and add it to my reading list.&amp;nbsp; Scheme is a fun language, and thinking about programming in a LISPy/Scheme-y way is very different from typical OO/C style languages.&amp;nbsp; Tends to be very jarring for me, but especially with lambda functions and related new features in C#, revisiting some of these functional language features should prove educational and helpful.&lt;/p&gt; &lt;p&gt;So... that's my list for now.&amp;nbsp; It's certain to change over time as I find a new favorite, and it's possible that I've completely left out some that really should be on my list.&amp;nbsp; As for you, do you agree?&amp;nbsp; Do you have your own favorite?&amp;nbsp; Which books have had the greatest impact on you, and what book would you be most proud of reading if asked the question in an interview?&lt;/p&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/403809392" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Ffavorite-developer-books%2F</feedburner:awareness></item><item><title>Probability Puzzle Answered</title><link>http://stevesmithblog.com/blog/probability-puzzle-answered/</link><pubDate>Thu, 25 Sep 2008 17:55:51 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/probability-puzzle-answered/</guid><dc:creator>ssmith</dc:creator><slash:comments>2</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;&lt;img style="margin: 0px 0px 0px 10px" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Monty_open_door.svg/180px-Monty_open_door.svg.png" align="right"&gt; In a recent post, I described a &lt;a href="http://stevesmithblog.com/blog/probability-puzzle/"&gt;Probability Puzzle that is actually known as the Monty Hall Problem&lt;/a&gt;.&amp;nbsp; This is &lt;a href="http://en.wikipedia.org/wiki/Monty_Hall_problem"&gt;a fairly famous problem and has a long write-up on Wikipedia&lt;/a&gt; that is definitely worth reading to get a good understanding of the problem.&amp;nbsp; Almost everyone fails to answer this problem correctly the first attempt, because it seems obvious that there is one prize behind one of the remaining two doors, and there is nothing constraining which door we might pick (the 2nd time), so it should be a fresh decision with a 50/50 chance of success.&lt;/p&gt; &lt;p&gt;In fact, the way to look at this problem is in reverse.&amp;nbsp; With the initial choice of one door out of three, the odds of success were clearly 1/3.&amp;nbsp; Said another way, &lt;strong&gt;the likelihood that a wrong choice was made was 2/3&lt;/strong&gt;.&amp;nbsp; Still another way to look at this is that the breakdown in odds is 1/3 assigned to the set of doors chosen (1 door) and 2/3 assigned to the set of doors not chosen (2 doors).&amp;nbsp; When it is revealed that one of the unchosen doors is not the winner, &lt;strong&gt;this changes nothing about the likelihood that the door you originally picked is correct&lt;/strong&gt;!&amp;nbsp; Your set still only has 1/3 and the unchosen set (which now has only 1 door in it) still has a 2/3 chance of being correct.&amp;nbsp; Thus, you definitely should switch doors, as it doubles the odds of winning the prize!&lt;/p&gt; &lt;p&gt;This result can easily be demonstrated with a bit of code, run a suitable number of times.&amp;nbsp; Pick a number from 0 to 2 to be the door with the prize.&amp;nbsp; Pick a number from 0 to 2 to be the contestant's selection.&amp;nbsp; Initial chance of success is 1 in 3.&amp;nbsp; Now pick one of the other two doors and reveal it, but only if it is not the prize.&amp;nbsp; You'll find that it is the prize 1/3 of the time - these get thrown out as the problem has defined that a goat must be revealed.&amp;nbsp; Now look at the number of times the contestant has the right door compared to the number of times the unselected door is correct, and you'll see quite clearly that it's twice as likely the unchosen door has the prize.&lt;/p&gt; &lt;p&gt;I have one more post on this subject for tomorrow, which twists this a little bit further.&amp;nbsp; I suggest reading the full &lt;a href="http://en.wikipedia.org/wiki/Monty_Hall_problem"&gt;Wikipedia writeup&lt;/a&gt; before diving into that one.&lt;/p&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/403008222" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Fprobability-puzzle-answered%2F</feedburner:awareness></item><item><title>Strategy Pattern With Ninject</title><link>http://stevesmithblog.com/blog/strategy-pattern-with-ninject/</link><pubDate>Thu, 25 Sep 2008 04:54:17 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/strategy-pattern-with-ninject/</guid><dc:creator>ssmith</dc:creator><slash:comments>6</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;This is a follow-up to my post about &lt;a href="http://stevesmithblog.com/blog/avoiding-dependencies/"&gt;avoiding dependencies with design patterns&lt;/a&gt;.&amp;nbsp; It left off with something like this as a Cart object that uses the Strategy pattern to avoid a direct dependency on SMTP emails.&lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Cart&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; ISendEmail emailProvider;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//public Cart()&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//{&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//    emailProvider = new LiveSmtpMailer();&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//}&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Cart(ISendEmail emailProvider)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.emailProvider = emailProvider;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Checkout()&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         &lt;span style="color: #008000"&gt;// Do some other stuff&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.emailProvider.SendMail(&lt;span style="color: #006080"&gt;"someuser@domain.com"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"store@acme.com"&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;                         &lt;span style="color: #006080"&gt;"Order Confirmation"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Your Order Was Received."&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Note that I've commented out the default constructor - I'll explain why in a moment.&lt;/p&gt;
&lt;p&gt;The next logical step in this series is to avoid the requirement of hard-coding in the class its default behavior of using a LiveSmtpMailer() instance to send email.&amp;nbsp; We want to be able to manage these default implementations centrally, either via a class or some kind of configuration file.&amp;nbsp; Tools that provide this functionality are collectively referred to as &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_Control"&gt;Inversion-of-Control&lt;/a&gt; containers, or IoC containers.&amp;nbsp; &lt;a href="http://ninject.org/"&gt;Ninject&lt;/a&gt; is one such tool.&lt;/p&gt;
&lt;p&gt;Download Ninject, build it if necessary, and add a reference to Ninject.Core to get started.&amp;nbsp; With this in place, we can do the necessary plumbing work to have Ninject instantiate our Cart class for us, rather than using the new keyword ourselves directly.&amp;nbsp; Avoiding the new keyword is a necessary consequence of most IoC containers, as far as I can tell.&amp;nbsp; To tell Ninject what to do when it finds it needs an ISendEmail interface implementation, you can create something like the following:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CustomModule : StandardModule&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Load()&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         Bind&amp;lt;ISendEmail&amp;gt;().To&amp;lt;ConsoleTestMailer&amp;gt;();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The ConsoleTestMailer is a new one I wrote for this example.&amp;nbsp; It's listed here:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ConsoleTestMailer : ISendEmail&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SendMail(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; To, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; From, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Subject, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Body)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         Console.WriteLine(&lt;span style="color: #006080"&gt;"To: "&lt;/span&gt; + To);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         Console.WriteLine(&lt;span style="color: #006080"&gt;"From: "&lt;/span&gt; + From);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         Console.WriteLine(&lt;span style="color: #006080"&gt;"Subject: "&lt;/span&gt; + Subject);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         Console.WriteLine(&lt;span style="color: #006080"&gt;"Body: "&lt;/span&gt; + Body);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;All it does is dump the email information to the console.&lt;/p&gt;
&lt;p&gt;Now we're ready to write the Main() method of our console application:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Program&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[] args)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         CustomModule module = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CustomModule();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         IKernel kernel = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StandardKernel(module);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         Cart myCart = kernel.Get&amp;lt;Cart&amp;gt;();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         myCart.Checkout();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;And that's it.&amp;nbsp; The magic happens on line 8.&amp;nbsp; If you leave the default constructor with the hardcoded implementation, then that's what is used.&amp;nbsp; Removing it and leaving only a constructor expecting an ISendEmail implementation allows Ninject to manage this dependency injection, and lets you manage it across your entire application from one location.&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/402467721" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Fstrategy-pattern-with-ninject%2F</feedburner:awareness></item><item><title>Probability Puzzle</title><link>http://stevesmithblog.com/blog/probability-puzzle/</link><pubDate>Wed, 24 Sep 2008 17:19:13 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/probability-puzzle/</guid><dc:creator>ssmith</dc:creator><slash:comments>5</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;I was recently introduced to the following puzzle by another developer (from &lt;a href="http://vertigosoftware.com/"&gt;Vertigo&lt;/a&gt;, in fact).&amp;nbsp; This is actually a fairly well-known problem and you'll find write-ups about it on Wikipedia and elsewhere, but I'll omit links to those sources from this post to prevent some temptation to just click and see the answer (I'll post everything in a follow-up).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;The Scenario&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Imagine you are on a game show in which a great prize is hidden behind one of three doors.&amp;nbsp; Behind one door lies a brand new car.&amp;nbsp; Behind each of the other two, a goat.&amp;nbsp; The host of the show has explained this to you, and asks you to select a door.&amp;nbsp; You choose one and inform the host of your decision.&amp;nbsp; He smiles and says "Let's see what you didn't win" and opens up one of the other doors, revealing a goat!&amp;nbsp; Then he looks at you and says, "The car is still behind one of these two doors.&amp;nbsp; If you'd like, I'll let you change your mind and switch which door you've selected.&amp;nbsp; What do you say?"&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Should you switch doors?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Is it in your best interest to switch doors, or does it matter?&amp;nbsp; When commenting, if you already know this problem, please avoid posting any spoilers or links to write-ups.&amp;nbsp; I'll publish a follow-up with all of that tomorrow.&lt;/p&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/401980489" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Fprobability-puzzle%2F</feedburner:awareness></item><item><title>Review - Murach ASP.NET 3.5 Programming with VB</title><link>http://stevesmithblog.com/blog/review-murach-asp-net-3-5-programming-with-vb/</link><pubDate>Tue, 23 Sep 2008 19:57:33 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/review-murach-asp-net-3-5-programming-with-vb/</guid><dc:creator>ssmith</dc:creator><slash:comments>0</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;&lt;img src="http://images.amazon.com/images/P/1890774472.01.MZZZZZZZ.jpg" align="right"&gt; I have a copy of &lt;a href="http://www.amazon.com/exec/obidos/ASIN/1890774472/aspalliancecom"&gt;Murach's ASP.NET 3.5 Web Programming with VB 2008&lt;/a&gt; (&lt;a href="http://www.murach.com/books/avb8/index.htm"&gt;book web site&lt;/a&gt;) that I received over the summer and have been meaning to write a short review.&amp;nbsp; So here goes.&amp;nbsp; First of all, I love the "Murach format" for books, especially for "how-to" books which as it happens tend to be what they publish.&amp;nbsp; Specifically, they lay out their books such that typically the left-hand page is providing some explanatory text, while the right page has the corresponding figures, source code, etc.&amp;nbsp; The result is that you pretty much always have everything you need in front of you, unlike 99% of the technical books out there in which you're always have to flip pages or read through multi-page code listings in order to figure out what line of code or figure the author is referencing.&lt;/p&gt; &lt;p&gt;Another thing I really liked about this book is that if you're a professor, trainer, instructor, etc. you can get courseware that integrates with the book (&lt;a href="http://www.dunntraining.com/"&gt;thanks, Mark Dunn, for this tip&lt;/a&gt;).&amp;nbsp; This is HUGE because normally it's quite a bit of effort and/or expense to get decent courseware put together (and kept up to date).&amp;nbsp; What's more, the Murach stuff, for the most part, is pretty good!&amp;nbsp; I know that doesn't sound like a glowing endorsement, but I've used a handful of third party course curricula and I can tell you that many do not meet this bar.&lt;/p&gt; &lt;p&gt;&lt;img src="http://images.amazon.com/images/P/1890774480.01.THUMBZZZ.jpg" align="right"&gt; I used the book and its associated training materials (obtained from the publisher) to teach a class last week that went quite well, and I'll be teaching a second class to the same group of students soon, using the same materials.&amp;nbsp; The class was in C#, but as luck would have it there is also a &lt;a href="http://www.amazon.com/exec/obidos/ASIN/1890774480/aspalliancecom"&gt;Murach's ASP.NET 3.5 Web Programming with C# 2008&lt;/a&gt; (&lt;a href="http://www.murach.com/books/acs8/index.htm"&gt;book web site&lt;/a&gt;) title that isn't actually in print yet but which had code samples and courseware available.&amp;nbsp; So, even though I didn't have the pressed trees version of the book, I was able to use it for the C#-specific course.&lt;/p&gt; &lt;p&gt;The book has 29 chapters and includes coverage of the basics of web programming on up through LINQ, IIS, AJAX, and web services.&amp;nbsp; Its approach to all of these is at a basic, introductory level, and it does a very good job of making these technologies very approachable for students who have had limited or no exposure to these subjects.&amp;nbsp; You can pick up either the &lt;a href="http://www.amazon.com/exec/obidos/ASIN/1890774480/aspalliancecom"&gt;C# or VB version for about $33 on Amazon&lt;/a&gt; at the moment, which seems quite reasonable given that it's just under 1000 pages.&lt;/p&gt;&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/401109236" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Freview-murach-asp-net-3-5-programming-with-vb%2F</feedburner:awareness></item><item><title>Slack and Constraints and Optimizing Throughput</title><link>http://stevesmithblog.com/blog/slack-and-constraints-and-optimizing-throughput/</link><pubDate>Mon, 22 Sep 2008 16:14:21 GMT</pubDate><guid isPermaLink="true">http://stevesmithblog.com/blog/slack-and-constraints-and-optimizing-throughput/</guid><dc:creator>ssmith</dc:creator><slash:comments>1</slash:comments><category domain="http://stevesmithblog.com/blog/">Blog</category><description>&lt;p&gt;This is my second post that's related to my recent reading of &lt;a href="http://www.amazon.com/exec/obidos/ASIN/9780321150783/aspalliancecom"&gt;Poppendiecks' Lean Software Development&lt;/a&gt; - read the first one here on &lt;a href="http://stevesmithblog.com/blog/delaying-decisions/"&gt;Delaying Decisions&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;A related book (and one thing I loved about Lean Software Development were the many references to other great books, some I'd read, some not) that I've read and recommend is &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0767907698/aspalliancecom"&gt;Slack&lt;/a&gt;, by Tom DeMarco.&amp;nbsp; It's referenced on page 81 of Lean Software Development, in reference to optimizing for flow as opposed to optimizing for utilization / efficiency.&lt;/p&gt; &lt;p&gt;In both books, the point is made that total throughput and resource efficiency are opposed to one another.&amp;nbsp; To prove this, consider the case where you have a worker who is only 60% utilized on time-critical tasks.&amp;nbsp; When you give this worker a task that takes 15 minutes, you can typically expect that it will get done in 15 minutes, and sometimes a little longer if you just gave them some other work ahead of this batch.&lt;/p&gt; &lt;p&gt;Now, clearly, this worker is not being used efficiently - they're only 60% utilized on critical tasks!&amp;nbsp; So management decides to assign this worker to two people, each of whom now puts their work requests into a queue, and the worker processes them FIFO as they are received.&amp;nbsp; Now the worker is typically 100% utilized and the queue is never empty, with some things sitting in it for several hours during busy periods of the day.&amp;nbsp; That 15 minute task you needed done now is going to take 2 hours, (but at least the worker isn't idle at all).&amp;nbsp; Overall throughput - the total time for a request to get through the system - as plummeted!&lt;/p&gt; &lt;p&gt;Highways, server CPUs, project schedules, and yes employees are all resources that need to have some &lt;em&gt;slack&lt;/em&gt; available if they're to be used in the most effective fashion from the point-of-view of productivity.&amp;nbsp; If you measure the flow of widgets shipped or project velocity or server requests served per second and average time to last byte - you'll find that all of these are better when resources have excess capacity than when they are 100% utilized, even though the latter is the most efficient use of those resources.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Clearly 100% efficiency is the enemy of overall system productivity.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Poppendiecks summarize with:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Just as a highway cannot provide acceptable service without some slack in capacity, so you probably are not providing your customers with the highest level of service if you have no slack in your organization.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Highways are being used most efficiently when they are completely gridlocked, if you measure the number of cars using the resource / total area of the highway.&amp;nbsp; Yet clearly from the perspective of an individual vehicle trying to get from point A to point B the highway's throughput is far better when it is underutilized.&lt;/p&gt; &lt;p&gt;On the very next page, they cite the Theory of Constraints, which I've quoted often in my presentations on performance tuning (though I haven't yet read the &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0884271668/aspalliancecom"&gt;book&lt;/a&gt; - it's on my list).&amp;nbsp; It relates not only to software performance, but to organizational performance as well:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;According to the &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0884271668/aspalliancecom"&gt;theory of constraints&lt;/a&gt;, the best way to optimize an organization is to focus on the throughput of the organization, because this is the key to generating profitable revenue.&amp;nbsp; The way to increase throughput is to look for the current bottleneck that is slowing things down and fix it.&amp;nbsp; Once that is done, find the next bottleneck and fix it.&amp;nbsp; Keep this up and you will have a fast moving value stream.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;Find the bottleneck.&amp;nbsp; Eliminate it.&amp;nbsp; Repeat.&amp;nbsp; This is performance tuning, of anything, in a nutshell.&lt;img src="http://feeds.stevesmithblog.com/~r/StevenSmith/~4/399930610" height="1" width="1"/&gt;</description><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetItemData?uri=StevenSmith&amp;itemurl=http%3A%2F%2Fstevesmithblog.com%2Fblog%2Fslack-and-constraints-and-optimizing-throughput%2F</feedburner:awareness></item><feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetFeedData?uri=StevenSmith</feedburner:awareness></channel></rss>
