<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.abdullin.com/~d/styles/itemcontent.css"?><!--Generated by Squarespace Site Server v5.9.1 (http://www.squarespace.com/) on Fri, 05 Mar 2010 14:23:28 GMT--><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Rinat Abdullin on Efficient Software Development</title><link>http://abdullin.com/journal/</link><description>Articles on efficient software development with .NET, including IoC, ORM, Cloud Computing.</description><lastBuildDate>Fri, 05 Mar 2010 13:58:37 +0000</lastBuildDate><copyright /><language>en-US</language><generator>Squarespace Site Server v5.9.1 (http://www.squarespace.com/)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.abdullin.com/RinatAbdullin" /><feedburner:info uri="rinatabdullin" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>RinatAbdullin</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><title>Mercurial Is Getting Better for .NET Projects</title><dc:creator>Rinat Abdullin</dc:creator><pubDate>Fri, 05 Mar 2010 04:33:43 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/mbejjolPXlI/mercurial-is-getting-better-for-net-projects.html</link><guid isPermaLink="false">287483:2929700:6911783</guid><description>&lt;p&gt;Recently I've started using &lt;a href="http://mercurial.selenic.com/" target="_blank" class="offsite-link-inline"&gt;Mercurial&lt;/a&gt; (distributed &lt;a href="http://abdullin.com/wiki/version-control-system-vcs.html"&gt;version control system&lt;/a&gt;, an analogue of Git) more and more for working on various projects. This applies even if the project itself lives in the Subversion for collaboration.&lt;/p&gt;

&lt;p&gt;Icon overlays have got more stable in the latest versions of Windows 7, Jungle Disk, &lt;a href="http://tortoisehg.bitbucket.org/" target="_blank" class="offsite-link-inline"&gt;TortoiseHg&lt;/a&gt; (shell extension for the Mercurial) and TortoiseSvn. The last two, share same overlays, as a matter of fact, along with showing much smarter overlay management. There is no need to mess with the registry (works on my machine).&lt;/p&gt;

&lt;p&gt;So it is a real pleasure to work with Mercurial these days. This also allows to perform solution-wide refactorings and cleanups featured by the ReSharper 5.0.&lt;/p&gt;

&lt;p&gt;Here's the snippet of the .hgignore file that I use:&lt;/p&gt;

&lt;pre&gt;
# Mercurial .hgignore file template by Abdullin.com
# For syntax see: http://linux.die.net/man/5/hgignore
# Source: http://bitbucket.org/abdullin/snippets/

# Visual Studio 
glob:*.user
glob:*.suo
glob:*.cache
glob:_ReSharper.*/
relre:/obj/
relre:/bin/

# Subversion
glob:.svn/
glob:_svn/

# Build structure
relre:^Build/

# Misc
glob:Thumbs.db
glob:*.bak
glob:*.log

&lt;/pre&gt;

&lt;p&gt;The snippet itself is saved (&lt;a href="http://bitbucket.org/abdullin/snippets/src/tip/hgignore.txt" target="_blank" class="offsite-link-inline"&gt;link to the latest version&lt;/a&gt;) on the &lt;a href="http://bitbucket.org" target="_blank" class="offsite-link-inline"&gt;bitbucket&lt;/a&gt;, although &lt;a href="http://code.google.com/" target="_blank" class="offsite-link-inline"&gt;Google Code&lt;/a&gt; already supports Mercuarial as well.&lt;/p&gt;

&lt;p&gt;In order to use the snippet, simply paste it into the ".hgignore" file in the root of the working copy. Chances are, the file has already been created for you by Mercurial.&lt;/p&gt;

&lt;p&gt;And here's a bit of PowerShell code for wiping clean a SVN working copy, in order to merge latest branch with it:&lt;/p&gt;

&lt;pre&gt;
ls -r -force | 
where {!$_.Mode.StartsWith("d") }  | 
where {!$_.FullName.Contains(".svn")} | 
del -force
&lt;/pre&gt;

&lt;p&gt;Basically, the command wipes clean all files (you can put it in a single line), leaving an empty folder tree with the Subversion files. Then you can copy another solution export over it (i.e. export of a Mercurial branch) and simply accept the changes. That's how we've been syncing some folders in SVN repositories in one of the projects a few years ago.&lt;/p&gt;

&lt;p&gt;Fortunately copying snapshot from the SVN to Mercurial is more simple than that: just wipe the all files, except for the single hg folder in the root; export contents of a Subversion solution over to this folder and commit changes.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=mbejjolPXlI:PSqEYcn8eEY:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=mbejjolPXlI:PSqEYcn8eEY:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=mbejjolPXlI:PSqEYcn8eEY:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=mbejjolPXlI:PSqEYcn8eEY:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=mbejjolPXlI:PSqEYcn8eEY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=mbejjolPXlI:PSqEYcn8eEY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=mbejjolPXlI:PSqEYcn8eEY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=mbejjolPXlI:PSqEYcn8eEY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/mbejjolPXlI" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-6911783.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2010/3/5/mercurial-is-getting-better-for-net-projects.html</feedburner:origLink></item><item><title>Scalability and Concurrency Challenge</title><dc:creator>Rinat Abdullin</dc:creator><pubDate>Tue, 05 Jan 2010 15:20:41 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/SwojU0TrdNI/scalability-and-concurrency-challenge.html</link><guid isPermaLink="false">287483:2929700:6228610</guid><description>&lt;p&gt;It is interesting, how concepts of separated features and messaging become more important as the distributed applications evolve. I keep encountering these again and again in the solutions at Lokad and in new reads showing up:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Articles about cloud computing;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://ayende.com/Blog/archive/2009/12/21/effectus-isolated-features.aspx" target="_blank"&gt;Effectus&lt;/a&gt; codebase by Ayende;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.udidahan.com/2009/12/09/clarified-cqrs/" target="_blank"&gt;Command-Query Responsibility Segregation&lt;/a&gt; by Udi;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://developer.mindtouch.com/Dream" target="_blank"&gt;MindTouch Dream&lt;/a&gt; principles of building lightweight decoupled services;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Composite_application" target="_blank"&gt;Composite Application&lt;/a&gt; theory.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So for the last few weeks I’ve been discovering things like &lt;a href="http://www.amqp.org/confluence/display/AMQP/AMQP+Specification" target="_blank"&gt;Advanced Message Queue Protocol&lt;/a&gt; (reading its specs is a pleasure of its own) and its implementations (&lt;a href="http://qpid.apache.org/" target="_blank"&gt;Apache Qpid&lt;/a&gt; and &lt;a href="http://www.rabbitmq.com/" target="_blank"&gt;RabbitMQ&lt;/a&gt;). There had also been a different approach to the REST services and concurrency handling as in the inspiring MindTouch Dream framework.&lt;/p&gt;  &lt;p&gt;Obviously, the toolset is not your native Microsoft .NET toolset, but:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;MindTouch Dream works natively on Mono and .NET;&lt;/li&gt;    &lt;li&gt;Apache QPID and RabbitMQ have .NET clients;&lt;/li&gt;    &lt;li&gt;It takes just a few lines of code to write .NET Dream Service to act as a gateway between AMQP and REST;&lt;/li&gt;    &lt;li&gt;For some reason I like AMQP more than MSMQ;&lt;/li&gt;    &lt;li&gt;In a current world it takes less than an hour to procure a cheap running server out in the cloud.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It is also interesting to see how REST services and AMQP middleware services have their parallels with the classical composite applications:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;AMQP == EventBroker&lt;/li&gt;    &lt;li&gt;Services == IoC Container environment (roughly)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So basically, there are quite a lot of concepts and technological approaches that suddenly start making a lot of sense to me.&lt;/p&gt;  &lt;p&gt;At the moment I’m interested in giving a try to build some learning prototype application using these technologies, just for the sake of practicing and learning pros and cons better. &lt;/p&gt;  &lt;p&gt;Does anybody know of a common or specific problems out in the field, that require potential scalability and async processing? Something, where scalability, concurrency and sync processing create a lot of challenges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update: &lt;/strong&gt; &lt;em&gt;Jonathan&lt;/em&gt; has really nice article about &lt;a href="http://jonathan-oliver.blogspot.com/2009/03/dddd-and-cqs-getting-started.html" target="_blank" class="offsite-link-inline"&gt;Getting Started with DDDD and CQS &lt;/a&gt; (there are a lot of references there as well).&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=SwojU0TrdNI:cLTT9bTJR8w:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=SwojU0TrdNI:cLTT9bTJR8w:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=SwojU0TrdNI:cLTT9bTJR8w:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=SwojU0TrdNI:cLTT9bTJR8w:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=SwojU0TrdNI:cLTT9bTJR8w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=SwojU0TrdNI:cLTT9bTJR8w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=SwojU0TrdNI:cLTT9bTJR8w:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=SwojU0TrdNI:cLTT9bTJR8w:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/SwojU0TrdNI" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-6228610.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2010/1/5/scalability-and-concurrency-challenge.html</feedburner:origLink></item><item><title>Windows Azure in Lokad</title><dc:creator>Rinat Abdullin</dc:creator><pubDate>Tue, 15 Dec 2009 20:44:13 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/upTMQbVrw2c/windows-azure-in-lokad.html</link><guid isPermaLink="false">287483:2929700:6070642</guid><description>&lt;p&gt;If you are interested in Cloud Computing, Windows Azure and some practical applications, then this &lt;strong&gt;short movie&lt;/strong&gt; by Microsoft might interest you. It had been featured at PDC’09 and is partially based on the &lt;strong&gt;use case around Lokad&lt;/strong&gt; (&lt;a href="http://lokad.com" target="_blank"&gt;company&lt;/a&gt; I’m working in):&lt;/p&gt;  &lt;div&gt;&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/pX0W8SMSewM&amp;amp;hl=en_GB&amp;amp;fs=1&amp;amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/pX0W8SMSewM&amp;amp;hl=en_GB&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If YouTube player does play properly, then there is a &lt;a href="http://www.youtube.com/watch?v=pX0W8SMSewM&amp;amp;feature=player_embedded" target="_blank"&gt;separate link&lt;/a&gt; or &lt;a href="http://videos.lokad.com/2009-12-14-azure/" target="_blank"&gt;downloadable movie files&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;There’s also the original &lt;a href="http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=4000005803" target="_blank"&gt;Cloud Computing Case Study&lt;/a&gt; on Windows Azure in Lokad made by Microsoft after a few interviews.&lt;/p&gt;  &lt;p&gt;Given all the latest changes in the technology, and the possible trends, that start showing up, we can say that the &lt;a href="http://abdullin.com/cloud-computing-in-net/" target="_blank"&gt;cloud computing&lt;/a&gt; is going to be extremely important in the mid-term future.&lt;/p&gt;  &lt;p&gt;Here’s another curious trend in the picture. It seems that stock markets might eventually add yet another commodity to their list – cloud computing instances. Amazon had recently announced &lt;a href="http://aws.amazon.com/ec2/spot-instances/" target="_blank"&gt;EC2 Spot Instances&lt;/a&gt; as an ability to obtain computing capacity at a price matching proposed bit. Once there is some cost-effective and efficient platform for redistributing cloud computing resources, all these datacenters with idle server rack might follow in. Forces of Economics and expense optimization might bring forth interesting development solutions afterwards.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=upTMQbVrw2c:LB1b1Rl4wMs:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=upTMQbVrw2c:LB1b1Rl4wMs:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=upTMQbVrw2c:LB1b1Rl4wMs:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=upTMQbVrw2c:LB1b1Rl4wMs:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=upTMQbVrw2c:LB1b1Rl4wMs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=upTMQbVrw2c:LB1b1Rl4wMs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=upTMQbVrw2c:LB1b1Rl4wMs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=upTMQbVrw2c:LB1b1Rl4wMs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/upTMQbVrw2c" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-6070642.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/12/15/windows-azure-in-lokad.html</feedburner:origLink></item><item><title>Microsoft Feedback 2010</title><category>Lokad</category><dc:creator>Rinat Abdullin</dc:creator><pubDate>Thu, 10 Dec 2009 07:56:34 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/cpD8LZia9Pk/microsoft-feedback-2010.html</link><guid isPermaLink="false">287483:2929700:6031678</guid><description>&lt;p&gt;There is usually a lot to learn from large companies like Microsoft, or less large ones.&lt;/p&gt;  &lt;p&gt;However, it takes a bit of learning on your own before you could understand and appreciate details and partially hidden interactions behind what is revealed.&lt;/p&gt;  &lt;p&gt;Fore example, that’s how Jetbrains ReSharper feedback looks like:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://abdullin.com/resource/WindowsLiveWriter-MicrosoftFeedback2010_B5FE-?fileId=5023971"&gt;&lt;img style="display: inline" title="2009-12-10_JetBrains_Feedback" alt="2009-12-10_JetBrains_Feedback" src="http://abdullin.com/resource/WindowsLiveWriter-MicrosoftFeedback2010_B5FE-?fileId=5023972" width="205" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here’s the one currently employed by us at &lt;a href="http://lokad.com" target="_blank"&gt;Lokad&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://abdullin.com/resource/WindowsLiveWriter-MicrosoftFeedback2010_B5FE-?fileId=5023974"&gt;&lt;img style="display: inline" title="2009-12-10_Lokad_Feedback" alt="2009-12-10_Lokad_Feedback" src="http://abdullin.com/resource/WindowsLiveWriter-MicrosoftFeedback2010_B5FE-?fileId=5023975" width="232" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;And that’s how Microsoft Office 2010 feedback looks like:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://abdullin.com/resource/WindowsLiveWriter-MicrosoftFeedback2010_B5FE-?fileId=5023976"&gt;&lt;img style="display: inline" title="2009-12-10_Microsoft_feedback" alt="2009-12-10_Microsoft_feedback" src="http://abdullin.com/resource/WindowsLiveWriter-MicrosoftFeedback2010_B5FE-?fileId=5023977" width="500" height="395" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Each of these three has it’s own benefits, including but not limited to:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;UI simplicity;&lt;/li&gt;    &lt;li&gt;Level of complexity of cliend-side and server-side infrastructure behind the feature;&lt;/li&gt;    &lt;li&gt;Support for multiple software applications within the same product line (all the way through various versions, deployment options);&lt;/li&gt;    &lt;li&gt;Ability to offer user to provide additional data, essential for the problem resolution;&lt;/li&gt;    &lt;li&gt;Level and quality of sensible automation behind the interaction.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There is a lot to learn from large companies for Lokad.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=cpD8LZia9Pk:FfaPturbPOQ:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=cpD8LZia9Pk:FfaPturbPOQ:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=cpD8LZia9Pk:FfaPturbPOQ:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=cpD8LZia9Pk:FfaPturbPOQ:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=cpD8LZia9Pk:FfaPturbPOQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=cpD8LZia9Pk:FfaPturbPOQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=cpD8LZia9Pk:FfaPturbPOQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=cpD8LZia9Pk:FfaPturbPOQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/cpD8LZia9Pk" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-6031678.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/12/10/microsoft-feedback-2010.html</feedburner:origLink></item><item><title>Fixing Icon Overlays for Dropbox + TortoiseSVN</title><category>How To</category><category>SVN</category><category>Tips</category><dc:creator>Rinat Abdullin</dc:creator><pubDate>Mon, 26 Oct 2009 06:42:36 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/eSqfbtuf1pI/fixing-icon-overlays-for-dropbox-tortoisesvn.html</link><guid isPermaLink="false">287483:2929700:5611588</guid><description>&lt;p&gt;If you are using Windows 7 (x64), Dropbox and TortoiseSVN, then you might eventually encounter that half of your icon overlays went missing.&lt;/p&gt;

&lt;p&gt;Since TortoiseSVN seems to be sharing same overlays with TortoiseCVS, TortoiseHG and TortoiseGit, these programs could experience same glitches.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TortoiseXXX&lt;/em&gt; - windows shell integration for a given &lt;a href="http://abdullin.com/wiki/version-control-system-vcs.html"&gt;version control system&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://www.getdropbox.com/gs" target="_blank" class="offsite-link-inline"&gt;Dropbox&lt;/a&gt;&lt;/em&gt; - SaaS backup solution that works like version control, but performs all the sharing automatically in the background. &lt;/p&gt;

&lt;p&gt;Loosing overlay icons hurts badly, since both Tortoise and Dropbox are extremely good in what they are doing.&lt;/p&gt;

&lt;h2&gt;Problem&lt;/h2&gt;

&lt;p&gt;There is only a limited number of overlay slots available in Windows. That's the byte order limitation (probably around 15, with 4 reserved by the OS). Whenever the limit is breached, we've got problems.&lt;/p&gt;

&lt;h2&gt;Solution&lt;/h2&gt;

&lt;p&gt;So we've got to reduce the number of overlays. Since there are no settings in Dropbox or TSVN to disable certain overlays, we'll have to do this manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step1:&lt;/strong&gt; Start the registry editor (regedit) and navigate to the:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\
  Explorer\ShellIconOverlayIdentifiers
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Step2:&lt;/strong&gt; Backup the entire branch. JIC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step3:&lt;/strong&gt; Delete overlays that are rarely used and not essential for everyday work. I personally deleted these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offline Files&lt;/li&gt;
&lt;li&gt;TortoiseLocked&lt;/li&gt;
&lt;li&gt;TortoiseIgnored&lt;/li&gt;
&lt;li&gt;TortoiseUnversionsed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step4:&lt;/strong&gt; Reboot.&lt;/p&gt;

&lt;p&gt;As the result, Tortoise icons finally show up. Behavior of the Dropbox is more erratic, but this is not critical.&lt;/p&gt;

&lt;h2&gt;Caveat&lt;/h2&gt;

&lt;p&gt;There could be better solutions to the problem.&lt;/p&gt;

&lt;p&gt;However, I didn't investigate the case a lot, for the lack of time - just checked that there are no proper solutions in the google, fired up the regedit, deleted a few entries and found out that &lt;strong&gt;it works for me&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;NB: &lt;a href="http://abdullin.com/storage/uploads/2009/10/DropboxPath x64.zip"&gt;Copy&lt;/a&gt; of &lt;a href="http://wiki.getdropbox.com/DropboxAddons/DropboxPath" target="_blank" class="offsite-link-inline"&gt;DropboxPath utility for x64&lt;/a&gt;.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=eSqfbtuf1pI:v5rKipJ0i84:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=eSqfbtuf1pI:v5rKipJ0i84:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=eSqfbtuf1pI:v5rKipJ0i84:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=eSqfbtuf1pI:v5rKipJ0i84:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=eSqfbtuf1pI:v5rKipJ0i84:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=eSqfbtuf1pI:v5rKipJ0i84:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=eSqfbtuf1pI:v5rKipJ0i84:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=eSqfbtuf1pI:v5rKipJ0i84:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/eSqfbtuf1pI" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-5611588.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/10/26/fixing-icon-overlays-for-dropbox-tortoisesvn.html</feedburner:origLink></item><item><title>Infrastructure Shards and Optional Components</title><category>Articles</category><category>C#</category><category>IoC</category><category>Lokad</category><category>Snippets</category><category>Theory</category><dc:creator>Rinat Abdullin</dc:creator><pubDate>Wed, 21 Oct 2009 05:56:05 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/zbWCBO4o6Hk/infrastructure-shards-and-optional-components.html</link><guid isPermaLink="false">287483:2929700:5564154</guid><description>&lt;p&gt;&lt;a href="http://abdullin.com/wiki/component-driven-development.html"&gt;Component-driven development&lt;/a&gt; really helps to deliver multiple applications and systems efficiently. It happens because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;important functionality is abstracted in components;&lt;/li&gt;
&lt;li&gt;components are coded and unit-tested only once;&lt;/li&gt;
&lt;li&gt;every component has multiple use cases that provide additional feedback and help to find problems or limitations, if there are any;&lt;/li&gt;
&lt;li&gt;whenever a component is fixed or improved, all its consumers would benefit from that automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we go up in the complexity of the development, it becomes too cumbersome to manage components on the individual basis. That's where &lt;em&gt;infrastructure shards&lt;/em&gt; come into the play.&lt;/p&gt;

&lt;h2&gt;Infrastructure Shards&lt;/h2&gt;

&lt;p&gt;Infrastructure shard is a group of components that work together to carry out some specific job in the application or system. They are joined to simplify reuse in multiple applications and contexts.&lt;/p&gt;

&lt;p&gt;Normally all these components are developed to support &lt;a href="http://abdullin.com/wiki/inversion-of-control-ioc.html"&gt;Inversion of Control&lt;/a&gt;, but if needed they could be wired together manually. In the IoC scenario, components are fit together using registration modules (or xml configuration blocks for the legacy containers). In the rare cases, when IoC context is not available (i.e.: we need to offer minimal feedback reporting to deal with possible unhandled exceptions on startup), a simple factory method would do the job.&lt;/p&gt;

&lt;p&gt;A single infrastructure shard could join components coming from the different libraries and application blocks. &lt;/p&gt;

&lt;p&gt;Feedback infrastructure shard (&lt;a href="http://code.google.com/p/lokad-sdk/" target="_blank" class="offsite-link-inline"&gt;sources&lt;/a&gt;), for example, would include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model-View-Controller elements:
&lt;ul&gt;
&lt;li&gt;User control view to be shown in the currently available &lt;em&gt;IViewspace&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Immutable models used to pass feedback reports and information around;&lt;/li&gt;
&lt;li&gt;Controller responsible for managing the view and user interactions;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://abdullin.com/journal/2008/11/23/net-application-block-for-validation-and-business-rules.html"&gt;Validation rules&lt;/a&gt; injected into the view in order to check and enforce user input.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Feedback helper components, aggregating system information to be attached to the report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, if we attempt to start our feedback reporting window, just with these few components, we would fail. This would happen because usually in the IoC environment &lt;em&gt;an infrastructure shard is not self-sufficient&lt;/em&gt;. It has to interact with the other components and services as well. The view, for instance, does not even have a window to present itself in; it is merely a user control:&lt;/p&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/10/2009-10-21_093717.png?__SQUARESPACE_CACHEVERSION=1256110659023" alt=""/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;So in order for the shard to work, we need to provide some external services. These are really easy to spot in the code if we consistently stick to the guidelines of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;only constructor injection is used (no property injection);&lt;/li&gt;
&lt;li&gt;every component has only a single constructor;&lt;/li&gt;
&lt;li&gt;components can inherit only from the interfaces (except for the views that have to derive from some user control).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given that we could find out that core feedback service components use these components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IViewspace - responsible for displaying view properly in the UI environment available;&lt;/li&gt;
&lt;li&gt;IReportService - responsible for establishing contact with the communication service shard (which will handle all the exception handling and reliability on its own) and sending the feedback report;&lt;/li&gt;
&lt;li&gt;IClientInteractions - provides UI-specific methods that allow to interact with user;&lt;/li&gt;
&lt;li&gt;Optional{ServiceConnection}.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last item is the most interesting one here. Here's why and how it works.&lt;/p&gt;

&lt;h2&gt;Optional Components&lt;/h2&gt;

&lt;p&gt;When we show feedback report window - we want to suggest user to use his existing email address and connection information. This way the feedback could be routed to the appropriate server and associated with the user's account. &lt;/p&gt;

&lt;p&gt;And we want to have code working in situations, when user context is not available (i.e.: user logged off or context is not even known).&lt;/p&gt;

&lt;p&gt;That's what the Optional{ServiceConnection} does. It allows to pass some information via IoC container, while indicating that the reference could be empty at the moment of retrieval. It's declaration is extremely simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt; Simple delegate that returns optional result &amp;lt;/summary&amp;gt;
public delegate Maybe&amp;lt;TResult&amp;gt; Optional&amp;lt;TResult&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's it. Yes, that resembles &lt;em&gt;Lazy&lt;/em&gt; of MEF, but is a bit simpler, does not require MEF libraries and can benefit from the synergy with &lt;a href="http://abdullin.com/journal/2009/10/6/zen-development-practices-c-maybe-monad.html"&gt;Maybe Monad&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;For example, if we want to get current user name in one of the views (if the user name is available), the code might look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// somewhere in the class
readonly Optional&amp;lt;ServiceConnection&amp;gt; _contextProvider;

// somewhere in the code
var sender = _contextProvider()
  .Convert(sc =&amp;gt; sc.Username)
  .GetValue(AnonymousUserName);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;While the registration of the optional might look like:   &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// extension method for Autofac ContainerBuilder
public static void RegisterExport&amp;lt;TComponent, TExported&amp;gt;(
  this ContainerBuilder builder,
  Func&amp;lt;TComponent, Maybe&amp;lt;TExported&amp;gt;&amp;gt; func)
{
  builder.Register&amp;lt;Optional&amp;lt;TExported&amp;gt;&amp;gt;(c =&amp;gt; 
    () =&amp;gt; func(c.Resolve&amp;lt;TComponent&amp;gt;()));
}

// actual registration
builder.RegisterExport&amp;lt;IApplicationController, ServiceConnection&amp;gt;(c =&amp;gt; 
  c.Context.Convert(ec =&amp;gt; ec.Connection));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this registration at hand, all trusted components that need to have access to the current connection context, can do that by requesting an instance of Optional{ServiceContext}.&lt;/p&gt;

&lt;p&gt;This technique is really useful when defining boundaries of infrastructure shards, required and optional dependencies that they might have.&lt;/p&gt;

&lt;h2&gt;Unit Testing&lt;/h2&gt;

&lt;p&gt;We can even easily isolate the shard in unit test in order to allow manual testing of feedback reporting:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Test, Explicit]
public void Show_synthetic_feedback()
{
  var data = RandFeedbackModels.NextTextDatas(0, 3);
  CreateService().ReportFeedback(data);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where &lt;em&gt;CreateService&lt;/em&gt; explicitly establishes all dependencies in the MockContainer and grabs the service:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IFeedbackService CreateService()
{
  Build(cb =&amp;gt;
  {
    // factories
    cb.Register&amp;lt;Func&amp;lt;ServiceConnection, ILokadService&amp;gt;&amp;gt;(ServiceFactory.GetConnector);
    cb.Register&amp;lt;Optional&amp;lt;ServiceConnection&amp;gt;&amp;gt;(() =&amp;gt; Maybe&amp;lt;ServiceConnection&amp;gt;.Empty);

    // services
    cb.Register&amp;lt;FeedbackService&amp;gt;().As&amp;lt;IFeedbackService&amp;gt;();
    cb.Register&amp;lt;ReportService&amp;gt;().As&amp;lt;IReportService&amp;gt;();

    cb.Register&amp;lt;FeedbackSenderController&amp;gt;().As&amp;lt;IFeedbackSenderState&amp;gt;();
  });

  WhenViewIsShown.Do(f =&amp;gt; f.ShowDialog());

  return Resolve&amp;lt;IFeedbackService&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see for the service connection provider we are passing a lambda expression that returns an empty connection context. &lt;/p&gt;

&lt;p&gt;Note that we are not establishing any view-related components, since ViewFixture (this test fixture derives from it) already does this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cb.Register&amp;lt;TView&amp;gt;().As&amp;lt;TView, TInterface&amp;gt;();
cb.Register&amp;lt;TestViewspace&amp;gt;().As&amp;lt;IViewspace, TestViewspace&amp;gt;();
cb.Register&amp;lt;TestInteractions&amp;gt;().As&amp;lt;IClientInteractions, TestInteractions&amp;gt;();
cb.Register(Specifics.Empty);
OnBuild(cb);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Result looks like this:&lt;/p&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/10/2009-10-21_093127.png?__SQUARESPACE_CACHEVERSION=1256110458483" alt=""/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Filling in the information and clicking Send would create a ticket in &lt;a href="http://www.lokad.com" target="_blank" class="offsite-link-inline"&gt;Lokad&lt;/a&gt; support system. By the way, you can use this opportunity to say what you think about the company.&lt;/p&gt;

&lt;h2&gt;Shard Synergies&lt;/h2&gt;

&lt;p&gt;Here are some additional synergy effects that come from using infrastructure shards to reuse similar components between multiple applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business functionality could be used to extend multiple applications. Since UI is shared, we could use shared documentation, tutorials and screenshots as well.&lt;/li&gt;
&lt;li&gt;Sometimes context requires infrastructure shard to be evolved. This brings potential improvements in all existing and new applications.&lt;/li&gt;
&lt;li&gt;When a group of components is developed to be used in multiple scenarios from the start, this polishes the overall design even further than &lt;a href="http://abdullin.com/wiki/test-driven-development-tdd.html"&gt;TDD&lt;/a&gt; or &lt;a href="http://abdullin.com/wiki/component-driven-development.html"&gt;CDD&lt;/a&gt; would alone.&lt;/li&gt;
&lt;li&gt;Localization or UI changes across the software product line become easier, since the effort does not have to be duplicated and tested in multiple codebases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;What do you think about all that?&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;Notes&lt;/h2&gt;

&lt;p&gt;I understand that this looks really similar to what Microsoft Extensibility Framework does with &lt;em&gt;Lazy&lt;/em&gt; and &lt;em&gt;Export&lt;/em&gt; . However, my belief is that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;extensibility discovery and management framework should stay completely detached from the components;&lt;/li&gt;
&lt;li&gt;inversion of control container should stay completely detached from the framework as well;&lt;/li&gt;
&lt;li&gt;attribute-based declarations on the components are evil;&lt;/li&gt;
&lt;li&gt;all component dependencies should be explicitly declared in the orchestrating code in strongly-typed manner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that the core components should not use extensibility framework. Infrastructure shard boundaries might do that, while acting as a simple gateways. But that's another story.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="http://feeds.abdullin.com/RinatAbdullin"&gt;subscribe to this journal&lt;/a&gt; to get all the updates. &lt;a href="http://abdullin.uservoice.com/" target="_blank" class="offsite-link-inline"&gt;Voting for the next article to be written&lt;/a&gt; is also possible.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=zbWCBO4o6Hk:kt0E4QtsqBo:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=zbWCBO4o6Hk:kt0E4QtsqBo:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=zbWCBO4o6Hk:kt0E4QtsqBo:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=zbWCBO4o6Hk:kt0E4QtsqBo:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=zbWCBO4o6Hk:kt0E4QtsqBo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=zbWCBO4o6Hk:kt0E4QtsqBo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=zbWCBO4o6Hk:kt0E4QtsqBo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=zbWCBO4o6Hk:kt0E4QtsqBo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/zbWCBO4o6Hk" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-5564154.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/10/21/infrastructure-shards-and-optional-components.html</feedburner:origLink></item><item><title>Efficient Development, Deployment and Customer Feedback at Lokad</title><category>Articles</category><category>Integration</category><category>Lifehacks</category><category>Lokad</category><category>TechOverview</category><category>Theory</category><category>xLim</category><dc:creator>Rinat Abdullin</dc:creator><pubDate>Mon, 19 Oct 2009 07:25:27 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/KjlxWpZyack/efficient-development-deployment-and-customer-feedback-at-lo.html</link><guid isPermaLink="false">287483:2929700:5548601</guid><description>&lt;p&gt;A while ago I wrote about &lt;a href="http://abdullin.com/journal/2009/7/8/deployment-and-updates-of-desktop-applications-wix-clickonce.html"&gt;deployment and updates of the desktop applications&lt;/a&gt; and outlined the technology we use at &lt;a href="http://lokad.com/" target="_blank" class="offsite-link-inline"&gt;Lokad&lt;/a&gt; for rapid and efficient delivery of various updates to the customers.&lt;/p&gt;

&lt;p&gt;Let's expand on the topic a little bit more, showing how a small company could create quite a bit of business value via some efficient development practices.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There will be a small questionnaire at the end of this article as well.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Development and Deployment Experience&lt;/h2&gt;

&lt;p&gt;Current application deployment and publication loop for &lt;a href="http://www.lokad.com/products.ashx" target="_blank" class="offsite-link-inline"&gt;Lokad Client Applications&lt;/a&gt; works like this: when developers commit new features or fixes to &lt;a href="http://abdullin.com/wiki/version-control-system-vcs.html"&gt;version control repository&lt;/a&gt; and hit a special build button on &lt;a href="http://abdullin.com/wiki/continuous-integration.html"&gt;integration server&lt;/a&gt;, following happens automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All &lt;a href="http://abdullin.com/wiki/unit-testing.html"&gt;unit tests&lt;/a&gt;, integration and code quality tests are executed against the latest codebase (build breaks if these fail).&lt;/li&gt;
&lt;li&gt;New version of install package (and optional downloads) is deployed to publicly available location.&lt;/li&gt;
&lt;li&gt;Download page is updated with the links to the new version.&lt;/li&gt;
&lt;li&gt;Existing users of an application get a nice "Update Available!" notification in the corner of their toolbar. Clicking on it launches semi-automatic download and upgrade process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note, that we are not using ClickOnce technology here, since it has important limitations we couldn't live with. Everything took a bit of time to setup once and then it is just started flowing.&lt;/p&gt;

&lt;h2&gt;Customer Feedback Experience&lt;/h2&gt;

&lt;p&gt;Recently, in order to enhance customer experience, yet another simple feature had been added to the client applications: integrated feedback reporting. Simply put, customer could click a button and send a message to the company. It will immediately show up in the customer support system. Additionally, all unhandled exceptions (should they happen) could be reported, too.&lt;/p&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/10/2009-10-19_103122.png" alt="Feedback button in Lokad"/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Feedback reports  (if customers decide to) could include following anonymous information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;system descriptor of the software (version, OS version);&lt;/li&gt;
&lt;li&gt;versions of the assemblies loaded into the AppDomain;&lt;/li&gt;
&lt;li&gt;latest portion of application log;&lt;/li&gt;
&lt;li&gt;statistics of some performance counters showing client-side information about interactions with our servers (number of communication failures, retries, amount of data transferred);&lt;/li&gt;
&lt;li&gt;exception counter statistics (information about unique exceptions handled by the application along with their counts).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span class="full-image-block ssNonEditable"&gt;&lt;span&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/10/2009-10-19_103222.png" alt="Feedback reporting to Lokad Support"/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Note, that sources for the &lt;em&gt;SystemDescriptor&lt;/em&gt;, &lt;em&gt;ExecutionCounter&lt;/em&gt; and &lt;em&gt;ExceptionCounter&lt;/em&gt; are available in &lt;a href="http://abdullin.com/shared-libraries/"&gt;Lokad Shared Libraries&lt;/a&gt;. Actual feedback reporting shard is shared with the community in the &lt;a href="http://code.google.com/p/lokad-sdk/" target="_blank" class="offsite-link-inline"&gt;Lokad SDK&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback system had been implemented as an infrastructure shard within the shared codebase. This implied IoC-friendly &lt;a href="http://abdullin.com/wiki/component-driven-development.html"&gt;component-driven design&lt;/a&gt; and allowed to efficiently reuse all components in multiple applications (even in these that didn't have any IoC infrastructure around). All improvements and fixes to the shared components, in such scenario, automatically benefit all applications that use them.&lt;/p&gt;

&lt;p&gt;Additionally, since the feedback system is implemented as an independent infrastructure shard, it can be used to trap and report possible exceptions that take place on the application startup (even before the &lt;a href="http://abdullin.com/wiki/inversion-of-control-ioc.html"&gt;Inversion of Control&lt;/a&gt; Container is setup). Later, when the application and composite UI elements are ready, we switch stand-alone feedback handler for integrated handler (that uses, application's Viewspace and action policies, for instance)&lt;/p&gt;

&lt;p&gt;This reduced feedback friction for the customers and made issue reports a lot more useful and helpful for the development team. Since all feedback reports get routed to the internal customer support system, we could feel the change really fast and resolve problems and provide solutions more efficiently.&lt;/p&gt;

&lt;h2&gt;New Challenge - Update Flood&lt;/h2&gt;

&lt;p&gt;This kind of automatic and tight integration between development, deployment and customer support spawns new possibilities and brings forth new challenges. First of all, it definitely affects the way we think about the development and plan future changes.&lt;/p&gt;

&lt;p&gt;Second, since it is too easy to deploy an update, we've got to start thinking about protecting customers from being flooded with a number of updates (software should solve the problems, not create new ones), since theoretically we could fire the deployment update after every single verified fix that is landed in the trunk.&lt;/p&gt;

&lt;p&gt;Here's how one of the implementation scenarios looks like right now.&lt;/p&gt;

&lt;p&gt;All software updates (packaged as a complete version, as usually) could be described with a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;version;&lt;/li&gt;
&lt;li&gt;download url;&lt;/li&gt;
&lt;li&gt;tags (Critical, RC, Test, Major etc)&lt;/li&gt;
&lt;li&gt;optional description.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Primary download page is automatically updated with the links only when "Critical" and "Major" versions are released.&lt;/p&gt;

&lt;p&gt;Customers are unformed about the Major updates to the installed software with a usual manner (i.e.: toolbar notification). Less-important updates are not shown to them explicitly but could be pulled (i.e.: from the menu), if customer needs that.&lt;/p&gt;

&lt;p&gt;This scenario should work if we are facing scenario, when there is a minor fix affecting only a single customer. We could deploy an update via the normal procedure, but it does not make a lot of sense to push updates to every single customer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation should be rather straightforward:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of updating simple txt on the server per every update, we could update an XML file in the RSS/Atom format with the build version, url, description and tags.&lt;/li&gt;
&lt;li&gt;By default every application filters out all non-Primary updates, displaying the rest on the toolbar. This way we deliver important functionality to customers, while saving them from the barrage of less important builds.&lt;/li&gt;
&lt;li&gt;Customers might explicitly look into the update stream, picking and firing the specific update they need (i.e. when informed about the fix by the customer support).&lt;/li&gt;
&lt;li&gt;Beta testers and partners might update application settings to be notified about RC and Minor deployments&lt;/li&gt;
&lt;li&gt;Developers and Testers might switch their filtering settings to include Beta and Minor updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Potential synergy effects:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updates could be subscribed to via a mere RSS reader and mashed with a company news (automagically).&lt;/li&gt;
&lt;li&gt;Since we are already tracking Delivery-Build labels for issues, this information could be pasted to the description dialog, providing customers and testers with more context (could be available from the application and from the web/RSS).&lt;/li&gt;
&lt;li&gt;It is possible to push the idea even further and let customers set simple filter in their application ("inform me when ticket #X is fixed"). Then, whenever the next deployment is detected, a simple regex could scan the description for the ticket number, raising friendly alert, whenever it is mentioned there.&lt;/li&gt;
&lt;li&gt;If we have a critical update at hand (i.e.: breaking API change or an important security vulnerability) we can block the entire app and insist on updating.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything might get even more interesting as extensible and composable application architectures (with extensions being developed and delivered concurrently) get into the picture, allowing fine-grained and yet automated customer-company interactions.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;In this short article we've walked over some development practices adopted in Lokad. These practices help the company to resolve customer problems and provide new solutions to their business challenges.&lt;/p&gt;

&lt;p&gt;In short the outlined practices include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;efficient software deployment and updates;&lt;/li&gt;
&lt;li&gt;efficient customer support and feedback collection;&lt;/li&gt;
&lt;li&gt;considering synergy effects and automation, whenever possible and feasible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, there's a lot more in efficient development, than these few practices. I'll address them eventually. You can &lt;a href="http://feeds.abdullin.com/RinatAbdullin"&gt;subscribe to this journal&lt;/a&gt; to get all the updates. &lt;a href="http://abdullin.uservoice.com/" target="_blank" class="offsite-link-inline"&gt;Voting for the next article to be written&lt;/a&gt; is also possible.&lt;/p&gt;

&lt;p&gt;As always, all feedback to the article is welcome and appreciated. Here are also a few questions, if you are willing to share your experience with the community around this Journal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How much time does it takes for the customer to report a problem and get an update in your development environment?&lt;/li&gt;
&lt;li&gt;Does your company share the code with the community?&lt;/li&gt;
&lt;li&gt;Are you a customer of Lokad? What do you think about this development approach? How could it be improved?&lt;/li&gt;
&lt;li&gt;Are you a competitor of Lokad? What do you think? ))&lt;/li&gt;
&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=KjlxWpZyack:E-GSZ09PiaE:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=KjlxWpZyack:E-GSZ09PiaE:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=KjlxWpZyack:E-GSZ09PiaE:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=KjlxWpZyack:E-GSZ09PiaE:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=KjlxWpZyack:E-GSZ09PiaE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=KjlxWpZyack:E-GSZ09PiaE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=KjlxWpZyack:E-GSZ09PiaE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=KjlxWpZyack:E-GSZ09PiaE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/KjlxWpZyack" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-5548601.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/10/19/efficient-development-deployment-and-customer-feedback-at-lo.html</feedburner:origLink></item><item><title>Let's Make Blogging More Efficient, Just like the Development</title><dc:creator>Rinat Abdullin</dc:creator><pubDate>Sat, 10 Oct 2009 11:59:08 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/7LIKRyX5TkE/lets-make-blogging-more-efficient-just-like-the-development.html</link><guid isPermaLink="false">287483:2929700:5456970</guid><description>&lt;p&gt;Over the course of the last few months I've gathered quite a few ideas and drafts about things that I wanted to share thoughts about. However, since there are too many of these, sometimes it is hard to pick one topic that deserves being turned into an article before the others.&lt;/p&gt;

&lt;p&gt;To clear up the whole blogging process and make it more efficient (just like in the software development), I've created a &lt;a href="http://abdullin.uservoice.com" target="_blank" class="offsite-link-inline"&gt;feedback forum for this Journal&lt;/a&gt; on uservoice and filled it with a list of some planned articles.&lt;/p&gt;

&lt;p&gt;It works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can check out these &lt;em&gt;article ideas&lt;/em&gt; and post some feedback on them (adding comments, questions).&lt;/li&gt;
&lt;li&gt;Every uservoice user is granted with 10 votes. You can &lt;strong&gt;distribute your votes between existing article ideas&lt;/strong&gt; or even &lt;strong&gt;create a new one&lt;/strong&gt; for a topic on efficient software development, that's dear to your heart.&lt;/li&gt;
&lt;li&gt;Whenever I'm stuck picking the next article to work on, uservoice should provide the clear picture of what interests the community around this Journal (eventually also providing an additional motivation to move forward).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see if this works out, shall we?&lt;/p&gt;

&lt;p&gt;Here's the link: &lt;a href="http://abdullin.uservoice.com" target="_blank" class="offsite-link-inline"&gt;What articles are you interested to read next?&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=7LIKRyX5TkE:a7iRMe6_dOE:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=7LIKRyX5TkE:a7iRMe6_dOE:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=7LIKRyX5TkE:a7iRMe6_dOE:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=7LIKRyX5TkE:a7iRMe6_dOE:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=7LIKRyX5TkE:a7iRMe6_dOE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=7LIKRyX5TkE:a7iRMe6_dOE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=7LIKRyX5TkE:a7iRMe6_dOE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=7LIKRyX5TkE:a7iRMe6_dOE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/7LIKRyX5TkE" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-5456970.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/10/10/lets-make-blogging-more-efficient-just-like-the-development.html</feedburner:origLink></item><item><title>Update on Maybe Monad: Q&amp;As and Caveats</title><dc:creator>Rinat Abdullin</dc:creator><pubDate>Thu, 08 Oct 2009 12:24:43 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/xjYuDmYKb90/update-on-maybe-monad-qas-and-caveats.html</link><guid isPermaLink="false">287483:2929700:5434067</guid><description>&lt;p&gt;My last Zen dev article on &lt;a href="http://abdullin.com/journal/2009/10/6/zen-development-practices-c-maybe-monad.html"&gt;Maybe Monad for C#&lt;/a&gt; had caused quite a few arguments and comments coming from different directions.&lt;/p&gt;

&lt;p&gt;To make the information exchange slightly more efficient, I've composed a few additions for the article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Questions and Answers&lt;/li&gt;
&lt;li&gt;Caveats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find this new content either below or in the &lt;a href="http://abdullin.com/journal/2009/10/6/zen-development-practices-c-maybe-monad.html"&gt;original article&lt;/a&gt; that had been updated. All new major updates on the topic will be delivered in the same way.&lt;/p&gt;

&lt;h2&gt;Questions and Answers&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;Why add another needless layer of complexity for such a simple task? Just learn how to use the null coalescing operator (??) and/or inline if-thens.&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Console.WriteLine(number != null ? "True" : "False");
Console.WriteLine(number ?? "Null Value");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Imagine a large real-world project that spawns multiple components and tiers, while facing problems slightly more challenging, than writing output to the console. If developers know that this project uses Maybe to declare potentially empty variables, then they are completely freed from checking for nulls and even thinking about that. That's one less thing to bother, making quite a difference in complex scenarios (and &lt;a href="http://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two" target="_blank" class="offsite-link-inline"&gt;human being can simultaneously bother only about 7 things max&lt;/a&gt;, anyway).&lt;/p&gt;

&lt;p&gt;This actual usage of &lt;em&gt;Maybe{T}&lt;/em&gt; might happen in just one or two methods of the project. However, when developers use them, they will know immediately (and not from the documentation) and will be forced to handle them because of the syntax.&lt;/p&gt;

&lt;p&gt;Things like that reduce development friction and allow complex project to be delivered efficiently and with really small teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;How is this different from Nullable{T} in C#?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Only value types are supported by Nullable generic (or its shorthand syntax). So you can't use a class variable in a nullable type (which makes sense, since the reference itself can be &lt;em&gt;null&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;Why do Lokad Shared Libraries feature null checks, although Maybe{T} is declared in the code?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because &lt;em&gt;Lokad.Shared.dll&lt;/em&gt;, as a really lightweight library, might be used in various projects. Some of these projects might not have "no nulls returned and expected" policy. So it is logical to protect shared methods from the nulls explicitly. in order to avoid the unpredictable behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;How do I use Maybe{T} if method can fail because of the multiple reasons and I want to know them&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Maybe{T}&lt;/em&gt; on its own is not designed to handle such situations. These are the primary logically-complete solutions for this situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can return &lt;em&gt;Maybe{T}&lt;/em&gt; while printing multiple failure details to the &lt;em&gt;IScope&lt;/em&gt; passed as an argument. That's how &lt;a href="http://abdullin.com/journal/2008/11/23/net-application-block-for-validation-and-business-rules.html"&gt;Lokad Rules&lt;/a&gt; are working. It also works well in long-running complex (especially asynchronous) operations that require logging and detailed failure control.&lt;/li&gt;
&lt;li&gt;You can use &lt;em&gt;Result{TValue,TError}&lt;/em&gt; monad returning strongly-typed error result (i.e.: enumeration value) or it's generic counterpart Result{TValue} (if the strong-typing is not possible for some reason).&lt;/li&gt;
&lt;li&gt;You can always use good old exceptions, if the above options do not suite you for some reason and you are OK with try-cath and breaking the functional code flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Caveats&lt;/h2&gt;

&lt;p&gt;This approach, as any other piece of knowledge from the &lt;a href="http://abdullin.com/xlim/"&gt;xLim body of knowledge&lt;/a&gt;, might be controversial and not applicable for you projects, development practices and beliefs.&lt;/p&gt;

&lt;p&gt;All that I can say - it works for me, allowing &lt;em&gt;slightly more efficient&lt;/em&gt; delivery, evolution and maintenance of .NET development projects ranging from business analytics servers, RESTful NoSql automation engines and up to Smart Client applications with reusable MVC infrastructure shards.&lt;/p&gt;

&lt;p&gt;This limited improvement in development efficiency sometimes requires using approaches and principles that may be somewhat incompatible with the traditional ones (MS .NET or Alt.NET), while continuously enforcing them across the codebases. But in the end, I think, it's worth it, just like &lt;a href="http://abdullin.com/wiki/continuous-integration.html"&gt;Continuous Integration&lt;/a&gt; or &lt;a href="http://abdullin.com/wiki/inversion-of-control-ioc.html"&gt;Inversion of Control&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But again, that's the way of Zen - everybody has his own way to satori.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As this is an update article, all comments are disabled here. Please use &lt;a href="http://abdullin.com/journal/2009/10/6/zen-development-practices-c-maybe-monad.html"&gt;original article on Maybe Monad&lt;/a&gt; for sharing your feedback (which is welcome and appreciated).&lt;/em&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=xjYuDmYKb90:BLtElPf_mxs:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=xjYuDmYKb90:BLtElPf_mxs:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=xjYuDmYKb90:BLtElPf_mxs:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=xjYuDmYKb90:BLtElPf_mxs:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=xjYuDmYKb90:BLtElPf_mxs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=xjYuDmYKb90:BLtElPf_mxs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=xjYuDmYKb90:BLtElPf_mxs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=xjYuDmYKb90:BLtElPf_mxs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/xjYuDmYKb90" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-5434067.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/10/8/update-on-maybe-monad-qas-and-caveats.html</feedburner:origLink></item><item><title>Zen Development Practices: C# Maybe Monad</title><category>Articles</category><category>C#</category><category>Lifehacks</category><category>Lokad</category><category>Snippets</category><category>Theory</category><category>Tips</category><category>xLim</category><dc:creator>Rinat Abdullin</dc:creator><pubDate>Mon, 05 Oct 2009 19:25:10 +0000</pubDate><link>http://feeds.abdullin.com/~r/RinatAbdullin/~3/CLAGosCD_ok/zen-development-practices-c-maybe-monad.html</link><guid isPermaLink="false">287483:2929700:5404980</guid><description>&lt;p&gt;One of the things I like about software development is a simple fact, that &lt;em&gt;efficiently developed code, block or software, takes much more time to document, than to deliver&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This efficiency could be based on certain practices, constraints and principles, followed by discipline. These items allow to take away small bits of complexity and development friction, allowing us to concentrate on the things that really matter and generate business value.&lt;/p&gt;

&lt;p&gt;Let's talk about one of this small things - a really simple construct in C# called Maybe (of the &lt;a href="http://en.wikipedia.org/wiki/Monad_(functional_programming)" target="_blank" class="offsite-link-inline"&gt;monad fame&lt;/a&gt;) that had completely freed me from all cases of NullReferenceException in my code, while making it cleaner.&lt;/p&gt;

&lt;p&gt;Sounds interesting? Let's have a look at the C# code and .NET usage patterns.&lt;/p&gt;

&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Maybe&amp;lt;T&amp;gt;&lt;/strong&gt;, as the &lt;em&gt;simplest monad implementation in .NET&lt;/em&gt;, is a &lt;strong&gt;generic class that can either hold value of type T or be empty&lt;/strong&gt;. There is a little bit of &lt;strong&gt;helper syntax&lt;/strong&gt; and some &lt;strong&gt;usage guidelines and patterns&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In this article we'll cover all of these; links for the sources in C# and binaries would be provided, too.&lt;/p&gt;

&lt;p&gt;Here's how the declaration of the Maybe class starts in C#:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Serializable, Immutable]
public sealed class Maybe&amp;lt;T&amp;gt; : IEquatable&amp;lt;Maybe&amp;lt;T&amp;gt;&amp;gt;
{
  readonly T _value;
  readonly bool _hasValue;

  Maybe(T item, bool hasValue)
  {
    _value = item;
    _hasValue = hasValue;
  }

  /// &amp;lt;summary&amp;gt; Gets the underlying value, if it is available &amp;lt;/summary&amp;gt;
  /// &amp;lt;value&amp;gt;The value.&amp;lt;/value&amp;gt;
  public T Value
  {
    get
    {
      if (!_hasValue)
        throw Errors.InvalidOperation(
          ResultResources.Dont_access_value_when_maybe_is_empty);

      return _value;
    }
  }

  internal Maybe(T value)
    : this(value, true)
  {
    // ReSharper disable CompareNonConstrainedGenericWithNull
    if (value == null) throw new ArgumentNullException("value");
    // ReSharper restore CompareNonConstrainedGenericWithNull
  }

  /// &amp;lt;summary&amp;gt; Gets a value indicating whether this instance 
  /// has value. &amp;lt;/summary&amp;gt;
  /// &amp;lt;value&amp;gt;&amp;lt;c&amp;gt;true&amp;lt;/c&amp;gt; if this instance has value; otherwise, 
  /// &amp;lt;c&amp;gt;false&amp;lt;/c&amp;gt;.&amp;lt;/value&amp;gt;
  public bool HasValue
  {
    get { return _hasValue; }
  }

  /// &amp;lt;summary&amp;gt;
  /// Default empty instance.
  /// &amp;lt;/summary&amp;gt;
  public static readonly Maybe&amp;lt;T&amp;gt; Empty = new Maybe&amp;lt;T&amp;gt;(default(T), false);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are a few implicit operators and helpers methods that improve the usage experience (we'll talk about them later), but the simple code above is the core of the approach. Primary monad operations could be expressed in this simple snippet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// function that MIGHT return a number
Maybe&amp;lt;int&amp;gt; DetectNumber(string number)
{
  switch (number)
  {
    case "Zero":
      // we are allowed an implicit conversion
      // so here we return a number directly
      return 0;
    case "One":
      return 1;
    case "Two":
      return 2;
    default:
      // empty singleton for missing value
      return Maybe&amp;lt;int&amp;gt;.Empty;
  }
}


// Actually getting a Monad in C#
var number = DetectNumber("Zero");

// prints "True"
Console.WriteLine(number.HasValue);
// prints "0"
Console.WriteLine(number.Value);


var number2 = DetectNumber("Hm..");
// prints "False"
Console.WriteLine(number2.HasValue);
// throws InvalidOperationException
Console.WriteLine(number2.Value);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So basically this &lt;em&gt;Maybe&lt;/em&gt; monad is extremely simple class that can either be empty or have value. If it is empty, and we attempt to access value, then the exception is thrown. In other words, that's a strongly-typed reference to an object that acts like null with some syntactic flavor.&lt;/p&gt;

&lt;p&gt;How is it even better than using nullable references and getting &lt;em&gt;NullReferenceException&lt;/em&gt; when you forget to check for &lt;em&gt;null&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Here are the reasons justifying the usage of &lt;em&gt;Maybe{T}&lt;/em&gt; for me:&lt;/p&gt;

&lt;h2&gt;Reason 1: Good Citizenship&lt;/h2&gt;

&lt;p&gt;By using Maybe{T} in my code I promise that all the code will be following good citizenship principles and will keep &lt;strong&gt;all&lt;/strong&gt; object references non-null (initialized to some value from the default). This promise is to be uphold by a self-discipline and unit tests.&lt;/p&gt;

&lt;p&gt;This helps to avoid all null references completely.&lt;/p&gt;

&lt;h2&gt;Reason 2: Explicit behavior and clean code&lt;/h2&gt;

&lt;p&gt;If there is a potentially nullable reference, parameter or a function return result, then it should be explicitly marked with the &lt;em&gt;Maybe{T}&lt;/em&gt;, exposing its behaviour to the reader and forcing him to explicitly handle the states.&lt;/p&gt;

&lt;p&gt;Additionally, using &lt;em&gt;Maybe{T}&lt;/em&gt; allows us to avoid throwing weird exceptions or returning nulls in situations, where result could be undefined. &lt;/p&gt;

&lt;p&gt;Consider declaration of the method like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt; Parses an encoded string into
/// authentication information. &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="encodedString"&amp;gt;Encoded string.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;authentication information&amp;lt;/returns&amp;gt;
/// &amp;lt;exception cref="ArgumentNullException"&amp;gt;when string is null&amp;lt;/exception&amp;gt;
/// &amp;lt;exception cref="InvalidOperationException"&amp;gt;when string is invalid&amp;lt;/exception&amp;gt;
AuthInfo ParseStringToAuthInfo(string encodedString);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This method declaration is really similar to a lot of existing methods from the .NET BCL (i.e.: &lt;em&gt;int.Parse&lt;/em&gt; as the simplest one) and it shares a lot of excessive noise and inherent problems. Most importantly we are throwing some exceptions, when the input is not expected and could not be handled gracefully. This:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blows the code execution and must be handled by a separate try-catch;&lt;/li&gt;
&lt;li&gt;requires code consumer to read the documentation instead of reading the method signature;&lt;/li&gt;
&lt;li&gt;does not prevent the code from potentially breaking in every single place, should we refactor and replace &lt;em&gt;InvalidOperationException&lt;/em&gt; by &lt;em&gt;InvalidAuthDataException&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's rewrite the method signature using the &lt;em&gt;Maybe&lt;/em&gt; monad style:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt; Attempts to parse an encoded string into 
/// authentication information. &amp;lt;/summary&amp;gt;
/// &amp;lt;param name="encodedString"&amp;gt;Encoded string.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;authentication information&amp;lt;/returns&amp;gt;
static Maybe&amp;lt;AuthInfo&amp;gt; ParseStringToAuthInfo(string encodedString)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this refactoring we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;decoupled ourselves from the &lt;em&gt;ArgumentNullException&lt;/em&gt;, since we believe that input will never be null. Method body would live without the appropriate null check as well;&lt;/li&gt;
&lt;li&gt;decoupled ourselves from the &lt;em&gt;InvalidOperationException&lt;/em&gt; and use optional value, that would be valid only if the parsing succeeded;&lt;/li&gt;
&lt;li&gt;no longer require the developer using the method to look in the code documentation in order to understand what exactly the method works;&lt;/li&gt;
&lt;li&gt;do not need defensive and noisy try-catch programming around the calls to this method (or anywhere in the call stack).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, there are other refactoring alternatives to the signature:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// Option1 : use bool
static bool TryParseString(string encodedString, out AuthInfo);   
// Option 2: return value that could be null
static AuthInfo ParseString(string encodedString);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;First option&lt;/em&gt; uses the TryGetValue approach you can see on the IDictionary interface. This approach resorts to the &lt;em&gt;out&lt;/em&gt; keyword (which I always avoid), breaks the functional style of the programming (method should always have a single value being returned) and adds some noise to the using code.&lt;/p&gt;

&lt;p&gt;Also &lt;em&gt;AuthInfo&lt;/em&gt; is returned as undefined, if the parsing fails, violating the good citizenship.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Second option&lt;/em&gt; returns value that would be &lt;em&gt;null&lt;/em&gt; in case the parsing fails. Developer, in order to discover this, has to read the documentation. And he has to protect himself from the possible problems with null checks against the result.&lt;/p&gt;

&lt;p&gt;In my opinion, method using the &lt;em&gt;Maybe&lt;/em&gt; monad is the most clean approach of them all. &lt;/p&gt;

&lt;h2&gt;Reason 3: Chaining and pipeline syntax&lt;/h2&gt;

&lt;p&gt;Ok, so we have our Maybe-powered method signature:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;static Maybe&amp;lt;AuthInfo&amp;gt; ParseStringToAuthInfo(string encodedString);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's actually see the full power of the concept in C# on a sample taken fresh from the production code. Consider the method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// simple pipeline sequence
Maybe&amp;lt;AuthPrincipal&amp;gt; LoadPrincipal(string key)
{
  return ParseStringToAuthInfo(key)
    .Combine(u =&amp;gt; _service.BuildAccountSession(u))
    .Convert(sa =&amp;gt; new AuthPrincipal(sa));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this LINQ-style and purely functional sequence of 3 lines, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attempt to parse the key into &lt;em&gt;AuthInfo&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;If the attempt was successful, we use some service to try to build an account session out of the parsed &lt;em&gt;AuthInfo&lt;/em&gt;. &lt;em&gt;BuildAccountSession&lt;/em&gt; operation might also fail, by the way. This is indicated in the method signature (by using Maybe) and would happen if the provided &lt;em&gt;AuthInfo&lt;/em&gt; didn't have a match in the repository.&lt;/li&gt;
&lt;li&gt;If we were successful in parsing the original string and in building the account session, then we create a new &lt;em&gt;AuthPrincipal&lt;/em&gt; class using this session; otherwise an empty Maybe{AuthPrincipal} is returned to indicate the composite failure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can see, detailed method description takes a bit more space, than the actual implementation. And the implementation itself is less fragile and smaller compared to traditional approach with nulls, throwing and handling various exceptions.&lt;/p&gt;

&lt;p&gt;After getting used to this benefit of Maybe, dealing with the code that has exceptions and nulls feels like working in Visual Studio without ReSharper installed. &lt;/p&gt;

&lt;p&gt;All the benefits listed above come from two classes (that contain less code, than this article) and some discipline. That's the way of &lt;a href="http://en.wikipedia.org/wiki/Zen" target="_blank" class="offsite-link-inline"&gt;Zen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://abdullin.com/storage/uploads/2009/07/2009-07-31-development-zen.jpg" alt="Zen image under Creative Commons Attribution ShareAlike 3.0 License from Wikipedia" /&gt;&lt;/p&gt;

&lt;p&gt;If you want to try &lt;em&gt;Maybe{T}&lt;/em&gt;, the code is available in &lt;em&gt;Lokad.Shared.dll&lt;/em&gt; from the &lt;a href="http://abdullin.com/shared-libraries/"&gt;Lokad Shared Libraries&lt;/a&gt;. You can either copy this class to your solution (while &lt;a href="http://feeds.abdullin.com/Shared-Libraries"&gt;keeping an eye on the project&lt;/a&gt; for any improvements and changes in the guidelines) or grab the latest download.&lt;/p&gt;

&lt;p&gt;Let's continue our article by outlining common operations available for Maybe{T}.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating Maybe&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// implicit conversion is the most common way to create Maybe&amp;lt;T&amp;gt;
// mostly it happens when we return actual value from within a
// method that returns maybe.
// Or, when we pass value into the optional function parameter
Maybe&amp;lt;int&amp;gt; maybeInt = 10;

// creates a maybe object when implicit casting is not available 
// for some reason (i.e.: anonymous types or failing type inferrence)
var nonEmptyMaybe = Maybe.From(value);

// each type has only a single empty maybe instance that is
// cached via the type-caching
var emptyAuthInfo = Maybe&amp;lt;AuthInfo&amp;gt;.Empty;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Getting Value&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// tests if the Maybe has value
var hasValue = maybeInt.HasValue;

// returns value behind the Maybe, throwing exception if it is empty
// this approach is rarely used (because of the pipeline operators)
var value = maybeInt.Value

// get's value from maybe, using some default, if it is empty
var value = maybeUsername.GetValue("guest@abdullin.com");

// get's value from maybe, executing default generation if it is empty
// handy for scenarios, when generating default values is CPU expensive
var value = maybeUsername.GetValue(() =&amp;gt; ComposeName());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Pipeline Operations&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// get Maybe that either has value derived from the parent Maybe
// or is empty, if the parent is empty
var maybeUsername = maybeIdentity.Convert(i =&amp;gt; i.Username);

// gets actual value that is derived from the parent Maybe, if it is not
// empty, or uses a predefined default 
// equivalent of Convert.GetValue
var username = maybeIdentity.Convert(i =&amp;gt; i.Username,"guest@abdullin.com");
var username = maybeIdentity.Convert(i =&amp;gt; i.Username,() =&amp;gt; ComposeName());

// combines result of the two Maybe's, either of which could be empty
var maybeFullName = maybeUsername.Combine(k =&amp;gt; LookupFullName(k));

// executes the action against the value, if Maybe is not empty,
// returns the original Maybe to continue pipelining 
maybeFullName.Apply(fn =&amp;gt; Console.WriteLine(fn))

// executes the action, if maybe is Empty
// returns the original Maybe to continue pipelining
maybeFullName.Handle(() =&amp;gt; Application.Terminate());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In addition to the operators above, &lt;em&gt;Maybe{T}&lt;/em&gt; class also defines proper equality and hashing operations. It is debugger-friendly, too.&lt;/p&gt;

&lt;p&gt;However, this does not end the list of reasons of using Maybe for the efficient development.&lt;/p&gt;

&lt;h2&gt;Reason 4: Simplified unit testing&lt;/h2&gt;

&lt;p&gt;Using &lt;em&gt;Maybe&lt;/em&gt; monad in .NET also has the benefit of allowing to introduce simplified DSL syntax for &lt;a href="http://abdullin.com/wiki/unit-testing.html"&gt;unit-testing&lt;/a&gt; code leveraging the approach. &lt;/p&gt;

&lt;p&gt;Here are the core extensions you need (they are pipelined together for the brevity)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// extensions checking different aspects of valid Maybe&amp;lt;T&amp;gt; monad
maybeValue
  .ShouldPass()
  .ShouldPassCheck(i =&amp;gt; i == 10)
  .ShouldPassWith(10)
  .ShouldBe(10)
  .ShouldBe(true);

// checking empty Maybe Moned
MaybeNot
  .ShouldFail()
  .ShouldBe(false);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Each extension, basically throws a descriptive assertion exception, if the condition is not met.&lt;/p&gt;

&lt;p&gt;Here's how the unit test might look like with one of these extensions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Test]
public void System_info_is_disabled()
{
  WhenViewIsShown.SetResult(DialogResult.OK);
  Subject.BindModel(RandClientModels.NextFeedbackView());
  Implementation.CheckSystemInfo(false);
  Subject
    .GetModel()
    .ShouldPassCheck(m =&amp;gt; m.SystemInformation == "");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the check fails, because the maybe has a value but this value is invalid, then the failure would look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;FailedAssertException: Expression should be true: '(m.SystemInformation = "")'.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These test extensions are located within &lt;em&gt;Lokad.Testing.dll&lt;/em&gt;, which is also a part of &lt;a href="http://abdullin.com/shared-libraries/"&gt;Lokad Shared Libraries&lt;/a&gt; within a &lt;em&gt;Lokad.Testing&lt;/em&gt; namespace.&lt;/p&gt;

&lt;p&gt;This separation is done in order to prevent &lt;em&gt;IntelliSense&lt;/em&gt; from being polluted with all the &lt;em&gt;Should&lt;/em&gt; statements, while we are working in the production code. Testing code, on the contrary can have access to these routines (which is done by referencing the testing assembly and using the namespace).&lt;/p&gt;

&lt;h2&gt;Reason 5: Initialization of Immutable classes&lt;/h2&gt;

&lt;p&gt;All we know that in F# it is extremely easy to create an immutable object from another record by providing a few override values in the cloning process:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let conn2 = { conn1 with Service = MyService }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we are using only C#-style immutable classes as models in our application (which is beneficial for a number of reasons, but is a large topic on its own), then we are limited to the constructor initialization only, which could be rather messy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// model definition
[Immutable, Serializable]
public sealed class ServiceConnection
{
  public readonly string Username;
  public readonly string Password;
  public readonly string AuthMode;
  public readonly Uri Service;

  public ServiceConnection(string username, string password, 
    string authMode, Uri service)
  {
    Username = username;
    Password = password;
    AuthMode = authMode;
    Service = service;
  }
}

// cloning with a custom service reference
var conn2 = new ServiceConnection(conn1.Username, conn2.Password, 
  conn2.AuthMode, MyService);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;More fields the model has, more messy cloning the process becomes. Fortunately, in the upcoming C# 4.0 we will be able to do everything more efficiently and with different combinations:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var conn2 = conn1.With(service: MyService);
var conn3 = conn1.With(username: Anonymous, AuthType: Plain);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This could be achieved with a single method by using C# 4.0 Optional Parameters and &lt;em&gt;Maybe{T}&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  public ServiceConnection With(
    string username = Maybe.String,
    string password = Maybe.String,
    string authType = Maybe.String,
    Uri service = Maybe.Uri)
  {
    return new ServiceConnection(
      username.GetValue(Username), 
      password.GetValue(Password),
      authType.GetValue(AuthType),
      service.GetValue(Service);
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;where &lt;em&gt;Maybe.String&lt;/em&gt; (and its &lt;em&gt;Uri&lt;/em&gt; analogue) is just a short-cut for Maybe{string}.Empty that is already declared on the &lt;em&gt;Maybe&lt;/em&gt; non-generic helper class in &lt;em&gt;Lokad.Shared.dll&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;Caveats&lt;/h2&gt;

&lt;p&gt;This approach, as any other piece of knowledge from the &lt;a href="http://abdullin.com/xlim/"&gt;xLim body of knowledge&lt;/a&gt;, might be controversial and not applicable for you projects, development practices and beliefs.&lt;/p&gt;

&lt;p&gt;All that I can say - it works for me, allowing &lt;em&gt;slightly more efficient&lt;/em&gt; delivery, evolution and maintenance of .NET development projects ranging from business analytics servers, RESTful NoSql automation engines and up to Smart Client applications with reusable MVC infrastructure shards.&lt;/p&gt;

&lt;p&gt;This limited improvement in development efficiency sometimes requires using approaches and principles that may be somewhat incompatible with the traditional ones (MS .NET or Alt.NET), while continuously enforcing them across the codebases. But in the end, I think, it's worth it, just like &lt;a href="http://abdullin.com/wiki/continuous-integration.html"&gt;Continuous Integration&lt;/a&gt; or &lt;a href="http://abdullin.com/wiki/inversion-of-control-ioc.html"&gt;Inversion of Control&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But again, that's the way of Zen - everybody has his own way to satori.&lt;/p&gt;

&lt;h2&gt;Questions and Answers&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;Why add another needless layer of complexity for such a simple task? Just learn how to use the null coalescing operator (??) and/or inline if-thens.&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Console.WriteLine(number != null ? "True" : "False");
Console.WriteLine(number ?? "Null Value");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Imagine a large real-world project that spawns multiple components and tiers, while facing problems slightly more challenging, than writing output to the console. If developers know that this project uses Maybe to declare potentially empty variables, then they are completely freed from checking for nulls and even thinking about that. That's one less thing to bother, making quite a difference in complex scenarios (and &lt;a href="http://en.wikipedia.org/wiki/The_Magical_Number_Seven,_Plus_or_Minus_Two" target="_blank" class="offsite-link-inline"&gt;human being can simultaneously bother only about 7 things max&lt;/a&gt;, anyway).&lt;/p&gt;

&lt;p&gt;This actual usage of &lt;em&gt;Maybe{T}&lt;/em&gt; might happen in just one or two methods of the project. However, when developers use them, they will know immediately (and not from the documentation) and will be forced to handle them because of the syntax.&lt;/p&gt;

&lt;p&gt;Things like that reduce development friction and allow complex project to be delivered efficiently and with really small teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;How is this different from Nullable{T} in C#?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Only value types are supported by Nullable generic (or its shorthand syntax). So you can't use a class variable in a nullable type (which makes sense, since the reference itself can be &lt;em&gt;null&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;Why do Lokad Shared Libraries feature null checks, although Maybe{T} is declared in the code?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because &lt;em&gt;Lokad.Shared.dll&lt;/em&gt;, as a really lightweight library, might be used in various projects. Some of these projects might not have "no nulls returned and expected" policy. So it is logical to protect shared methods from the nulls explicitly. in order to avoid the unpredictable behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;How do I use Maybe{T} if method can fail because of the multiple reasons and I want to know them&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Maybe{T}&lt;/em&gt; on its own is not designed to handle such situations. These are the primary logically-complete solutions for this situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can return &lt;em&gt;Maybe{T}&lt;/em&gt; while printing multiple failure details to the &lt;em&gt;IScope&lt;/em&gt; passed as an argument. That's how &lt;a href="http://abdullin.com/journal/2008/11/23/net-application-block-for-validation-and-business-rules.html"&gt;Lokad Rules&lt;/a&gt; are working. It also works well in long-running complex (especially asynchronous) operations that require logging and detailed failure control.&lt;/li&gt;
&lt;li&gt;You can use &lt;em&gt;Result{TValue,TError}&lt;/em&gt; monad returning strongly-typed error result (i.e.: enumeration value) or it's generic counterpart Result{TValue} (if the strong-typing is not possible for some reason).&lt;/li&gt;
&lt;li&gt;You can always use good old exceptions, if the above options do not suite you for some reason and you are OK with try-cath and breaking the functional code flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;Does Maybe work with validation rules?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yes, &lt;em&gt;Maybe{T}&lt;/em&gt; works with &lt;a href="http://abdullin.com/journal/2008/11/23/net-application-block-for-validation-and-business-rules.html"&gt;Lokad validation and business rules&lt;/a&gt;. You can also use &lt;em&gt;MaybeIs&lt;/em&gt; helper class to compose strongly-typed rules on top of the &lt;em&gt;Maybe{T}&lt;/em&gt; monad. &lt;em&gt;MaybeIs&lt;/em&gt; has two static methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;MaybeIs.EmptyOr{T}(params Rule{T}[] rules)&lt;/em&gt; - composes validation rule that succeeds only if the &lt;em&gt;Maybe{T}&lt;/em&gt; is empty &lt;strong&gt;or&lt;/strong&gt; the underlying value passes additional rules.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;MaybeIs.ValidAnd{T}(params Rule{T}[] rules)&lt;/em&gt; - composes validation rule that succeeds if the &lt;em&gt;Maybe{T}&lt;/em&gt; is not empty &lt;strong&gt;and&lt;/strong&gt; the underlying value passes additional rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sample usage in composing more complex rule:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static void ModelIsValid(FeedbackModel model, IScope scope)
{
  scope.Validate(() =&amp;gt; model.Sender, 
    MaybeIs.EmptyOr&amp;lt;string&amp;gt;(StringIs.ValidEmail));

  scope.Validate(() =&amp;gt; model.Model, ModelIsValid);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;So essentially you are replacing "optional != null" with "optional.HasValue"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Not exactly. HasValue is rarely checked against directly. Take a look at the piece of authentication code below. There are two possibly failing functions in it, that return &lt;em&gt;Maybe{T}&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Maybe&amp;lt;AuthPrincipal&amp;gt; LoadPrincipal(string key)
{
  return ParseStringToAuthInfo(key)
    .Combine(u =&amp;gt; _service.BuildAccountSession(u))
    .Convert(sa =&amp;gt; new AuthPrincipal(sa));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Signatures are like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;static Maybe&amp;lt;AuthInfo&amp;gt; ParseStringToAuthInfo(string encodedString);
Maybe&amp;lt;AccountSession&amp;gt; BuildAccountSession(AuthInfo authInformation);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;HasValue&lt;/em&gt; and &lt;em&gt;Value&lt;/em&gt; aren't mentioned in this code. That's how it usually works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; &lt;em&gt;What about operator overloading:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static implicit operator T(Maybe&amp;lt;T&amp;gt; mayBe)
{
  return mayBe.Value; //or mayBe._value;
}

public static implicit operator bool(Maybe&amp;lt;T&amp;gt; mayBe)
{
  return mayBe.HasValue;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This kind of implicit conversion from Maybe directly to value/state is not advised for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It looses the intent of using &lt;em&gt;Maybe{T}&lt;/em&gt; to force explicit handling of nullable situations.&lt;/li&gt;
&lt;li&gt;Implicit conversion from Maybe to value is logically incorrect as it might return &lt;em&gt;default(T)&lt;/em&gt; value or result in exception (depending on implementation).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Basically such an implicit operation would feel somewhat similar to the old C++ joke from bash.org:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#define TRUE false
#define FALSE true
// and good luck with debugging))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Side note: Implicit conversion from value to &lt;em&gt;Maybe{T}&lt;/em&gt; or from error/value to &lt;em&gt;Result{TValue,TError}&lt;/em&gt;, as opposed to the case above, does not violate this logic. This is because we are not forcing collapse of possibility of multiple states into one known state (while have side effects if the state is not what we expect).&lt;/p&gt;

&lt;p&gt;This is why conversion from value to maybe is implicit, while the opposite has to be done either via the Value property or via the explicit conversion.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Let's wrap the things up.&lt;/p&gt;

&lt;p&gt;In this article we've talked about &lt;em&gt;Maybe{T}&lt;/em&gt; generic class that, as a simple monad concept, allows in .NET to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promote &lt;strong&gt;Good citizenship&lt;/strong&gt; in the code avoiding nulls and exceptions;&lt;/li&gt;
&lt;li&gt;write &lt;strong&gt;clean code with explicit behavior&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;use expressive LINQ-style syntax with &lt;strong&gt;chaining and pipeline operators&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;benefit from the &lt;strong&gt;simplified unit testing&lt;/strong&gt; syntax;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;initialize immutable classes efficiently in C# 4.0&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C# source files and compiled binaries featuring &lt;em&gt;Maybe&lt;/em&gt; monad and testing extensions could be downloaded from the &lt;a href="http://abdullin.com/shared-libraries/"&gt;Lokad Shared Libraries&lt;/a&gt; Open Source project.&lt;/p&gt;

&lt;p&gt;It is important to note, that the current design of &lt;em&gt;Maybe{T}&lt;/em&gt; and development practices around it are based on the ongoing R&amp;amp;D process and production usage cases. As such, they might gradually evolve and improve further (this being reflected in Lokad Shared Libraries). &lt;/p&gt;

&lt;p&gt;This article is also considered to be an essential part of &lt;a href="http://abdullin.com/xlim/"&gt;xLim 3 development body of knowledge&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are interested in more articles on Zen Development practices, you can stay tuned by &lt;a href="http://feeds.abdullin.com/RinatAbdullin"&gt;subscribing to this blog via RSS&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Next article I'm considering for these series is about &lt;em&gt;Result&lt;/em&gt; variations of the monads in C#, that allow handling more complex failure scenarios, than a simple Maybe (BTW, the previous Zen article was about &lt;a href="http://abdullin.com/journal/2009/7/31/zen-development-practices-method-level-ioc.html"&gt;Method-level IoC&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All comments, thoughts and any other feedback are welcome and appreciated.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=CLAGosCD_ok:wx_O3rvuwbg:nQ_hWtDbxek"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=nQ_hWtDbxek" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=CLAGosCD_ok:wx_O3rvuwbg:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=CLAGosCD_ok:wx_O3rvuwbg:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=CLAGosCD_ok:wx_O3rvuwbg:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=CLAGosCD_ok:wx_O3rvuwbg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=CLAGosCD_ok:wx_O3rvuwbg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.abdullin.com/~ff/RinatAbdullin?a=CLAGosCD_ok:wx_O3rvuwbg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RinatAbdullin?i=CLAGosCD_ok:wx_O3rvuwbg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RinatAbdullin/~4/CLAGosCD_ok" height="1" width="1"/&gt;</description><wfw:commentRss>http://abdullin.com/journal/rss-comments-entry-5404980.xml</wfw:commentRss><feedburner:origLink>http://abdullin.com/journal/2009/10/6/zen-development-practices-c-maybe-monad.html</feedburner:origLink></item></channel></rss>
