<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;A0EFQ34yeSp7ImA9WhRbF0Q.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982</id><updated>2012-02-09T16:00:12.091+01:00</updated><category term="Windows Mobile" /><category term="Visual Studio" /><category term="Conferences" /><category term="Linq" /><category term="REST" /><category term=".Net" /><category term="Tools" /><category term="Misc" /><category term="Moss" /><category term="Gadgets" /><category term="Commerce Server" /><category term="Design" /><category term="Devteach" /><category term="NMoneys" /><category term="Android" /><category term="Unit Testing" /><category term="NDC" /><category term="Testing.Commons" /><category term="Testing.Commons.NUnit" /><category term="Open Source" /><category term="Speaking" /><title>Yet another layer of indirection</title><subtitle type="html">On technology and geekiness...
Mostly .Net development</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://dgondotnet.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>135</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/YetAnotherLayerOfIndirection" /><feedburner:info uri="yetanotherlayerofindirection" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0EFQ387eyp7ImA9WhRbF0Q.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-7133811674995095090</id><published>2012-02-09T16:00:00.000+01:00</published><updated>2012-02-09T16:00:12.103+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-09T16:00:12.103+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="REST" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>REST Raiding. WebApi</title><content type="html">&lt;p&gt;&lt;a href="'"&gt;WebApi&lt;/a&gt; looked as one of the strongest contenders at first, just by its lineage (MSFT is his champion). But when I saw its pre-beta status I had second thoughts. And third thoughts remembering all the horror stories I have had with its father: &lt;a href="http://msdn.microsoft.com/en-us/library/ms731082.aspx"&gt;Windows Communication Foundation&lt;/a&gt;. Since I spent less time than I wanted evaluating OpenRasta I gave WebApi a spin. And here are my thoughts.&lt;/p&gt;  &lt;h2&gt;Get It!&lt;/h2&gt;  &lt;p&gt;Getting WebApi up and running is simple enough: install the &lt;a href="http://nuget.org/packages/WebApi"&gt;WebApi&lt;/a&gt; package and you are good to go. There are a number of other packages that add some interesting features, but I only went for the simple, barebones, server side of things.&lt;/p&gt;  &lt;h2&gt;Documentation&lt;/h2&gt;  &lt;p&gt;The &lt;a href="http://wcf.codeplex.com/wikipage?title=Getting%20started:%20Building%20a%20simple%20web%20api"&gt;walkthrough&lt;/a&gt; is pretty comprehensive but the site does not have a whole lot of “official” documentation. But the package comes with a pair of .chm files that are really handy.&lt;/p&gt;  &lt;p&gt;And one cannot complain about the number of people writing about the product in their blogs. The information might be outdated, but it should give an idea of the activity of the community around the product, which is pretty nice, in my opinion.&lt;/p&gt;  &lt;h2&gt;The Services&lt;/h2&gt;  &lt;p&gt;Creating services (or APIs, as they are called in WebApi jargon) is a two step thing out-of-the-box.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Create a class decorated with the &lt;code&gt;ServiceContract&lt;/code&gt; attribute that contains one or more related methods (and related means URL-related) and implement your logic:       &lt;pre class="c-sharp" name="code"&gt;[WebGet(UriTemplate = &amp;quot;&amp;quot;)]
public Resources.Catalog[] GetCatalogs()
{
    // fancy population of 'resource'
    return resource;
}&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;And register the route corresponding to the resource you are serving when the application starts: 
    &lt;pre class="c-sharp" name="code"&gt;RouteTable.Routes.Add(
        new ServiceRoute(
            &amp;quot;catalogs&amp;quot;,
            new HttpServiceHostFactory(),
            typeof(CatalogsApi)));&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some content negotiation is included out of the box by adding an &lt;em&gt;Accept&lt;/em&gt; request header, being the default XML and JSON is also included. A nice touch is that it supports qualified values (see the &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1"&gt;spec&lt;/a&gt;), meaning that will return the supported type with the higher relative quality factor or default to XML. Another nice touch is the fact that the response includes the codification charset of the data, which helps with those “weird” characters that we all love (ñ, æ, å,…)&lt;/p&gt;

&lt;p&gt;One of the things that impressed me the most was how the whole URL placeholder and extra request information is handled. If one wants to have another API hanging from an already defined base route (in this case, &lt;em&gt;/catalogs&lt;/em&gt;) another method in the api class is created and decorated with the &lt;code&gt;WebGet&lt;/code&gt; attribute, setting the &lt;code&gt;UriTemplate&lt;/code&gt; property to a string that will contain the placeholder information for that route, including any query string information that we may want to get and that information will be set in the parameters defined for the method. Pretty nifty.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;[WebGet(UriTemplate = &amp;quot;{catalogName}?lang={lang}&amp;quot;)]
public Resources.Catalog Get(string catalogName, string lang)
{
    // even more fancy stuff
    return resource;
}&lt;/pre&gt;

&lt;p&gt;And the icing of the cake for those who need it? Easy &lt;a href="http://www.odata.org/"&gt;OData&lt;/a&gt; support. Apparently it does not get on well with REST according to some, but it is a pretty popular format of delivering information.&lt;/p&gt;

&lt;h2&gt;Opinion&lt;/h2&gt;

&lt;p&gt;I was pleasantly surprised by how smooth WebApi looks like. That only mean they did a good job to come up with a nice to work with API on top of the configuration hell that WCF is. And that is a compliment, by the way. 
  &lt;br /&gt;It does what it does in a nice manner but I do not have an opinion about extensibility points and customizations as I did not push it. But I know from my light reading about the subject that it supports the concept of resource factory, allowing to use your IOC container of choice to inject the dependencies your service might have in an easy manner.&lt;/p&gt;

&lt;p&gt;Probably one the nicest things one can say is that it gets the job done without getting in one’s way, with a simple api, meaningful defaults and adherence to the spec. Do not know about relative performance, compared to some of the other contenders, though.&lt;/p&gt;

&lt;p&gt;I have very few bad things (if any) to say. The only &lt;em&gt;but&lt;/em&gt; is the two step creation of services (service plus the route), but I am confident there might be an extension to have it in one single step.&lt;/p&gt;

&lt;p&gt;Would I use WebApi? I cannot see why not.
  &lt;br /&gt;Was it the one I chose? No, it was not. Only because I tried it by chance and expected worse (due to its WCF heritage) it did not get higher in my list of preferences.

  &lt;br /&gt;Would I recommend its use? Yeah, give it a go. It may suit your needs.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-7133811674995095090?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/6XmTfwNBiFQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/7133811674995095090/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=7133811674995095090" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/7133811674995095090?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/7133811674995095090?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/6XmTfwNBiFQ/rest-raiding-webapi.html" title="REST Raiding. WebApi" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2012/02/rest-raiding-webapi.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cHQ3c_eyp7ImA9WhRUGE8.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-2214014983510966257</id><published>2012-01-29T09:13:00.001+01:00</published><updated>2012-01-29T09:17:12.943+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-29T09:17:12.943+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="REST" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>REST Raiding. OpenRasta</title><content type="html">&lt;p&gt;I had very high hopes for this one. I was really, really, ready to like it. I had the preconceived idea that this was going to be the one to be chosen. But…&lt;/p&gt;  &lt;h2&gt;Get It!&lt;/h2&gt;  &lt;p&gt;I really do not want to be mean or sound (too) rant-y. But I need to tell the whole story.&lt;/p&gt;  &lt;p&gt;Let’s face it, looks matter. Compare these two sites. If they were a web-shop, from which you would buy from? If they were a web framework, which one projects quality and care? I do not intend to be cheap, but… seriously?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://lh6.ggpht.com/-rDjHLFdndaE/TyT_hqPfMnI/AAAAAAAAAwE/NDDJ2NzQqLE/s1600-h/OpenRasta_Home_22.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="OpenRasta_Home_2" border="0" alt="OpenRasta_Home_2" src="http://lh4.ggpht.com/-0AMd6JgyW6k/TyT_iU7qsNI/AAAAAAAAAwI/v3rPC0nIFhg/OpenRasta_Home_2_thumb.png?imgmax=800" width="244" height="176" /&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/-E0XR3hpKfEY/TyT_iwn6QyI/AAAAAAAAAwQ/KK3lxEAv-N0/s1600-h/nancy_home2.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="nancy_home" border="0" alt="nancy_home" src="http://lh3.ggpht.com/-huK3E9FT8k4/TyT_jxL3hqI/AAAAAAAAAwY/h_MbXp62r-w/nancy_home_thumb.png?imgmax=800" width="244" height="232" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Ok, dodgy as it looks I bit the bullet and tried my luck finding a NuGet package. None. Nil. Zero. If you want a package, go install &lt;a href="http://www.openwrap.org/"&gt;OpenWrap&lt;/a&gt; and let it take over the soul and guts from your &lt;code&gt;.csproj&lt;/code&gt;. Not an option. Not for me, at least.     &lt;br /&gt;Ok, let’s find a binary download… Hitting the &lt;a href="https://github.com/openrasta/openrasta-stable/wiki/"&gt;documentation page&lt;/a&gt;… Looks promising. Darn! It points to an apparently &lt;a href="https://github.com/openrasta/openrasta-stable"&gt;outdated&lt;/a&gt; source code repository. Well, it links to a &lt;a href="https://github.com/openrasta/openrasta-stable/wiki/Packages"&gt;list&lt;/a&gt; of the various repositories (and no links to them?). Fine, I know how the Web works &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-sadsmile" alt="Sad smile" src="http://lh6.ggpht.com/-_7Iy6X-P4U8/TyT_kkenihI/AAAAAAAAAwg/gGGG8WwyBLo/wlEmoticon-sadsmile2.png?imgmax=800" /&gt; and how to navigate GitHub, so stop complaining already! What? No binaries? I already broke &lt;a href="http://lh5.ggpht.com/-I0T8LoqMtR4/TtZSBDLyu_I/AAAAAAAAAvk/XznphgUipMQ/s1600-h/image7.png"&gt;my rules&lt;/a&gt; with this project, that is how ready to like it I was…    &lt;br /&gt;Cloning a couple of repositories and for once in my life I will read the doc first, as I know these guys can get funky with the build process. Oh dear, the &lt;a href="https://github.com/openrasta/openrasta-stable/wiki/Downloading-and-Compiling-OpenRasta"&gt;instructions&lt;/a&gt; are outdated, there is no &lt;code&gt;make.bat&lt;/code&gt; anywhere the new source tree. Some investigation tells me it is just a shortcut for &lt;code&gt;msbuild&lt;/code&gt;. Fire it and… what is the result? An assembly with version 0.0.0.0. WTF?&lt;/p&gt;  &lt;h2&gt;Documentation&lt;/h2&gt;  &lt;p&gt;Being the most mature of the contenders I was expecting documentation to be more comprehensive and a wealth blog posts about how to get started. And I was not disappointed. I have little to none complaints in the documentation are.&lt;/p&gt;  &lt;h2&gt;The Services&lt;/h2&gt;  &lt;p&gt;Or &lt;em&gt;handlers&lt;/em&gt; as they are called in Open Rasta are the classes that give access to our resources (the snapshots of information). They are truly POCOs, not needing any parent class, interface or attribute. Just name the methods wisely (correlating to HTTP verbs) or drive the default behavior with the configuration:&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public class CatalogsHandler
{
    public CatalogCollection Get()
    {
        var resource = // get the resource 

        return resource;
    }
}&lt;/pre&gt;

&lt;p&gt;Speaking of which, one of the things that caught my attention when I first saw the framework was how much it relied in configuration and how “beautiful” was the API to handle it. I still think the effort they put in having an elegant configuration API was worthy, but having seen other frameworks in which configuration is superfluous it now seems almost like a waste. An exercise of waste, nonetheless.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class Configuration : IConfigurationSource
{
    public void Configure()
    {
        using (OpenRastaConfiguration.Manual)
        {
            ResourceSpace.Has
                .ResourcesOfType&amp;lt;CatalogCollection&amp;gt;()
                    .AtUri(&amp;quot;/catalogs&amp;quot;)
                    .HandledBy&amp;lt;CatalogsHandler&amp;gt;()
                    .AsXmlDataContract().And.AsJsonDataContract();
        }
    }
}&lt;/pre&gt;

&lt;p&gt;And precisely with configuration came the last sin I committed with the framework. I got overconfident with the usage of the API and I forgot to include the &lt;code&gt;using (OpenRastaConfiguration.Manual)&lt;/code&gt; statement. It may not look as much, but was capital in me giving up. Because it makes nothing work with a dreadful &lt;code&gt;ArgumentNullException&lt;/code&gt;. Swallowing my pride again I dived in the code but could not make any sense of such a complex framework in such short period of time. So I reverted to community support, which turns out to be just &lt;a href="http://stackoverflow.com/questions/8816005/argumentnullexception-when-initializing-site"&gt;StackOverflow&lt;/a&gt; (having read that the Google Groups is dead). I cannot complain, as I got my question answered and my thanks were given in less than a week. 

  &lt;br /&gt;By that time it was too late. I had seen enough, given up and tagged the framework as not viable for this project, thanks for asking.&lt;/p&gt;

&lt;h2&gt;Opinion&lt;/h2&gt;

&lt;p&gt;As one can imagine, I cannot be too happy about my time with the framework. And definitely was not the chosen one.&lt;/p&gt;

&lt;p&gt;I tried very hard to like it. And being disappointed is partly my fault (a combination of high expectations and carelessness in reading the walkthrough).
  &lt;br /&gt;I still believe is one the nicest frameworks to work with (once you get it up and running) with tons of places to hook up your own behavior and probably the most HTTP-friendly of them all (for example, requesting a resource in a format that is not configured, returns a proper &lt;code&gt;406 Not Acceptable&lt;/code&gt; code).

  &lt;br /&gt;Their support for dependency management is kind of nice, but a bit &lt;a href="https://github.com/openrasta/openrasta/wiki/Dependency-Injection"&gt;verbose&lt;/a&gt; for my liking, but one can use of of the multiple hooks to have the IOC container of the month working with the framework and using all the coolness of the container for dependency registration.&lt;/p&gt;

&lt;p&gt;Final sayings? It &lt;u&gt;will be&lt;/u&gt; a killer framework once it settles down from the code/project/repository migrations turmoil, the new version is released and contributors fix the build and the doc. Until that happens, I won’t be getting anywhere close for production purposes.&lt;/p&gt;

&lt;p&gt;And for pity’s sake! Include some sort of binary distribution for those that have not drunk from the OpenWrap chalice! I am not even suggesting a lame NuGet package. That would be too low, wouldn’t it? &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://lh3.ggpht.com/-zdKbRCDJuQI/TyT_lLcCKsI/AAAAAAAAAwk/48jhnhvKWRg/wlEmoticon-winkingsmile%25255B2%25255D.png?imgmax=800" /&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-2214014983510966257?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/dsSrXqXiZ1Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/2214014983510966257/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=2214014983510966257" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2214014983510966257?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2214014983510966257?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/dsSrXqXiZ1Y/rest-raiding-openrasta.html" title="REST Raiding. OpenRasta" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-0AMd6JgyW6k/TyT_iU7qsNI/AAAAAAAAAwI/v3rPC0nIFhg/s72-c/OpenRasta_Home_2_thumb.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2012/01/rest-raiding-openrasta.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUHQnc_cCp7ImA9WhRUEEU.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-3941426297385386078</id><published>2012-01-20T20:37:00.001+01:00</published><updated>2012-01-20T20:37:13.948+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-20T20:37:13.948+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="REST" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>REST Raiding. Nancy</title><content type="html">&lt;p&gt;The first contender has a lovely woman’s name: &lt;a href="http://nancyfx.org/"&gt;Nancy&lt;/a&gt;.&lt;/p&gt;  &lt;h2&gt;Get it!&lt;/h2&gt;  &lt;p&gt;Getting Nancy up and running is as straightforward as it can be: create a Visual Studio Web Application project and install the &lt;a href="https://nuget.org/packages/Nancy.Hosting.Aspnet"&gt;nuget package&lt;/a&gt;. That is it.&lt;/p&gt;  &lt;h2&gt;Documentation&lt;/h2&gt;  &lt;p&gt;If the &lt;a href="http://nancyfx.org/"&gt;homepage&lt;/a&gt; was both elegant and useful, the &lt;a href="https://github.com/NancyFx/Nancy/wiki/Documentation"&gt;documentation page&lt;/a&gt; is mouth watering. Simple and straight to the point. I was pleasantly surprised by the quality and the general vibe of the project.     &lt;br /&gt;This one is for those that claim that all OSS projects are a waste of time and lack documentation. Watch and cry.&lt;/p&gt;  &lt;h2&gt;The services&lt;/h2&gt;  &lt;p&gt;The service that returns all snapshots will be hosted in the url &lt;em&gt;/catalogs&lt;/em&gt; and the one that returns the single detail in &lt;em&gt;/catalogs/{catalog_name}&lt;/em&gt;. Resources are accessed in Nancy via modules (inheritors of &lt;code&gt;NancyModule&lt;/code&gt;). Modules specify the URL and the HTTP method using a very neat indexer-function syntax. Since both services are related by the base URL, Nancy allows them to be grouped in the same module. No more configuration. As DRY and simple as it gets.&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public class CatalogsModule : NancyModule
{
    public CatalogsModule() : base(&amp;quot;/catalogs&amp;quot;)
    {
        Get[&amp;quot;/&amp;quot;] = parameters =&amp;gt;
        {
            var model = new[]
            {
                // define the model
            };

            return Response.BarebonesContentNegotiation(Request, model);
        };

        Get[&amp;quot;/{catalogName}&amp;quot;] = parameters =&amp;gt;
        {
            string name = parameters.catalogName;
            CultureInfo language = Request.GetLanguage();
            var model = new Catalog
            {
                // model
            };
            return Response.BarebonesContentNegotiation(Request, model);
        };
    }
}&lt;/pre&gt;

&lt;p&gt;The /catalogs service is as simple as it gets as no argument is needed and uses no globalization. The only thing to point out is the &lt;code&gt;Response.BarebonesContentNegotiation()&lt;/code&gt; method. Since Nancy does not implement (yet) any content negotiation or dynamic response formatting I developed a coarse method to find out whether to return XML or default to JSON, using the Nancy extensions &lt;code&gt;.AsXml()&lt;/code&gt; and &lt;code&gt;.AsJson()&lt;/code&gt;. It is clumsy and incorrect to an extreme, but since it is a POC I am not that embarrassed &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://lh4.ggpht.com/-UNLQtqYGnxw/TxnCaNLigII/AAAAAAAAAv8/7Ri1UPw_S0o/wlEmoticon-winkingsmile2.png?imgmax=800" /&gt;&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public static Response BarebonesContentNegotiation&amp;lt;TModel&amp;gt;(this IResponseFormatter response, Request request, TModel model)
{
    bool acceptsXml = request.Headers.Accept
        .Any(a =&amp;gt; a.IndexOf(&amp;quot;xml&amp;quot;, StringComparison.OrdinalIgnoreCase) &amp;gt;= 0);

    return acceptsXml ? response.AsXml(model) : response.AsJson(model);
}&lt;/pre&gt;

&lt;p&gt;For the /catalogs/{catalog_name} service there are some more interesting points. The first one is how route parameters are passed: that is what the function argument &lt;em&gt;parameters&lt;/em&gt; is for. It cleverly uses dynamics to give access to the parameters by name. The other thing to point out is how the language is retrieved by extending the&amp;#160; Nancy type &lt;code&gt;Request&lt;/code&gt;. It should be easy enough since it exposes the &lt;code&gt;Headers.AcceptLanguage&lt;/code&gt; property. Unfortunately, the language string is not parsed and weighed as it should be (&lt;a href="#nancy-update"&gt;yet&lt;/a&gt;) and the whole language string is passed in the first element of the collection. Well, since I am hosting Nancy in ASP.NET, I have all the “power” of the ASP.NET pipeline, and the weighed collection of languages can be accessed from the current &lt;code&gt;HttpRequest.UserLanguages&lt;/code&gt; property (as long as testability is not a big concern).&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public static CultureInfo GetLanguage(this Request request)
{
    HttpRequest http = HttpContext.Current.Request;

    return request.Query.lang.HasValue ?
        CultureInfo.GetCultureInfo(request.Query.lang.Value) :
        fromRequestOrInvariant(http);
}
private static CultureInfo fromRequestOrInvariant(HttpRequest request)
{
    return (request.UserLanguages ?? Enumerable.Empty&amp;lt;string&amp;gt;())
        .Select(CultureInfo.GetCultureInfo)
        .FirstOrDefault(ci =&amp;gt; !ci.IsNeutralCulture) ?? CultureInfo.InvariantCulture;
}&lt;/pre&gt;

&lt;p&gt;In the above snippet one can see the clever use of dynamics to access query-string values (via a dynamic property with the key of the element that gives access to an object that let know whether the key has a value and which value is that).&lt;/p&gt;

&lt;h2&gt;Opinion&lt;/h2&gt;

&lt;p&gt;I have to admit I did not expect Nancy to be in such a good shape. The site looks gorgeous, documentation is available, community is growing and getting it up and running was a pleasure.&lt;/p&gt;

&lt;p&gt;And what is more important: what they preach about low ceremony and simplicity cannot be more true. Most of the decisions make sense and look clean and approachable.&lt;/p&gt;

&lt;p&gt;Its simplicity and youth make it lack some features I needed out of the box (such as dynamic response formatting) but I am certain that they will come.&lt;/p&gt;

&lt;p&gt;Definitely a strong candidate to be taken very seriously.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a name="nancy-update"&gt;&lt;/a&gt;UPDATE: I mentioned that how the Accept-Language header was not parsed correctly. Well, I created a new &lt;a href="https://github.com/NancyFx/Nancy/issues/474"&gt;issue&lt;/a&gt; in their &lt;a href="https://github.com/NancyFx/Nancy"&gt;GitHub repository&lt;/a&gt;. Literally, minutes passed until I received feedback and hours until a pull request was issued with the fix. That, dear readers, is just another testimony of how awesome OSS can become.&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-3941426297385386078?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/le_BS3rqokM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/3941426297385386078/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=3941426297385386078" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3941426297385386078?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3941426297385386078?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/le_BS3rqokM/rest-raiding-nancy.html" title="REST Raiding. Nancy" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-UNLQtqYGnxw/TxnCaNLigII/AAAAAAAAAv8/7Ri1UPw_S0o/s72-c/wlEmoticon-winkingsmile2.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2012/01/rest-raiding-nancy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0AMQnc-fCp7ImA9WhRVE0w.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-3675900217220155684</id><published>2012-01-11T20:56:00.001+01:00</published><updated>2012-01-11T20:56:23.954+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-11T20:56:23.954+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="REST" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>RESTing in the Laurels</title><content type="html">&lt;p&gt;Late Happy New Year to everyone!&lt;/p&gt;  &lt;p&gt;For the first of 2012 let’s start with a short series of post about my adventures in finding a suitable web framework that makes likeable building REST services.&lt;/p&gt;  &lt;h2&gt;Corralling the Problem&lt;/h2&gt;  &lt;p&gt;Very rarely I write about concrete pieces of work I perform for my customers. This time I will break the rule, since this instance is about a proof of concept and no details are going to be given away.   &lt;br /&gt;Hopefully, someone that faces the same problem I faced when choosing, can find my journey interesting.&lt;/p&gt;  &lt;p&gt;The proof of concept that scopes my findings is about creating simple URL-accessible read-only services. The information returned can be localized and be returned in various formats (XML and JSON), chosen by the consumer. Of the services to be built, the most “complex” is returning some sort of catalog information, having two endpoints: one that returns a snapshot of all of them and another endpoint that returns an extended version of a single one.&lt;/p&gt;  &lt;h2&gt;Non-Functional&lt;/h2&gt;  &lt;p&gt;As the reader can see, the functional requirements aforementioned are really simple. The non-functional requirements will, as well, be concrete.&lt;/p&gt;  &lt;p&gt;For one, services need to be &lt;strong&gt;easy to develop&lt;/strong&gt;. That rules out any framework that require extensive configuration and/or a great deal of ceremony (yeah, WCF I am looking at you!).&lt;/p&gt;  &lt;p&gt;They also need to be &lt;strong&gt;HTTP-friendly&lt;/strong&gt;. HTTP is a simple protocol but often misunderstood and underestimated. It covers all my requirements and a great deal more. For example, content negotiation is possible by expressing a rich set of formats accepted by the client in the headers, and extra formats can be defined to cover scenarios such as versioning. Likewise, localization is achieved with the same technique, including a weighted list of languages the client request the information in. Standard return codes provide a standard vocabulary of possible outcome and caching information can be specified.&lt;/p&gt;  &lt;p&gt;Unfortunately, as rich as HTTP is, there are a wealth of bad clients to the protocol and shortcuts to be taken. Of those, we contemplate an easy way to &lt;strong&gt;override&lt;/strong&gt; both the language and format of the response by the means of providing query-string arguments.&lt;/p&gt;  &lt;p&gt;Nice-to-have extras that won’t probably be needed in the firsts versions are:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;performance&lt;/strong&gt;: it should&amp;#160; &lt;u&gt;lightweight&lt;/u&gt; enough to not become a problem when multiple clients perform requests. I want my code to be the scalability problem if they ever exists&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;extensibility&lt;/strong&gt;: being able to easily get in the middle of the request &lt;u&gt;pipeline&lt;/u&gt; at several stages in order to clean up the implementation of the service itself&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;coolness&lt;/strong&gt;: it should be &lt;u&gt;pleasant&lt;/u&gt; to work with and have a &lt;u&gt;strong community&lt;/u&gt; that can provide knowledge when newer features that need advanced usages come. OSS is a plus, but not required. Oddly enough all the frameworks analyzed give access to their source code.&lt;/p&gt;  &lt;h2&gt;The Contenders&lt;/h2&gt;  &lt;p&gt;My time is limited for the task and there are lots of such frameworks that can be used for my problem. So I framed the products to evaluate to:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Nancy&lt;/li&gt;    &lt;li&gt;OpenRasta&lt;/li&gt;    &lt;li&gt;ServiceStack&lt;/li&gt;    &lt;li&gt;WebApi&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-3675900217220155684?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/2vBhqiaP2g0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/3675900217220155684/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=3675900217220155684" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3675900217220155684?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3675900217220155684?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/2vBhqiaP2g0/resting-in-laurels.html" title="RESTing in the Laurels" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2012/01/resting-in-laurels.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUDQ349fCp7ImA9WhRQF0w.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-4085473250131891789</id><published>2011-12-12T19:43:00.001+01:00</published><updated>2011-12-12T19:57:52.064+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-12T19:57:52.064+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons.NUnit" /><title>Contract Verification in NUnit. Comparisons</title><content type="html">&lt;p&gt;Before anyone gets confused I am using a very broad definition of &lt;em&gt;contract&lt;/em&gt; that it is not related at all with &lt;a href="http://msdn.microsoft.com/en-us/devlabs/dd491992"&gt;Code Contracts&lt;/a&gt; or Design by Contract.     &lt;br /&gt;What I mean by &lt;em&gt;contract&lt;/em&gt; is the correct implementation of an interface that has become idiomatic. And before you ask, an interface is &lt;u&gt;not&lt;/u&gt; a contract. I consider it part of the definition of a contract, but it lacks on the definition of the obligations of client and supplier and most importantly, the verification of such contract. And also before you ask, no, Code Contracts do not provide all the means to express complex obligations and outcomes when conditions are met.&lt;/p&gt;  &lt;p&gt;One of such contracts that are pervasive in the .NET Framework is &lt;a href="http://msdn.microsoft.com/en-us/library/4d7sx9hd.aspx"&gt;&lt;code&gt;IComparable&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt;. This useful interface define how two types can be compared for the purpose of sorting. As a matter of fact, it is so useful I have already written about it in the past in the &lt;a href="http://dgondotnet.blogspot.com/search?q=comparison"&gt;Equality and Comparison series&lt;/a&gt;. One missing point in such series is how to check that we have fulfilled all the un-checked obligations (they are written, although scattered, in the interface and operators documentation).&lt;/p&gt;  &lt;h2&gt;Greener Pastures&lt;/h2&gt;  &lt;p&gt;Other testing frameworks, such as &lt;a href="http://www.mbunit.com/"&gt;MbUnit&lt;/a&gt;, have had a way to verify those obligations for some time now, in the shape of &lt;a href="http://www.gallio.org/wiki/doku.php?id=mbunit:contract_verifiers"&gt;contract verifiers&lt;/a&gt;. Their implementation of the idea is such that complete test fixtures are created for the verification purpose, making my endeavor of porting such functionality to the &lt;a href="http://nunit.com/"&gt;NUnit&lt;/a&gt; I use and almost love a pretty difficult one, as that would make me dig deeper than I feel compelled to in the inner working of its provider model. Besides, MbUnit’s syntax is not something I am very fond of, so a re-write was bound to happen.&lt;/p&gt;  &lt;h2&gt;Framing the Problem&lt;/h2&gt;  &lt;p&gt;The problem with comparison if not very complex, but it has to be done right. &lt;/p&gt;  &lt;p&gt;In its simplest form, can be defined that types should return a negative value when compared against a bigger value, a positive value when compared against a smaller value and zero when compared against an equal value. Oh, and one has to keep in mind those pesky nulls. Oh, and one has a handful operators that could ne checked too. Oh, and one can compare types against other types, not just itself. Oh, and what we have to check is the same regardless of the type that implements the comparison we are testing.&lt;/p&gt;  &lt;p&gt;It is easy to see that the number of combinations and the fact they are repetitive make the subject a perfect candidate to receive a helping hand.&lt;/p&gt;  &lt;h2&gt;The helping hand&lt;/h2&gt;  &lt;p&gt;Testing? Asserting for correctness? Looks like a task for &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-NUnit"&gt;Testing.Commons.NUnit&lt;/a&gt;. And indeed it is.&lt;/p&gt;  &lt;p&gt;To start with, the problem can be presented like an assertion over several values and can be split into several parts: the implementation of &lt;code&gt;IComparable&amp;lt;T&amp;gt;&lt;/code&gt;, being &lt;code&gt;T&lt;/code&gt; the same type of the instance being asserted; the implementation of &lt;code&gt;IComparable&amp;lt;T&amp;gt;&lt;/code&gt;, where &lt;code&gt;T&lt;/code&gt; is not the same type as the instance being asserted; the implementation of comparison operators (&lt;code&gt;&amp;lt;, &amp;gt;, &amp;gt;=, &amp;lt;=&lt;/code&gt;) against the same type as the instance being asserted; and the implementation of comparison operators against other types.&lt;/p&gt;  &lt;p&gt;For the first two cases (the implementation of &lt;code&gt;IComparable&amp;lt;T&amp;gt;&lt;/code&gt;), the custom constraint &lt;code&gt;ImplementsComparableConstraint&lt;/code&gt; is used, maybe through the &lt;code&gt;Must.Satisfy.ComparableSpecificationAgainst()&lt;/code&gt; extension. Its usage is really simple:&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;[Test]
public void ComparableToSelf()
{
    ComparableSubject target = //...
    ComparableSubject lessThanTarget = //... 
    ComparableSubject greaterThanTarget = //... 

    Assert.That(target, new ImplementsComparableConstraint&amp;lt;ComparableSubject&amp;gt;(lessThanTarget, lessThanTarget));
    Assert.That(target, Must.Satisfy.ComparableSpecificationAgainst(lessThanTarget, lessThanTarget));
}&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;[Test]
public void ComparableToOther()
{
    string eq = &amp;quot;eq&amp;quot;, lt = &amp;quot;lt&amp;quot;, gt = &amp;quot;gt&amp;quot;;
    ComparableSubject target = //...

    Assert.That(target, Must.Satisfy.ComparableSpecificationAgainst(lt, gt, eq));
}&lt;/pre&gt;

&lt;p&gt;Provide either two or three instances of the type it is being compared against, one that is greater and one that is smaller and maybe one that is equal (when comparison to itself is not possible) and the combinations with null and not null values will be checked, providing a nice informative message when the type does not honor the contract.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;A type that implements comparison operators to &amp;lt;ComparisonAgainstSelf&amp;gt;.
&amp;lt;target&amp;gt; must be &amp;lt;= (less than or equal to) &amp;lt;target&amp;gt;
  Expected: True
  But was:  False&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;A type that implements comparison operators to &amp;lt;String&amp;gt;.
&amp;lt;target&amp;gt; must be &amp;lt; (less than) &amp;quot;gt&amp;quot;
  Expected: True
  But was:  False&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;A type that implements IComparable&amp;lt;ComparableSubject&amp;gt; contract.
&amp;lt;target&amp;gt; must be greater than &amp;lt;lt&amp;gt;
  Expected: greater than 0
  But was:  -1&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;A type that implements IComparable&amp;lt;String&amp;gt; contract.
&amp;lt;target&amp;gt; must be less than null
  Expected: less than 0
  But was:  2&lt;/pre&gt;

&lt;p&gt;For the next two cases (the implementation of comparison operators) the custom constraint &lt;code&gt;ImplementsComparisonConstraint&lt;/code&gt; is used, maybe using the &lt;code&gt;Must.Satisfy.ComparisonSpecificationAgainst()&lt;/code&gt;. Again, the usage is really simple:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;[Test]
public void ComparableToSelf()
{
    ComparisonAgainstSelf target = //...
    ComparisonAgainstSelf lt =  //...
    ComparisonAgainstSelf gt =  //...

    Assert.That(target, Must.Satisfy.ComparisonSpecificationAgainst(lt, gt));
}&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;[Test]
public void CanBeCreatedWithExtension_ComparableToOther()
{
    ComparisonAgainstReference target = //...
    string eq = &amp;quot;eq&amp;quot;, lt = &amp;quot;lt&amp;quot;, gt = &amp;quot;gt&amp;quot;;

    Assert.That(target, Must.Satisfy.ComparisonSpecificationAgainst&amp;lt;ComparisonAgainstReference, string&amp;gt;(lt, gt, eq));
}&lt;/pre&gt;

&lt;p&gt;Again, just provide some instances to compare against and the right combinations of null and not null values would be checked. Error messages are likewise descriptive:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;A type that implements comparison operators to &amp;lt;String&amp;gt;.
&amp;lt;target&amp;gt; must be &amp;lt; (less than) &amp;quot;gt&amp;quot;
  Expected: True
  But was:  False&lt;/pre&gt;

&lt;h2&gt;Peek inside&lt;/h2&gt;

&lt;p&gt;The implementation itself is not terribly sophisticated once the problem is laid out. But there are a few important tricks that made the code so much easier to write (and much DRY-er).&lt;/p&gt;

&lt;p&gt;One of the&amp;#160; most important internals is the concept of &lt;code&gt;&lt;a href="https://www.assembla.com/code/testing-commons/git/nodes/src/Testing.Commons.NUnit/Constraints/ChainedConstraints.cs"&gt;ChainedContraints&lt;/a&gt;&lt;/code&gt;. This is just a simple chain-of-responsibility collection of constraints, that will be lazily executed until one of them fail, in which case, it will be surfaced in order for part of the error message to be written by that failing constraint.&lt;/p&gt;

&lt;p&gt;Another interesting trick has to do with the fact that operators are static constructs and, therefore, there is no way to represent them as an interface or a generic class. What one can do is, instead, use code generation to build a delegate that represents the operation. I used (and changed a bit) a working implementation from &lt;a href="http://www.yoda.arachsys.com/csharp/miscutil/"&gt;MiscUtil&lt;/a&gt; after remembering an article about &lt;a href="http://www.yoda.arachsys.com/csharp/genericoperators.html"&gt;generic numeric operations&lt;/a&gt;. Basically it uses expression trees to generate the delegates the execute the operators. Clever thing indeed.&lt;/p&gt;

&lt;h2&gt;What else?&lt;/h2&gt;

&lt;p&gt;So far, nothing else. Go get, use and give feedback &lt;a href="http://nuget.org/packages/Testing.Commons.NUnit"&gt;Testing.Commons.NUnit&lt;/a&gt; from its Nuget home. And stay connected, if you will, for more of these contract checkers/verifiers.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-4085473250131891789?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/px1zMNn4duE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/4085473250131891789/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=4085473250131891789" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/4085473250131891789?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/4085473250131891789?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/px1zMNn4duE/contract-verification-in-nunit.html" title="Contract Verification in NUnit. Comparisons" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/12/contract-verification-in-nunit.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4EQXk8eSp7ImA9WhRRF0g.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-5345094333418603467</id><published>2011-12-01T16:55:00.000+01:00</published><updated>2011-12-01T16:55:00.771+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-01T16:55:00.771+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><title>The Sixth OSSense</title><content type="html">&lt;p&gt;I think I heard &lt;a href="http://www.hanselman.com/blog/"&gt;Mr. Hanselman&lt;/a&gt; say once that a .NET Open Source project does not exist if was not available through &lt;a href="http://nuget.org/"&gt;Nuget&lt;/a&gt;. That was said very, very early in the “packaging game”, but hey, bluffs are so cheap to make!     &lt;br /&gt;I did not take it seriously, of course. My lack of vision is legendary as I genuinely believed that finding the OSS project page, downloading a zip and adding an assembly reference was not that painful.&lt;/p&gt;  &lt;h2&gt;Oh, The Pain&lt;/h2&gt;  &lt;p&gt;I was wrong. Well, it is not that painful. But there are two steps in the process that can go horribly wrong.    &lt;br /&gt;First: finding the project. Even with pages and search engines devoted to the noble task of finding Open source projects, it is not a simple task to get a useful project found.     &lt;br /&gt;Second: downloading the binaries. Let’s face it, some of the people that write wonderfully handy tools and library are the same that do not know how to put together a nice, usable site for a fellow programmer to get a glimpse of what your useful piece of software can do and most importantly: how to even download it and get it running. And do not get me started with those projects that you have to build (compile is so unfashionable these days) in order to use. You should be writing OSS for people to &lt;u&gt;use&lt;/u&gt; and for the clever, helping ones to contribute and improve it. But do not scare the hell of the less knowledgeable ones with a stupidly complex process when what they only want is use what you have created and, maybe, thank you.&lt;/p&gt;  &lt;h2&gt;Sucking a bit less&lt;/h2&gt;  &lt;p&gt;With the advent of packaging systems one of the steps is dead easy: finding the project becomes navigating the equivalent of an App Store (I hope I do not get sued for using the term) and read the more or less descriptive synopsis. That is how spoiled we have become.    &lt;br /&gt;Has “I want if now, fast and free” attitude, the instant gratification society, the epicureal orgy ruined the hippy OSS mindset? I do not think so. Everything evolves. What was acceptable some time ago it is not anymore, because something better/more accessible&amp;#160; substituted it. And now, there is little to none excuse to be snobbish and not making your OSS project available for the masses.&lt;/p&gt;  &lt;h2&gt;Not so fast, Tiger&lt;/h2&gt;  &lt;p&gt;Is it enough? Not for me. Let me tell you how it goes with me, dear OSS project:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-I0T8LoqMtR4/TtZSBDLyu_I/AAAAAAAAAvk/XznphgUipMQ/s1600-h/image7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-bNyTqXmMx7o/TtZSB6FnnHI/AAAAAAAAAvs/Od2lofCsEsc/image_thumb5.png?imgmax=800" width="405" height="354" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Summing it up: if you are not in Nuget chances of finding you are slim and if you are up there, you better have a half-decent project page.&lt;/p&gt;  &lt;p&gt;Mind you, I am not being spoiled or arrogant. Do not take it personally. It will be a loss for us both if we do not get to know each other.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-5345094333418603467?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/X9yzeWX_dl4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/5345094333418603467/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=5345094333418603467" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5345094333418603467?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5345094333418603467?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/X9yzeWX_dl4/sixth-ossense.html" title="The Sixth OSSense" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-bNyTqXmMx7o/TtZSB6FnnHI/AAAAAAAAAvs/Od2lofCsEsc/s72-c/image_thumb5.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/12/sixth-ossense.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUFRnw8eSp7ImA9WhRRFks.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-359467973648373759</id><published>2011-11-30T16:50:00.001+01:00</published><updated>2011-11-30T16:50:17.271+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-30T16:50:17.271+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Gadgets" /><title>Less is… uh, less?</title><content type="html">&lt;p&gt;Or so the saying goes, right? The &lt;strike&gt;lazy&lt;/strike&gt; minimalist in me wants to say the utterly wrong “Less is More”.     &lt;br /&gt;&lt;em&gt;Wrong&lt;/em&gt; as I am writing about Solid State. Which is a mystery itself… was there ever a Liquid one?&lt;/p&gt;  &lt;p&gt;When talking about screen size (and many other less interesting subjects), the more and bigger the better. I, myself, have been spoiled for so long with plenty. I had been a happy member of the triple-monitor club, but my membership was put on hold when I moved out from the &lt;em&gt;office&lt;/em&gt; office to work most of the time from my &lt;em&gt;home&lt;/em&gt; office. Neither my desk nor my work laptop were up for it, but I was content enough with a dual arrangement: my valuable own 22” Samsung 225BW paired with the 20” HP LP2065 kindly provided by my employer (which is indeed a nicer display with a higher resolution then mine’s).&lt;/p&gt;  &lt;p&gt;Nice and all that, but Julemand (the local version of good-old Santa Claus –amongst other names–) came early this year to take advantage of a nicely priced offer on a stunning 27” IPS-paneled Dell U2711. Julemand also left some seriously stiff neck that prevented me from jumping to unpack it and install it as soon as I got it, but that’s another story.&lt;/p&gt;  &lt;h2&gt;The Subject&lt;/h2&gt;  &lt;p&gt;Important thing is: boy it is huge! Place it facing upwards, pour some water and you have a freaking swimming pool. Do you think I am exaggerating? You may be right, but that’s how excited I am. I have not had the chance to spare the time it deserves, but I think it is a cutie. A cutie beefy screen. It does not matter it won’t earn many design prizes, but to me, hideous it is not.&lt;/p&gt;  &lt;h2&gt;My Relationship with the Subject&lt;/h2&gt;  &lt;p&gt;I have another confession. I know nothing of displays, calibration reviews and articles are gibberish to me. Reading them makes me feel as ignorant and visually-crippled as I feel hearing-challenged when I read discussions about audiophile headphones. I notice when something looks better when compared to another display, regardless of gamut, deltas and all the other jargon; just as I can hear differences between cheap-o headphones and the more expensive ones. Just do not make me choose amongst the quality ones as I simply cannot tell the difference.    &lt;br /&gt;I am not a designer. I like my home pictures stunning with real colors; I like my IDE windows happily sharing space and I hate scrolling in order to compare two-plus pieces of text. And I like, not, love, durable, quality pieces of equipment. And a quality display is one of the best investments one can do. You are going to be using it all the time and it is not going to become “obsolete” in 2-3 years time, like most of computing equipment you are currently using. &lt;/p&gt;  &lt;h2&gt;Facts of Life&lt;/h2&gt;  &lt;p&gt;Not all is candy floss and bouncing elves. Having a set up with such disparate displays comes with some quirks. the first one is that the difference of resolution makes impossible to span a window amongst the two displays. Not that I do it that often, but I have done it. I tried and it dos not work. It feels like major refraction. In fact, it is so big that makes dragging from one screen an uncannily weird experience.&lt;/p&gt;  &lt;p&gt;But the most annoying one? Here’s a fact for you: it is impossible to calibrate two monitors side by side, unless they are the same model. And even there you’ll find subtle differences. And mine do not even use the same technology! They look crazy different. I will give it another frustrating shot when the new monitor image settles down (or is it just another urban legend?)&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;What else can I say? Oh, yeah, I like them big.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-359467973648373759?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/CNXXOn4zY6Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/359467973648373759/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=359467973648373759" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/359467973648373759?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/359467973648373759?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/CNXXOn4zY6Y/less-is-uh-less.html" title="Less is… uh, less?" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/11/less-is-uh-less.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQNQ307eyp7ImA9WhRSFk0.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-2076699842916487580</id><published>2011-11-18T09:03:00.001+01:00</published><updated>2011-11-18T09:03:12.303+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-18T09:03:12.303+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Speaking" /><title>Tak for i går</title><content type="html">&lt;p&gt;Con esta expresión danesa quiero dar las gracias a todos los asistentes a mi charla de ayer en el grupo de usuarios de Madrid.NET. Fue un placer y espero que lo hayáis disfrutado casi tanto como yo. Todo el material (código, enlaces y notas) está disponible en &lt;a title="https://github.com/dgg/Dgg.Cqrs.Sample" href="https://github.com/dgg/Dgg.Cqrs.Sample"&gt;https://github.com/dgg/Dgg.Cqrs.Sample&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;With this very Danish expression I want to thank all the attendance of my yesterday’s talk. It was awesome to speak to you all. I hope you enjoyed it as much as I did.&lt;/p&gt;  &lt;p&gt;All the material from the talk (“slides” + code + all links) is available from &lt;a title="https://github.com/dgg/Dgg.Cqrs.Sample" href="https://github.com/dgg/Dgg.Cqrs.Sample"&gt;https://github.com/dgg/Dgg.Cqrs.Sample&lt;/a&gt;,&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-2076699842916487580?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/dJw6reZ_P2I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/2076699842916487580/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=2076699842916487580" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2076699842916487580?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2076699842916487580?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/dJw6reZ_P2I/con-esta-expresion-danesa-quiero-dar.html" title="Tak for i går" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/11/con-esta-expresion-danesa-quiero-dar.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcHQHo5fSp7ImA9WhRSEEU.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-887371574141284875</id><published>2011-11-12T08:13:00.001+01:00</published><updated>2011-11-12T08:13:51.425+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-12T08:13:51.425+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Speaking" /><title>Heading Motherland</title><content type="html">&lt;p&gt;no, I am not leaving beautiful, cloudy Denmark. Well… I am, but just for some days.&lt;/p&gt;  &lt;p&gt;Why anyone cares? Because it is not for (all) pleasure. As a matter of fact I will be doing something that I had liked to do for long time: speaking in a Spanish User Group. And the guys of &lt;a href="http://madriddotnet.wordpress.com/2011/11/11/evento-cqrs-by-example/"&gt;Madrid .NET&lt;/a&gt; gave me the chance to do it (thanks &lt;a href="http://www.lfraile.net/"&gt;Luis&lt;/a&gt;!)&lt;/p&gt;  &lt;p&gt;The topic is one I am very fond of: CQRS. And one that I touched both in the &lt;a href="http://www.anug.dk/"&gt;Århus User Group&lt;/a&gt; and for my colleagues in &lt;a href="http://www.vertica.dk/"&gt;Vertica&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Some time has passed since I envisioned the contents and new technologies have settled down, so I did a small rewrite of the sample code and I am going to try a new concept of slides.    &lt;br /&gt;Besides, timing is a bit off, as &lt;a href="http://dddworkshopee2.eventbrite.com/"&gt;Eric Evans&lt;/a&gt; and &lt;a href="http://cqrsworkshopud.eventbrite.com/"&gt;Udi Dahan&lt;/a&gt; have been touching some of the same topics just this past week &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-surprisedsmile" alt="Surprised smile" src="http://lh4.ggpht.com/-rTd-4NW-WU8/Tr4creFo5CI/AAAAAAAAAvY/kkVEEmbDgP8/wlEmoticon-surprisedsmile%25255B2%25255D.png?imgmax=800" /&gt; Ok, they have the names, the brains, the experience and the books. But I do have… uh, well… yes! the charms… and the jokes… and I hope they don’t speak Spanish, so I can have one more on my side.    &lt;br /&gt;Mix it with the fact that it is going to be my first time speaking technical jargon in my mother tongue and that (I hope) there’ll be familiar faces in the attendance and one can understand why I am thrilled about it.&lt;/p&gt;  &lt;p&gt;So, what are you waiting for? Go and &lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032499147&amp;amp;Culture=es-ES"&gt;register&lt;/a&gt; and see me sweat my beers.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-887371574141284875?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/hFoSkfaUkCo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/887371574141284875/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=887371574141284875" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/887371574141284875?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/887371574141284875?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/hFoSkfaUkCo/heading-motherland.html" title="Heading Motherland" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-rTd-4NW-WU8/Tr4creFo5CI/AAAAAAAAAvY/kkVEEmbDgP8/s72-c/wlEmoticon-surprisedsmile%25255B2%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/11/heading-motherland.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UDQXo8eyp7ImA9WhRTEU0.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-6914764785429455455</id><published>2011-10-31T23:47:00.001+01:00</published><updated>2011-10-31T23:47:50.473+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-31T23:47:50.473+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons.NUnit" /><title>One After the Other</title><content type="html">&lt;p&gt;That is an enigmatic title to write about serialization. Well, sort of, as one of the meanings of the word refers to that concept.    &lt;br /&gt;But writing about successions is not my intention. My intention is to write about the technique that allows objects to be persisted to another medium different from their native memory space and more specifically on how to test serialization of objects.&lt;/p&gt;  &lt;h2&gt;Freeze!&lt;/h2&gt;  &lt;p&gt;That is kind of what the values on an object do when it gets serialized. The values of the properties (the state of the object) are saved to the serialization medium (a stream) hoping they will be reconstituted into another instance of the type.&lt;/p&gt;  &lt;p&gt;Once the type developer decides that his/her creation needs some flavor of serialization (the .NET framework offers some flavors on its own and third party libraries expand the choice) comes the time in which tests are written to either guide the implementation or check it against some assumptions.&lt;/p&gt;  &lt;p&gt;In my limited experience designing serializable types I have faced several scenarios that I needed to test:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;check that the type can be successfully serialized and de-serialized &lt;/li&gt;    &lt;li&gt;check that the serialized form of an object contains the same values as the original &lt;/li&gt;    &lt;li&gt;provide examples of the serialization format &lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;Return Ticket, Please&lt;/h2&gt;  &lt;p&gt;The first two scenarios can be tested by serializing the type, then de-serializing it, and comparing the values to the original object (the one that was serialized in the first place). Depending of the flavor of serialization, different objects are involved in the serialization sprinkling some I/O over the mixture.&lt;/p&gt;  &lt;p&gt;The serialization target is, more often than not, rather unimportant, as so are the mechanics of the serialization flavor. Remember, we are not testing serialization per se, we are checking that our type can be serialized and the state is maintained. Once we have taken from the picture the repetitive and unimportant code, we can use an abstraction of the process of serializing and de-serializing an object to a stream. And that abstraction is provided by &lt;code&gt;IRoundtripSerializer&lt;/code&gt;, included in &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-Serialization"&gt;Testing.Commons&lt;/a&gt;.&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public interface IRoundtripSerializer&amp;lt;T&amp;gt; : IDisposable
{
    string Serialize(T toSerialize);
    T Deserialize();
}&lt;/pre&gt;

&lt;p&gt;For that abstraction, some implementations are provided for popular types of serialization provided by the .NET Framework: &lt;code&gt;BinaryRoundtripSerializer&lt;/code&gt;, &lt;code&gt;XmlRoundtripSerializer&lt;/code&gt;, &lt;code&gt;DataContractRoundtripSerializer&lt;/code&gt; and &lt;code&gt;JsonRoundtripSerializer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But such types only implement the mechanics. How about actual checking the properties of the de-serialized object? For that purpose the &lt;code&gt;SerializationConstraint&lt;/code&gt;, provided by &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-NUnit-Constraints#serializationconstraint"&gt;Testing.Commons.NUnit&lt;/a&gt; can be used. Its usage is really simple, just use the &lt;code&gt;Must&lt;/code&gt; extension to choose the flavor and provide constraints to be used over the de-serialized instance:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(new Serializable { D = 3m, S = &amp;quot;s&amp;quot; },
    Must.Be.BinarySerializable&amp;lt;Serializable&amp;gt;(
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(Serializable.DataContractString(&amp;quot;s&amp;quot;, 3m),
    Must.Be.DataContractDeserializable&amp;lt;Serializable&amp;gt;(
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(Serializable.DataContractString(&amp;quot;s&amp;quot;, 3m),
    Must.Be.XmlSerializable&amp;lt;Serializable&amp;gt;(
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(Serializable.DataContractString(&amp;quot;s&amp;quot;, 3m),
    Must.Be.JsonSerializable&amp;lt;Serializable&amp;gt;(
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;p&gt;But imagine you want to check the serialization of your type using a third party library (like the excellent &lt;a href="http://json.codeplex.com/"&gt;JSON.Net&lt;/a&gt;). 

  &lt;br /&gt;Well, nothing prevents the implementation of a &lt;code&gt;IRoundtripSerializer&lt;/code&gt; that uses that third party library and the usage of the extension created for such scenario: &lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;var serializer = MockRepository.GenerateStub&amp;lt;IRoundtripSerializer&amp;lt;Serializable&amp;gt;&amp;gt;();
serializer.Stub(s =&amp;gt; s.Deserialize()).Return(serializable);
Assert.That(serializable,
    Must.Be.Serializable(serializer, 
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;h2&gt;By Example&lt;/h2&gt;

&lt;p&gt;For the third supported scenario (providing the serialization representation), the abstraction &lt;code&gt;IDeserializer&lt;/code&gt; is provided by Testing.Commons:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public interface IDeserializer
{
    T Deserialize&amp;lt;T&amp;gt;(string toDeserialize);
}&lt;/pre&gt;

&lt;p&gt;And the same implementation for usual .NET serialization methods: &lt;code&gt;XmlDeserializer&lt;/code&gt;, &lt;code&gt;DataContractDeserializer&lt;/code&gt; and &lt;code&gt;JsonDeserializer&lt;/code&gt;. Binary serialization is left out as it is pretty useless to provide a string representing the internal binary format. As before, one can use a constraint provided by Testing.Commons.NUnit, &lt;code&gt;DeserializationConstraint&lt;/code&gt; instatiable by &lt;code&gt;Must&lt;/code&gt; extensions.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(Serializable.XmlString(&amp;quot;s&amp;quot;, 3m),
            Must.Be.XmlDeserializable&amp;lt;Serializable&amp;gt;(
                Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
               .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(Serializable.DataContractString(&amp;quot;s&amp;quot;, 3m),
    Must.Be.DataContractDeserializable&amp;lt;Serializable&amp;gt;(
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(Serializable.JsonString(&amp;quot;s&amp;quot;, 3m),
    Must.Be.JsonDeserializable&amp;lt;Serializable&amp;gt;(
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;p&gt;And again, one can go custom implementing the interface and passing the instance to the extension:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;var deserialized = new Serializable { D = 3m, S = &amp;quot;s&amp;quot; };

var deserializer = MockRepository.GenerateStub&amp;lt;IDeserializer&amp;gt;();
deserializer.Stub(s =&amp;gt; s.Deserialize&amp;lt;Serializable&amp;gt;(serializationRepresentation)).Return(deserialized);
Assert.That(serializationRepresentation,
    Must.Be.Deserializable&amp;lt;Serializable&amp;gt;(deserializer, 
        Has.Property(&amp;quot;S&amp;quot;).EqualTo(&amp;quot;s&amp;quot;)
        .And.Property(&amp;quot;D&amp;quot;).EqualTo(3m)));&lt;/pre&gt;

&lt;h2&gt;Using it Already&lt;/h2&gt;

&lt;p&gt;If you want to be testing the serialization of your types, you can get the latest version of &lt;a href="http://nuget.org/List/Packages/Testing.Commons"&gt;Testing.Commons&lt;/a&gt; and &lt;a href="http://nuget.org/List/Packages/Testing.Commons.NUnit"&gt;Testing.Commons.NUnit&lt;/a&gt; from NuGet, which will be, from now one, the only way of getting the binaries (apart from building fro the source).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-6914764785429455455?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/7x18_VbWaP0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/6914764785429455455/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=6914764785429455455" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/6914764785429455455?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/6914764785429455455?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/7x18_VbWaP0/one-after-other.html" title="One After the Other" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/10/one-after-other.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQHRn48cSp7ImA9WhdaEk0.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-2018478282989956190</id><published>2011-10-21T16:45:00.001+02:00</published><updated>2011-10-21T16:45:37.079+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-21T16:45:37.079+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Gadgets" /><title>It…is…not…dead… Yet</title><content type="html">&lt;p&gt;Sure not many people know what a &lt;a href="http://www.zune.net/en-US/products/zunehd/default.htm"&gt;Zune player&lt;/a&gt; is (and even less own one).    &lt;br /&gt;But those who know it and are more or less up to date on what is going on in the Microsoft arena keep reminding me “oh… and by the way, your Zune is dead. Microsoft &lt;a href="http://www.zune.net/en-US/support/zuneplayers/supportzuneplayers.htm"&gt;killed it&lt;/a&gt;.”&lt;/p&gt;  &lt;h2&gt;But it isn’t…&lt;/h2&gt;  &lt;p&gt;…even though &lt;em&gt;they&lt;/em&gt; program us to think it is. A company made a business decision of stop producing a product.&lt;/p&gt;  &lt;p&gt;No one killed anyone.   &lt;br /&gt;No one knocked on my door with the intention to take away my device.    &lt;br /&gt;No one is erasing my devices' content remotely or making it fail on purpose with an invisible remote.&lt;/p&gt;  &lt;p&gt;The only thing just happened is that no new units of the product are going to be produced. How that could affect me?&lt;/p&gt;  &lt;h3&gt;No more device updates&lt;/h3&gt;  &lt;p&gt;I have not experienced any bugs in my player. So if everything stays as it is I am as happy as I was before the announcement. Besides, when was the last time my player was updated with a major feature? Either I cannot remember or was not a major feature I use. No problem here for me.&lt;/p&gt;  &lt;h3&gt;No replacements&lt;/h3&gt;  &lt;p&gt;I think I have been so lucky that I never had to send something to repair after the warranty expired. Sure, devices crashed, but getting a newer device that does much more for a fraction of what the broken device cost or slightly higher than the repair itself was the way to go. Again, not a problem.&lt;/p&gt;  &lt;h3&gt;No more apps&lt;/h3&gt;  &lt;p&gt;Is this a joke? Since when app development was a factor for getting a Zune? If that was your case you should have been disappointed way earlier.   &lt;br /&gt;I bought my Zune knowing its lousy app support. But I did not need apps. I needed high capacity, good sound quality, lightness and long battery life. I got all of that when I bought it and those features are not going anywhere&lt;/p&gt;  &lt;h3&gt;No new versions&lt;/h3&gt;  &lt;p&gt;I like the device that much that when it does not work anymore I would buy the newest version, sure… or not, because a better solution from other vendor will be available, or I simply fancy a change. Besides, one of the biggest assets of the device is being able to use the Zune Marketplace accessible though the Zune software. That is alive, kicking an improving since Microsoft is leveraging its telephony strategy on it. When Microsoft removes support for Zune HD devices for newer versions of the &lt;a href="http://www.zune.net/en-US/products/software/default.htm"&gt;Zune software&lt;/a&gt; (if it ever happens) then I will be pissed and I will rant in my blog again. Not now.&lt;/p&gt;  &lt;h2&gt;There I say it&lt;/h2&gt;  &lt;p&gt;I could not care less if there are going to be any more Zunes. I am happy with mine. And despite my (already tamed) impulses of getting a second unit as a replacement I have only one thing in my head: Microsoft blew it, once again. They killed a great device. When my beloved sexy Zune dies (let it live a long life) I will go for the best high capacity, longer battery life and lighter device I can get at that time, and sure as hell it won’t be a telephone.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-2018478282989956190?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/CeIOhXw9SdE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/2018478282989956190/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=2018478282989956190" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2018478282989956190?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2018478282989956190?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/CeIOhXw9SdE/itisnotdead-yet.html" title="It…is…not…dead… Yet" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/10/itisnotdead-yet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMGQ34_cCp7ImA9WhdbF0Q.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-7552719858309095053</id><published>2011-10-16T21:13:00.001+02:00</published><updated>2011-10-16T21:13:42.048+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-16T21:13:42.048+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons.NUnit" /><title>Testing with ExpectedObjects</title><content type="html">&lt;p&gt;The other day I read an interesting post about testing and a library that might help in some cases, its title is “&lt;a href="http://lostechies.com/derekgreer/2011/06/28/introducing-the-expected-objects-library/"&gt;Introducing the Expected Objects&lt;/a&gt;” library. I thought it might be useful and so I spent a spare evening writing some code to check whether is something that could be useful for my team.&lt;/p&gt;  &lt;h2&gt;The Problem&lt;/h2&gt;  &lt;p&gt;Imagine you are testing a complex object: multiple properties, graphs of objects, collections… and you want to test the outcome of some operation on it and you are using &lt;a href="http://www.nunit.com/"&gt;NUnit&lt;/a&gt; as your testing framework.     &lt;br /&gt;Which strategies are available?&lt;/p&gt;  &lt;h3&gt;Multiple Assertions&lt;/h3&gt;  &lt;p&gt;Most of the time, this is accomplished by using one or more assertions (watch it) that will check the values of certain properties. As the object is complex, the assertion might be complicated or I might not communicate correctly what we are trying to achieve.&lt;/p&gt;  &lt;h3&gt;IEqualityComparer&lt;/h3&gt;  &lt;p&gt;Another way of checking it is creating an instance with the members that are relevant to the test and providing a custom equality comparer to check just those values. This approach has some drawbacks:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;it might no be easy to have the expected object in the desired state and in any case we are using a great deal of logic inside our test, which can lead to false positives &lt;/li&gt;    &lt;li&gt;whenever the assertion fails, we have no useful feedback about what went wrong &lt;/li&gt;    &lt;li&gt;the comparer has to be created ad-hoc and, as always, unless tested, needs to be taken as a source of false positives &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Composite of constraints&lt;/h3&gt;  &lt;p&gt;This is probably your best choice as it is not too difficult to create something that communicates intent properly and the feedback when the assertion fails contains all sorts of useful information. The drawback lies in the amount of artifacts that one need to create in order to achieve the goals.&lt;/p&gt;  &lt;h2&gt;Another solution&lt;/h2&gt;  &lt;p&gt;Most of the time the composite of constraints is the best solution, but for simpler scenarios the extra work might not look appealing. After all the test is focusing in just a a subset of the properties of the actual object, isn’t there an easier/cheaper way?&lt;/p&gt;  &lt;p&gt;And here is where &lt;a href="https://github.com/derekgreer/expectedObjects"&gt;ExpectedObjects&lt;/a&gt; can lay its helping hand. Amongst other features it allows checking the equality of instances of types that do not have to be the same type but have the same “shape” and values. Thus, one can create an anonymous object containing just the values needed and assert the actual objects against it.&lt;/p&gt;  &lt;p&gt;In this example, &lt;em&gt;complex&lt;/em&gt; is an instance of &lt;code&gt;CustomWithCollection&lt;/code&gt; that it is pretty complex (although feasible to create, for the sake of the example). This instance might be returned by the method we are testing and we are only interested in its &lt;em&gt;Name&lt;/em&gt; property and certain properties of its &lt;em&gt;Addresses&lt;/em&gt; collection. An anonymous object is created with just the properties that are of interest for the test, and the &lt;code&gt;Must.Match.Expected()&lt;/code&gt; magic (powered by ExpectedObjects and sprinkled with a bit of adaptation logic) does it job beautifully.&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;var complex = new CustomerWithCollection
{
    Name = &amp;quot;name&amp;quot;,
    PhoneNumber = &amp;quot;number&amp;quot;,
    Addresses = new[]
    {
        new Address { AddressLineOne = &amp;quot;1_1&amp;quot;, AddressLineTwo = &amp;quot;1_2&amp;quot;, City = &amp;quot;city_1&amp;quot;, State = &amp;quot;state_1&amp;quot;, Zipcode = &amp;quot;zip_1&amp;quot;},
        new Address { AddressLineOne = &amp;quot;2_1&amp;quot;, AddressLineTwo = &amp;quot;2_2&amp;quot;, City = &amp;quot;city_2&amp;quot;, State = &amp;quot;state_2&amp;quot;, Zipcode = &amp;quot;zip_2&amp;quot;}
    }
};

var expected = new
{
    Name = &amp;quot;name&amp;quot;,
    Addresses = new object[]
    {
        new { State = &amp;quot;state_1&amp;quot;},
        new { Zipcode = &amp;quot;zip_2&amp;quot;}
    }
};

Assert.That(complex, Must.Match.Expected(expected));&lt;/pre&gt;

&lt;p&gt;What happens when the expectations are not met? In this example, a pretty deep-buried value does not match the one occurring in the actual object. The assertion will fail and the failure is pretty descriptive:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;var complex = new CustomerWithCollection
{
    Name = &amp;quot;name&amp;quot;,
    PhoneNumber = &amp;quot;number&amp;quot;,
    Addresses = new[]
    {
        new Address { AddressLineOne = &amp;quot;1_1&amp;quot;, AddressLineTwo = &amp;quot;1_2&amp;quot;, City = &amp;quot;city_1&amp;quot;, State = &amp;quot;state_1&amp;quot;, Zipcode = &amp;quot;zip_1&amp;quot;},
        new Address { AddressLineOne = &amp;quot;2_1&amp;quot;, AddressLineTwo = &amp;quot;2_2&amp;quot;, City = &amp;quot;city_2&amp;quot;, State = &amp;quot;state_2&amp;quot;, Zipcode = &amp;quot;zip_2&amp;quot;}
    }
};

var expected = new
{
    Name = &amp;quot;name&amp;quot;,
    Addresses = new object[]
    {
        new { State = &amp;quot;state_1&amp;quot;},
        new { Zipcode = &amp;quot;notSameValue&amp;quot;}
    }
};

Assert.That(complex, Must.Match.Expected(expected));&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-VgNs6Tz8HAM/Tpss4_mLWsI/AAAAAAAAAuY/wbd_Wrvo0Ys/s1600-h/ExpectedObjects%25255B12%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ExpectedObjects" border="0" alt="ExpectedObjects" src="http://lh4.ggpht.com/-C-9vZsD3IYI/Tpss5fDrioI/AAAAAAAAAug/i1XmTOxZEVM/ExpectedObjects_thumb%25255B8%25255D.png?imgmax=800" width="640" height="130" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How about refactoring of the actual object? Bad news is that you have a failing test for structural change reason (annoying). Good news is that your tests running in your CI process caught it straight away and it is easy to change. Even better is that some refactoring tools are pretty good in “guessing” the rename and suggest a solution.&lt;/p&gt;

&lt;h2&gt;Wow. Exactly what I Needed&lt;/h2&gt;

&lt;p&gt;Isn’t Open Source Software amazing? If you think so, go and get &lt;a href="http://www.assembla.com/spaces/testing-commons/documents/byRdC--aur4kz_acwqjQYw/download/byRdC--aur4kz_acwqjQYw"&gt;Testing.Commons.NUnit&lt;/a&gt; (or snatch it from &lt;a href="http://nuget.org/List/Packages/Testing.Commons.NUnit"&gt;NuGet&lt;/a&gt;)and you can start using this feature and some others straight away!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-7552719858309095053?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/TKEndjWO8UM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/7552719858309095053/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=7552719858309095053" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/7552719858309095053?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/7552719858309095053?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/TKEndjWO8UM/testing-with-expectedobjects.html" title="Testing with ExpectedObjects" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-C-9vZsD3IYI/Tpss5fDrioI/AAAAAAAAAug/i1XmTOxZEVM/s72-c/ExpectedObjects_thumb%25255B8%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/10/testing-with-expectedobjects.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIFRn46cCp7ImA9WhdUF0g.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-2436067633433336849</id><published>2011-10-04T21:59:00.001+02:00</published><updated>2011-10-04T22:01:57.018+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-04T22:01:57.018+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons.NUnit" /><title>Testing.Commons.NUnit sees the Light</title><content type="html">&lt;p&gt;Yup, as I mentioned &lt;a href="http://dgondotnet.blogspot.com/2011/10/testingcommons-goes-10.html"&gt;before&lt;/a&gt;, after the first “full release” of &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt;, Testing.Commons.NUnit would start to receive more love (and code commits, now that we are at it).&lt;/p&gt;  &lt;p&gt;The first version (0.1) has been released. Binaries can be downloaded from the project files &lt;a href="https://www.assembla.com/spaces/testing-commons/documents/bx5s-y7Sar4k8aacwqjQWU/download/bx5s-y7Sar4k8aacwqjQWU"&gt;area&lt;/a&gt; or from &lt;a href="http://nuget.org/List/Packages/Testing.Commons.NUnit"&gt;NuGet&lt;/a&gt;.&lt;/p&gt;  &lt;h2&gt;Inside the Box?&lt;/h2&gt;  &lt;p&gt;For this premier, I chose to include a base test fixture that makes easier to write AAA tests. Just inherit from &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-NUnit#arrange-act-assert"&gt;ArrangingTest&lt;/a&gt;, implement the method that initializes the SUT, and the subject will be initialized for you and the beginning of each test.&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public class UsefulWhenDealingWithSubjectsWithMockableDependencies : ArrangingTest&amp;lt;ISubjectWithDependencies&amp;gt;
{
    // dependencies go into fields for test to access them
    private IDependencyOne _one;
    private IDependencyTwo _two;

    protected override ISubjectWithDependencies initSubject()
    {
        // dependencies are initialized inside the arrange method
        _one = MockRepository.GenerateStub&amp;lt;IDependencyOne&amp;gt;();
        _two = MockRepository.GenerateStub&amp;lt;IDependencyTwo&amp;gt;();
        return new SubjectWithDependencies(_one, _two);
    }

    [Test]
    public void DoSomethingWithOne_InvokesDependencyOne()
    {
        // Act
        Subject.DoSomethingWithOne();
        // Assert
        _one.AssertWasCalled(o =&amp;gt; o.DoSomething());
    }

    [Test]
    public void DoSomethingWithOne_InvokesDependencyTwo()
    {
        // Act
        // &amp;quot;Subject&amp;quot; is already initialized and reset
        Subject.DoSomethingWithTwo();
        // Assert
        _two.AssertWasCalled(o =&amp;gt; o.DoSomethingElse());
    }
}&lt;/pre&gt;

&lt;p&gt;Also included goes the &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-NUnit-Constraints#constrainedenumerable"&gt;ConstrainedEnumerable&lt;/a&gt; constraint. That allows constraints to be applied to each member of an enumerable and provide meaningful feedback when it fails:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;[Test]
public void CanBeCreatedWithExtension()
{
    Assert.That(new[] { 1, 2 }, new ConstrainedEnumerable(Is.EqualTo(1), Is.LessThan(3)));
    Assert.That(new[] {1, 2}, Must.Be.Constrained(Is.EqualTo(1), Is.LessThan(-3)));
}&lt;/pre&gt;

&lt;pre class="html" name="code"&gt;Element # 1 from &amp;lt; 1, 2 &amp;gt; failed to satisfy constraint.
Expected: less than -3
But was:  2&lt;/pre&gt;

&lt;p&gt;Have fun using it and do not forget to give feedback and getting involved in the project!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-2436067633433336849?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/JEF5AwmGB_0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/2436067633433336849/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=2436067633433336849" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2436067633433336849?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/2436067633433336849?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/JEF5AwmGB_0/testingcommonsnunit-sees-light.html" title="Testing.Commons.NUnit sees the Light" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/10/testingcommonsnunit-sees-light.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYESXgyfip7ImA9WhdUFUg.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-5844802836384798667</id><published>2011-10-02T13:15:00.001+02:00</published><updated>2011-10-02T13:15:08.696+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-02T13:15:08.696+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><title>Testing.Commons goes 1.0</title><content type="html">&lt;p&gt;Let’s throw a party!&lt;/p&gt;  &lt;h2&gt;A Big Gap&lt;/h2&gt;  &lt;p&gt;Wait a second? Last release was 0.4.0.0, when stuff &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-Web#the_asp.net_profile_system._profiletestprovider"&gt;to test the profile system&lt;/a&gt; was added. “&lt;em&gt;Either you have been terribly busy or you are tricking us.&lt;/em&gt;”&lt;/p&gt;  &lt;p&gt;Well, more of the latter if you check the amount of code of the deltas committed. In reality my plan was to go 1.0 when all the code I previously had was ported. It turned out to be less than I thought as I trimmed out some parts I cannot use and clipped redundancies.&lt;/p&gt;  &lt;h2&gt;What’s in?&lt;/h2&gt;  &lt;p&gt;Besides the &lt;a href="http://dgondotnet.blogspot.com/2011/10/documentation-does-get-outdated.html"&gt;already mentioned&lt;/a&gt; in my previous ranting-entry &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-Globalization#culturereseter"&gt;CultureReseter&lt;/a&gt;, that allows scoped fine grained control over the culture of the thread, the bulk comes in the shape of helpers to ease testing web elements.&lt;/p&gt;  &lt;p&gt;&lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-Web#custom_controls._controllifecycle"&gt;ControlLifeCyle&lt;/a&gt; allows calling protected method to simulate the life-cycle of a custom control and &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki/Testing-Commons-Web#bringin_big_guns._httpcontextbuilder"&gt;HttpContextBuilder&lt;/a&gt; eases the creation of the “&lt;em&gt;800 lb gorilla&lt;/em&gt;” that &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.aspx"&gt;HttpContext&lt;/a&gt; is.&lt;/p&gt;  &lt;h3&gt;ControlLifeCycle&lt;/h3&gt;  &lt;p&gt;It may sound like a small thing, but the coolest feature of the class is being able to infer the name of the protected method from a strongly-typed event name.   &lt;br /&gt;I cannot tell you how many times I have fought the war of C# syntax clumsiness for events. This time I spent more time and won it just by chance. change is because I found the solution while googling late in the evening for something else.    &lt;br /&gt;All the &lt;a href="http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx"&gt;Expression&lt;/a&gt; code I have spiked and how many times I have looked Rhino-Mocks’ proxy based codebase (not the simplest codebase to grasp I have to say) in search of a way that allows me to get the name of an event using strongly-typed reflection will not see the light. The secret was MSIL parsing. But of course!&lt;/p&gt;  &lt;p&gt;The inspiration came from a blog about Castle.Windsor &lt;a href="http://docs.castleproject.org/Windsor.AllPages.aspx?Cat=Windsor.Facilities"&gt;facilities&lt;/a&gt;, which made me look into their &lt;a href="http://docs.castleproject.org/Windsor.Event-Wiring-Facility.ashx"&gt;facilities for event wiring&lt;/a&gt;, dig into their &lt;a href="https://github.com/castleproject/Castle.Windsor/blob/master/src/Castle.Facilities.EventWiring/NaiveMethodNameExtractor.cs"&gt;source code&lt;/a&gt; and pick the pieces that I needed, and re-organize them for my purposes. Don’t we love OSS software?&lt;/p&gt;  &lt;h3&gt;HttpContextBuilder&lt;/h3&gt;  &lt;p&gt;Yes, this one is got external inspiration: &lt;a href="http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://jasonbock.net/jb/CodeMockHttpContext.aspx"&gt;here&lt;/a&gt;. But Phil Haack’s reflective-heavy approach was making my tests fail and Jason Bock’s was felt aged and feature-short. So I merged the ideas from both, fluently lifted its API and voilà, one can create feature rich instances of the big guy.&lt;/p&gt;  &lt;h2&gt;Where you said?&lt;/h2&gt;  &lt;p&gt;I knew it, &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt; is exactly what you were looking for! Go and get it from the &lt;a href="https://www.assembla.com/spaces/testing-commons/documents/capsF-7m8r4ilWacwqjQWU/download/capsF-7m8r4ilWacwqjQWU"&gt;project site&lt;/a&gt; or &lt;a href="http://nuget.org/List/Packages/Testing.Commons"&gt;NuGet&lt;/a&gt;.&lt;/p&gt;  &lt;h3&gt;What now?&lt;/h3&gt;  &lt;p&gt;I told you I finished importing the bulk of my previously created code. That means that, unless people contribute we are going to see a slow down in the rate of releases.&lt;/p&gt;  &lt;p&gt;That is not sad in itself, because it means that &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki#testing.commons.nunit"&gt;Testing.Commons.NUnit&lt;/a&gt; is ready to take-off!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-5844802836384798667?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/gvpvZsrsXH0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/5844802836384798667/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=5844802836384798667" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5844802836384798667?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5844802836384798667?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/gvpvZsrsXH0/testingcommons-goes-10.html" title="Testing.Commons goes 1.0" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/10/testingcommons-goes-10.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYCQXk7fCp7ImA9WhdUFUg.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-6379956444788106441</id><published>2011-10-02T12:09:00.001+02:00</published><updated>2011-10-02T12:09:20.704+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-02T12:09:20.704+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Misc" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>Documentation Does Get Outdated</title><content type="html">&lt;p&gt;I am not going to start another flame war about whether documentation is evil or not.&lt;/p&gt;  &lt;p&gt;My personal stand is that is evil but mostly needed.&lt;/p&gt;  &lt;p&gt;One of my biggest concerns with documentation is that, more often than not, tends to become obsolete no matter how hard you try to keep it current. One might seek several explanations, but my personal take is that updating documentation is not nearly as fun as changing code. When I say no matter how hard one try I mean it. I do not intend to disregards completely the value of documentation altogether, but I intend to point out just another example that supports by beliefs.&lt;/p&gt;  &lt;h2&gt;Busted!&lt;/h2&gt;  &lt;p&gt;How much do you think Microsoft spends on documentation? Well, they do have technical writers and correctors and probably proof-readers of corrections, so I would assume they spend more than the average software company does. Some people believe they are not in the bottom half of the table when it comes to documenting their software. At least I think the BCL documentation is not horrendous, although it has its WTF highlights.   &lt;br /&gt;And this praise would be all I’d to say if software was static, but, alas, it is not. Methods evolve, and internal changes sneak in unnoticed.&lt;/p&gt;  &lt;p&gt;One of such changes is exceptions thrown by a method. .NET does not, fortunately I would say, have the concept of checked exceptions, in which the exceptions thrown by a method become a part of its signature. .Net has the concept of documenting the exceptions, but there is no compiler activity in checking whether the exception can actually be thrown in the execution path of the method. so one might happily add or remove exceptions inside a method and the compiler would silently do its job with no complaints.&lt;/p&gt;  &lt;p&gt;That exact event happened to a pretty popular .NET class, the &lt;a href="http://msdn.microsoft.com/en-us/library/bkb1k2x8.aspx"&gt;Thread&lt;/a&gt;. In version 4, a check was removed for the setter of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.thread.currentculture.aspx"&gt;CurrentCulture&lt;/a&gt; property. In previous versions one could not set the current culture of the thread to a &lt;a href="http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.isneutralculture.aspx"&gt;neutral culture&lt;/a&gt; or a &lt;a href="http://msdn.microsoft.com/en-us/library/system.notsupportedexception.aspx"&gt;NotSupportedException&lt;/a&gt; would be thrown.&lt;/p&gt;  &lt;p&gt;Of course documentation was never updated to reflect that change in code.&lt;/p&gt;  &lt;h2&gt;How did you?&lt;/h2&gt;  &lt;p&gt;It happens that &lt;a href="http://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt; contains a class that allows having fine control over the culture a piece of code (mostly a test) runs. Its name is &lt;strong&gt;&lt;em&gt;&lt;a href="http://www.assembla.com/code/testing-commons/git/nodes/src/Testing.Commons/Globalization/CultureReseter.cs"&gt;CultureReseter&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;. A variant of such class has been used for some time now in software running previous versions of the framework.&lt;/p&gt;  &lt;p&gt;Such class had &lt;em&gt;zero&lt;/em&gt; lines of documentation. Instead it came with a bunch of unit tests that told you how to use it and, most importantly, how &lt;u&gt;not&lt;/u&gt; to use it. In one of such scenarios the potential user of my class was pointed out that a neutral culture is not valid when setting the current culture of the thread, as doing so would throw an exception.&lt;/p&gt;  &lt;p&gt;Of course when I tried to run a similar test on .NET4 (the platform of choice of &lt;a href="http://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt;), it automatically failed. I was puzzled. At first I double and tripled checked what I was doing wrong as I thought that such behavior had not changed. Hell! the documentation was telling me it had not changed!!! I had to fire my {decompiler-of-choice} to see with my own eyes that the change, indeed, happened and that my test was catching the change of behavior.&lt;/p&gt;  &lt;h2&gt;So?&lt;/h2&gt;  &lt;p&gt;Does that mean we should ditch documentation at all? Nop.   &lt;br /&gt;But what we could do is use documentation for things that cannot be expressed in code. And let code, in the shape of test, speak about the behavior of each class. &lt;/p&gt;  &lt;p&gt;No offense for technical writers, but we would be better off with less of those and more developers engaged in the endeavor of writing good, expressive tests as a mean of documenting behavior and making it available for us developers.&lt;/p&gt;  &lt;p&gt;There is no better documentation.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-6379956444788106441?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/xRZZ1mchjys" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/6379956444788106441/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=6379956444788106441" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/6379956444788106441?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/6379956444788106441?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/xRZZ1mchjys/documentation-does-get-outdated.html" title="Documentation Does Get Outdated" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/10/documentation-does-get-outdated.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YDRHcyeCp7ImA9WhdUFUk.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-7506344099715894799</id><published>2011-10-02T11:52:00.001+02:00</published><updated>2011-10-02T11:52:55.990+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-02T11:52:55.990+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><category scheme="http://www.blogger.com/atom/ns#" term="NMoneys" /><title>NMoneys.Exchange gets an Article as well.</title><content type="html">&lt;p&gt;I am sure you are aware of both &lt;a href="http://dgondotnet.blogspot.com/2011/06/nmoneys-goes-20-and-gets-company.html"&gt;NMoneys and its companion&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I have written another article in &lt;a href="http://www.codeproject.com/KB/dotnet/NMoneys_Exchange.aspx"&gt;The Code Project&lt;/a&gt; showing what can this extension to &lt;a href="http://code.google.com/p/nmoneys/"&gt;NMoneys&lt;/a&gt; can do for you.&lt;/p&gt;  &lt;p&gt;Enjoy your reading and comment on it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-7506344099715894799?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/SUC2oYthYrM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/7506344099715894799/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=7506344099715894799" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/7506344099715894799?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/7506344099715894799?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/SUC2oYthYrM/nmoneysexchange-gets-article-as-well.html" title="NMoneys.Exchange gets an Article as well." /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/10/nmoneysexchange-gets-article-as-well.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIHSHg-fip7ImA9WhdVEUw.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-4317442391735488869</id><published>2011-09-15T22:10:00.001+02:00</published><updated>2011-09-15T22:12:19.656+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-15T22:12:19.656+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><title>Configure Reality</title><content type="html">&lt;p&gt;Configuration in enterprise application is a fact of life.    &lt;br /&gt;My take on it is as follows: delay it as late as possible and hard-code in anger until someone asks for a change. Then, accepting the fact that is likely to happen again, the value is pushed into configuration.&lt;/p&gt;  &lt;p&gt;Configuration can be as simple as a collection of key-value pairs. But sometimes, configuration needs to be more complex than key-value pairs; just imagine some sort of hierarchical structure or a simple collection of related values.&lt;/p&gt;  &lt;p&gt;For key-value pairs we can use the old &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms228154.aspx"&gt;appSettings&lt;/a&gt;&lt;/em&gt; section, with all its type un-safety (sorry, I forgot &lt;em&gt;type-unsafe&lt;/em&gt; is derogative, nowadays we use &lt;em&gt;dynamic&lt;/em&gt; to name things that blow up at runtime) and if we cannot wait so long and be old-fashioned and get earlier feedback from tools/compiler (boo!) &lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/k4s6c3a0.aspx"&gt;application settings&lt;/a&gt;&lt;/em&gt; is another option.     &lt;br /&gt;For those edge cases in which more complexity is actually needed, there is also a wealth of information about how to use XML serialization to use strongly-typed classes, including various &lt;a href="http://haacked.com/archive/2004/06/25/verylastconfigurationsectionhandler.aspx"&gt;very&lt;/a&gt; last &lt;a href="http://www.codinghorror.com/blog/2006/08/the-last-configuration-section-handler-revisited.html"&gt;configuration&lt;/a&gt; sections ever to be written.&lt;/p&gt;  &lt;p&gt;My preferred option, though, is using custom configuration sections, taking advantage of the well-thought set of classes living in System.Configuration. It is a pretty extensive topic which &lt;a href="http://www.codeproject.com/KB/dotnet/mysteriesofconfiguration.aspx"&gt;other people&lt;/a&gt; have covered in detail, but basically revolves around custom classes decorated with attributes with a semantic model that can be used to improve performance and live outside the rigid world of what can be done within attributes.&lt;/p&gt;  &lt;h2&gt;Dirt goes Under the Rug&lt;/h2&gt;  &lt;p&gt;The very fact that I am writing about it and deserves a place inside a testing library means that, in terms of testability, configuration can give you some headaches if configuration is used all over the place.&lt;/p&gt;  &lt;p&gt;I consider configuration an infrastructure concern and as such I tend to abstract it away behind a interface; so consumers of configuration do not need to deal with configuration’s testing challenges.&lt;/p&gt;  &lt;p&gt;But what happens when we need to test that our configuration object hierarchy is indeed correct? Furthermore, imagine for a second that your application behavior can be somehow tweaked once deployed by changing configuration values. What if those changes are done by people different from the ones that developed the application (or maybe the forgetful same ones)? What if, {insert_deity} forbids, whoever touches configuration makes a mistake? We would definitely want the error message to be descriptive. Or maybe we just want to provide some executable documentation about the usage of our configuration section and get some regression tests for free in the process.&lt;/p&gt;  &lt;p&gt;My point is that we want to test not only the consumers of configuration (providing a &lt;a href="http://xunitpatterns.com/Test%20Double.html"&gt;test double&lt;/a&gt;), but the providers of configuration as well.&lt;/p&gt;  &lt;h2&gt;Behave!&lt;/h2&gt;  &lt;p&gt;Fact is that, regardless of the configuration strategy being used, only one set of configuration values tends to be loaded into the application. And such model does not really lend itself to testing multiple cases. The solution is simple enough: the class that provides the configuration can be instantiated differently while testing from the way is instantiated during application runtime. The trick is using an external configuration file via &lt;a href="http://msdn.microsoft.com/en-us/library/ms224437.aspx"&gt;ConfigurationManager.OpenExeConfiguration(string)&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Let’s exemplify with a complex configuration of a caching system in which each cache has a different time-to-life for its elements and each cache can have dependencies with other caches. The abstraction for this piece of configuration could be something like:&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public interface ICachingConfiguration
{
    TimeSpan TimeToExpire(string cacheName);
    bool HasDependencies(string cacheName);
    IEnumerable&amp;lt;string&amp;gt; GetDependantCaches(string cacheName);
}&lt;/pre&gt;

&lt;p&gt;The class implementing the abstraction, uses a bunch of collection elements “hanging” from a custom &lt;a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationsection.aspx"&gt;ConfigurationSection&lt;/a&gt;, the &lt;strong&gt;&lt;em&gt;CachingConfigurationSection&lt;/em&gt;&lt;/strong&gt;. The default constructor will be used when the provider is instantiated “normally”, but the constructor receiving the path of an executable (or assembly) file is used during testing to inject a file that contains the configuration for the scenario being tested.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class CachingConfiguration : ICachingConfiguration
{
    private readonly CachingConfigurationSection _section;
    public CachingConfiguration()
    {
        _section = (CachingConfigurationSection)ConfigurationManager.GetSection(CachingConfigurationSection.SectionName);
    }
    public CachingConfiguration(string configFile)
    {
    _section = (CachingConfigurationSection)ConfigurationManager.OpenExeConfiguration(configFile).GetSection(CachingConfigurationSection.SectionName);
    }
    public TimeSpan TimeToExpire(string cacheName)
    {
        ExpirationElement expiration = _section.Expirations[cacheName];
        if (expiration == null) throw new ConfigurationErrorsException();
        return expiration.Value;
    }
    public bool HasDependencies(string cacheName)
    {
        DependenciesCollection dependencies = _section.Dependencies;
        return dependencies != null &amp;amp;&amp;amp; dependencies[cacheName] != null;
    }
    public IEnumerable&amp;lt;string&amp;gt; GetDependantCaches(string cacheName)
    {
        IEnumerable&amp;lt;string&amp;gt; cacheNames = Enumerable.Empty&amp;lt;string&amp;gt;();
        if (HasDependencies(cacheName))
        {
            cacheNames = _section.Dependencies[cacheName].DependantCaches
                .Cast&amp;lt;DependantCacheElement&amp;gt;()
                .Select(dependant =&amp;gt; dependant.Name);
        }
        return cacheNames;
    }
}&lt;/pre&gt;

&lt;h2&gt;Find and Fetch&lt;/h2&gt;

&lt;p&gt;So the provider can receive a path from a file… Other part if the puzzle is a helper class that allows a declarative way of expressing the configuration file to be loaded. That part is achieved by decorating our tests with ConfigurationAssemblyAttribute, specifying the path to an imaginary assembly named after the file that contains the piece of configuration to be tested. For instance, a configuration file named &lt;em&gt;CachingCorrectConfig.dll.config&lt;/em&gt; can be loaded by decorating the test with the path to an assembly &lt;em&gt;CachingCorrectConfig.dll&lt;/em&gt;. That assembly file does not even need to be a real assembly, it suffices being an empty file with the .dll extension. In order to ease the retrieval of the attribute the ExternalConfiguration.GetConfigurationAssemblyPath() method can be used within the test. Let’s see how easy it is:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;[Test]
[ConfigurationAssembly(&amp;quot;..\\..\\Configuration\\ConfigFiles\\CachingCorrectConfig.dll&amp;quot;)]
public void GetConfigurationAssemblyPath_TestDecoratedWithAssemblyFile_AllowsAccessToConfigurationValuesFromCustomConfiguration()
{
    string assemblyPath = ExternalConfiguration.GetConfigurationAssemblyPath(MethodBase.GetCurrentMethod());

    ICachingConfiguration subject = null;
    Assert.That(() =&amp;gt; subject = new CachingConfiguration(assemblyPath), Throws.Nothing);

    Assert.That(subject.TimeToExpire(&amp;quot;expiration1&amp;quot;), Is.EqualTo(1.Seconds()));
    Assert.That(subject.HasDependencies(&amp;quot;cache2&amp;quot;), Is.True);
    Assert.That(subject.GetDependantCaches(&amp;quot;cache1&amp;quot;), Is.EqualTo(new[]{&amp;quot;cache1_1&amp;quot;, &amp;quot;cache1_2&amp;quot;}));
}&lt;/pre&gt;

&lt;h2&gt;When Things Go Wrong&lt;/h2&gt;

&lt;p&gt;A way to tell people what to do is telling them what NOT to do. That works for testing as well. We need to verify that our assumptions on what we consider incorrect configuration are indeed correct (weird stuff). Problem is, error messages are localized and we do not really want to couple the success of a test of ours to a text on a third party resource (the framework is a “third party” in this case).
  &lt;br /&gt;Well, all of my machines run English versions of both OS and .NET Framework so I think it is OK that my default error message fragments are in that language. If that is not the case for you, the same extensibility model as for the &lt;a href="http://www.assembla.com/code/testing-commons/git/nodes/src/Testing.Commons/Must.cs"&gt;Must&lt;/a&gt; provider is used, so feel free to provide your own extension method for whichever case you feel like testing to &lt;strong&gt;&lt;em&gt;ExceptionMessagePart.For&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;[Test, ConfigurationAssembly(&amp;quot;..\\..\\Configuration\\ConfigFiles\\CachingIncorrectConfig_UndefinedElement.dll&amp;quot;)]
public void UndefinedElement_ExceptionWithMessageContaining()
{
    string assemblyPath = ExternalConfiguration.GetConfigurationAssemblyPath(MethodBase.GetCurrentMethod());
    Assert.That(() =&amp;gt; new CachingConfiguration(assemblyPath), Throws.InstanceOf&amp;lt;ConfigurationErrorsException&amp;gt;()
        .With.Message.StringContaining(ExceptionMessagePart.For.UndefinedElement(ExpirationElement.ElementName)));
}
[Test, ConfigurationAssembly(&amp;quot;..\\..\\Configuration\\ConfigFiles\\CachingIncorrectConfig_MissingRequiredElement.dll&amp;quot;)]
public void MissingRequiredElement_ExceptionWithMessageContaining()
{
    string assemblyPath = ExternalConfiguration.GetConfigurationAssemblyPath(MethodBase.GetCurrentMethod());
    Assert.That(() =&amp;gt; new CachingConfiguration(assemblyPath), Throws.InstanceOf&amp;lt;ConfigurationErrorsException&amp;gt;()
        .With.Message.StringContaining(ExceptionMessagePart.For.MissingRequiredMember(ExpirationsCollection.CollectionName)));
}&lt;/pre&gt;

&lt;h2&gt;I Want It!&lt;/h2&gt;

&lt;p&gt;You got it! It is in &lt;a href="http://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt;! &lt;a href="http://www.assembla.com/spaces/testing-commons/documents/brZP5038Kr4joVeJe5cbLr/download/brZP5038Kr4joVeJe5cbLr"&gt;Binary&lt;/a&gt; or &lt;a href="http://nuget.org/List/Packages/Testing.Commons"&gt;packaged&lt;/a&gt;, your choice.&lt;/p&gt;

&lt;p&gt;Have many ideas for improvement? Share them and contribute to the project. Let the code speak.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-4317442391735488869?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/V4np6wnVeWk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/4317442391735488869/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=4317442391735488869" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/4317442391735488869?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/4317442391735488869?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/V4np6wnVeWk/configure-reality.html" title="Configure Reality" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/09/configure-reality.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUINQ3k5eSp7ImA9WhdVEUw.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-8425590285445051586</id><published>2011-09-13T20:30:00.001+02:00</published><updated>2011-09-15T22:13:12.721+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-15T22:13:12.721+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>The Magnificent Sixteen</title><content type="html">&lt;p&gt;GUIDs are precious little things. Useful, annoying at times, but lovable nonetheless. Cherish them as if they were unique (all pun intended) and they will pay your love back.&lt;/p&gt;  &lt;p&gt;I am one of those who despises wasting GUIDs. Some would go even further: They will say I am afraid that we are going to run out of them.    &lt;br /&gt;Reality is, I firmly believe they have a higher purpose in life than being stuck in some obscure testing project, never seeing the “production light”, test run, after test run, after test run…     &lt;br /&gt;But just imagine this other equally terrible fate: being born for a split second of a test run and die after it finished. The paradigm of purposeless life: be born in pain (and wasted CPU cycles), enjoy a brief life (microseconds) while the test runs, be in the middle of action without being noticed and die. No one remembers you. No one ever ask you what your value was. You are irrelevant, Dispensable. A mere thing used for the sole purpose of not using The One Whose Name Cannot Be Mentioned:&lt;/p&gt;  &lt;pre&gt;Guid.Empty&lt;/pre&gt;

&lt;p&gt;These apocalyptic scenarios are everywhere around us:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;developers that use GUID generation shortcuts in test projects are preventing those otherwise very capable entities to be born where they are most needed: production code. 
    &lt;pre&gt;new Guid(“somethingThatWasCopiedFromATool”)&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;Some sadistic developers even generate new GUIDS for every run of the test! Heartless, cold-blooded GUID murderers, that will burn in hell listening to their victim’s screams, if you ask me. 
    &lt;pre&gt;Guid.NewGuid()&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Stop the Slaughter&lt;/h2&gt;

&lt;p&gt;I cannot tell how many unborn GUIDs I have saved with my own hands. But I felt I could do better. How many times I have dreamt of using a team of well-trained GUIDs that can stop the massacre? Loads. But know I moved my lazy developer-ass and share with you someone that can introduce you to &lt;strong&gt;T&lt;em&gt;he Magnificent Sixteen&lt;/em&gt;: &lt;em&gt;&lt;strong&gt;GuidBuilder&lt;/strong&gt;&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My experience tells me that in most test one does not need trillions of GUIDs to compare. An upper limit close to the dozen is more accurate. Beyond that limit, I am in a position to assure you are getting yourself into a big mess with that test. But that dozen or so are important for your test scenario. You are probably identifying some objects with those, so it is important that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;they are different &lt;/li&gt;

  &lt;li&gt;no innocent GUID suffers &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can use GuidBuilder.Build() to create one of the Magnificent Sixteen. An hexadecimal figure is all you need, and a GUID with all digits set to that figure will be created. Pass it as a char or a byte.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;Assert.That(GuidBuilder.Build('0'), Is.EqualTo(new Guid(&amp;quot;00000000-0000-0000-0000-000000000000&amp;quot;)));
Assert.That(GuidBuilder.Build(3), Is.EqualTo(new Guid(&amp;quot;33333333-3333-3333-3333-333333333333&amp;quot;)));&lt;/pre&gt;

&lt;h2&gt;Where Do I Sign?&lt;/h2&gt;

&lt;p&gt;Luckily, no signature is needed. You get it alongside the rest of the wonders of &lt;a href="http://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt; in their latest version (&lt;a href="http://www.assembla.com/spaces/testing-commons/documents/ajGCXe3Jur4jwJeJe5cbLr/download/ajGCXe3Jur4jwJeJe5cbLr"&gt;v0.2&lt;/a&gt;) which can also be obtained via &lt;a href="http://nuget.org/List/Packages/Testing.Commons"&gt;Nuget Package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Use it. Save those GUIDs. Delay the Doomsday that will happen when we run out of them. Decrease that crazy entropy growth. But remember, if it is not hexadecimal (0 to 15 or '0' to 'F'), it is not one of the Magnificent Sixteen.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-8425590285445051586?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/S6wuHI1Ik1s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/8425590285445051586/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=8425590285445051586" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/8425590285445051586?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/8425590285445051586?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/S6wuHI1Ik1s/magnificent-sixteen.html" title="The Magnificent Sixteen" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/09/magnificent-sixteen.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QEQ3o_eSp7ImA9WhdXGU0.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-5524275245122767651</id><published>2011-09-01T22:35:00.001+02:00</published><updated>2011-09-01T22:35:02.441+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-01T22:35:02.441+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><category scheme="http://www.blogger.com/atom/ns#" term="NMoneys" /><title>NMoneys 2.1.0.0</title><content type="html">&lt;p&gt;Not a lot of movement in &lt;a href="http://code.google.com/p/nmoneys/"&gt;NMoneys&lt;/a&gt; until now.&lt;/p&gt;  &lt;p&gt;But the unthinkable, has happened: I have received an email notification for a change in the ISO standard for currencies!! After more than two years subscribed I finally received my first amendment newsletter. I totally attribute this event to changes in the &lt;a href="http://www.currency-iso.org/"&gt;maintenance agency&lt;/a&gt;, which changes are very welcome, Excel and XML tables of &lt;a href="http://www.currency-iso.org/dl_iso_table_a1.xls"&gt;current&lt;/a&gt; and &lt;a href="http://www.currency-iso.org/dl_iso_tables_a3.xls"&gt;historic&lt;/a&gt; currencies, amongst others.&lt;/p&gt;  &lt;p&gt;As a result I made some quick changes to support the latest standard and pushed the new version for everyone to enjoy.&lt;/p&gt;  &lt;p&gt;And that is how it should be, shouldn’t it?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-5524275245122767651?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/DIPdnxKWaMg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/5524275245122767651/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=5524275245122767651" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5524275245122767651?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5524275245122767651?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/DIPdnxKWaMg/nmoneys-2100.html" title="NMoneys 2.1.0.0" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/09/nmoneys-2100.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUHR3w4fCp7ImA9WhdXFEU.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-3661396619588813869</id><published>2011-08-28T01:03:00.001+02:00</published><updated>2011-08-28T01:03:56.234+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-28T01:03:56.234+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons" /><category scheme="http://www.blogger.com/atom/ns#" term="Design" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>Clarity is The Theme of the Party</title><content type="html">&lt;p&gt;While developing the improvements for the &lt;strong&gt;&lt;em&gt;Generate&lt;/em&gt;&lt;/strong&gt; class of &lt;a href="http://dgondotnet.blogspot.com/2011/08/testingcommons-its-matter-of-time.html"&gt;Testing.Commons&lt;/a&gt; I faced an API design challenge that I, at least, consider challenging.&lt;/p&gt;  &lt;p&gt;Imagine we have to model a TimeOfDay class, that puts a name to an important time of the day, such as noon or midnight and which members are used from within a delegate, to give a nice lambda-ish flavor to the API:&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;DateTime dt = 28.August(2006).At(t =&amp;gt; t.Noon);&lt;/pre&gt;

&lt;p&gt;How could one design such a type?&lt;/p&gt;

&lt;h2&gt;Enumerations, Good Old Friends&lt;/h2&gt;
&lt;cite&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/cc138362.aspx"&gt;MSDN&lt;/a&gt;: ”An enumeration type (also named an enumeration or an enum) provides an efficient way to define a set of named integral constants that may be assigned to a variable.”&lt;/cite&gt;, which means that you can put a name on a constant value, as long as it is one of the supported types (integral type &lt;em&gt;byte&lt;/em&gt;, &lt;em&gt;sbyte&lt;/em&gt;, &lt;em&gt;short&lt;/em&gt;, &lt;em&gt;ushort&lt;/em&gt;, &lt;em&gt;int&lt;/em&gt;, &lt;em&gt;uint&lt;/em&gt;, &lt;em&gt;long&lt;/em&gt;, or &lt;em&gt;ulong&lt;/em&gt;). 

&lt;p&gt;As we want to represent that time of the day as the time elapsed since the day started, we are willing to represent it as a TimeSpan. Of course, TimeSpan is not one of the supported types, which rules out enumerations.&lt;/p&gt;

&lt;h2&gt;Static, Not Good Enough&lt;/h2&gt;

&lt;p&gt;One way to overcome this problem is declare the values either as constants. Since they are not constants as the compilers likes them, they could be public readonly fields, as in:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class TimeOfDay
{
    public static readonly TimeSpan Noon = TimeSpan.FromHours(12);
    public static readonly TimeSpan Midnight = TimeSpan.Zero;
}&lt;/pre&gt;

&lt;p&gt;That is almost fine (we can use static to prevent instantiation), if what we want to use is the class in statements, as in:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;TimeOfDay noon = TimeOfDay.Noon;&lt;/pre&gt;

&lt;p&gt;Unfortunately, in order to use it within the lambda an instance of TimeOfDay is required as static fields cannot be accesses from object instances &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-sadsmile" alt="Sad smile" src="http://lh4.ggpht.com/-5R8IRtgJBUM/Tll32rXsLcI/AAAAAAAAAjk/ukSq1tmrjWA/wlEmoticon-sadsmile%25255B2%25255D.png?imgmax=800" /&gt;.&lt;/p&gt;

&lt;h2&gt;Instance is the way to go&lt;/h2&gt;

&lt;p&gt;Instances if what is needed, instances is what will be provided.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class TimeOfDay
{
    public readonly TimeSpan Noon = TimeSpan.FromHours(12);
    public readonly TimeSpan Midnight = TimeSpan.Zero;
}&lt;/pre&gt;

&lt;p&gt;That indeed allows the delegate usage, and instantiation is allowed. I do not see a lot of people willing to instantiate such a simple class (we have become so lazy as to consider the new operator as an annoyance) nor I want to instantiate one every time, just to access a “constant” field (serious case of micro-optimization, I know).&lt;/p&gt;

&lt;h2&gt;Thou Shall Not Instantiate&lt;/h2&gt;

&lt;p&gt;Preventing instantiation from the outside is as simple as to provide the lamest construction of all time: a singleton. I do not care about lazy initialization or anything, so the simplest construct is used:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class TimeOfDay
{
    public readonly TimeSpan Noon = TimeSpan.FromHours(12);
    public readonly TimeSpan Midnight = TimeSpan.Zero;
    
    private TimeOfDay(){ }
    
    internal static readonly TimeOfDay Instance = new TimeOfDay();
}&lt;/pre&gt;

&lt;p&gt;Now, we are able to prevent instantiation from outside (and inside the assembly) and happily use the single instance exposed by Instance from within the assembly.&lt;/p&gt;

&lt;p&gt;We could satisfy the users that want to consume static counterparts, but it would have to be using another name, as static and instance members cannot have the same name &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-sadsmile" alt="Sad smile" src="http://lh4.ggpht.com/-5R8IRtgJBUM/Tll32rXsLcI/AAAAAAAAAjk/ukSq1tmrjWA/wlEmoticon-sadsmile%25255B2%25255D.png?imgmax=800" /&gt;. But as that is not a use case that I foresee (famous last words) I decided not to add them.&lt;/p&gt;

&lt;h2&gt;Interesting?&lt;/h2&gt;

&lt;p&gt;Maybe. I, for one, enjoyed designing an API test-first.
  &lt;br /&gt;Useful? Well, I think the API is intuitive and expressive. What do you think?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-3661396619588813869?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/iLggjQEWno0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/3661396619588813869/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=3661396619588813869" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3661396619588813869?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3661396619588813869?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/iLggjQEWno0/clarity-is-theme-of-party.html" title="Clarity is The Theme of the Party" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-5R8IRtgJBUM/Tll32rXsLcI/AAAAAAAAAjk/ukSq1tmrjWA/s72-c/wlEmoticon-sadsmile%25255B2%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/08/clarity-is-theme-of-party.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUMRX0_eip7ImA9WhdXFEU.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-3600416229857156281</id><published>2011-08-28T00:10:00.001+02:00</published><updated>2011-08-28T00:14:44.342+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-28T00:14:44.342+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons" /><category scheme="http://www.blogger.com/atom/ns#" term=".Net" /><title>Testing.Commons. It’s a matter of time</title><content type="html">&lt;p&gt;Face it: time is everywhere and cannot run away from it. That is why I chose time to be the subject of the first release of &lt;a href="http://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt;, a mere 0.1.&lt;/p&gt;  &lt;p&gt;Classes that deal with time in the BCL (&lt;strong&gt;&lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.datetime.aspx"&gt;DateTime&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx"&gt;DateTimeOffset&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.timespan.aspx"&gt;TimeSpan&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;) might have their issues. They might not be accurate. They might not be correct at all. There might be some better alternatives. But they are not going anywhere, anytime soon.&lt;/p&gt;  &lt;p&gt;And code that make use of them needs to be tested and, honestly, those classes do not have the most expressive API when it comes to create instances of them. This feature is not that incredible useful in the “real world” (the world of production code) where dates are rarely hard-coded, but it does not hurt anyone if a bit of lipstick is put on top.&lt;/p&gt;  &lt;h2&gt;D-Day&lt;/h2&gt;  &lt;p&gt;DateTimes can be created in a very visual way using a set of cleverly named extension methods.&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;DateTime date = 2.January(2000);&lt;/pre&gt;

&lt;p&gt;Sometimes what one needs is whichever date between two bounds.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;DateTime one = Generate.Between(11.March(1977)).And(27.August(2011)).Single();&lt;/pre&gt;

&lt;p&gt;And sometimes what one needs is a number of dates between two bounds. Careful, though; an infinite stream of dates takes a long time to enumerate, limit the number of results.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;IEnumerable&amp;lt;DateTime&amp;gt; infinite = Generate.Between(11.March(1977)).And(27.August(2011)).Stream();
IEnumerable&amp;lt;DateTime&amp;gt; tenDates = Generate.Between(11.March(1977)).And(27.August(2011)).Stream(10);&lt;/pre&gt;

&lt;h2&gt;Times Are A’ Changing&lt;/h2&gt;

&lt;p&gt;Dates are alright, but we have measures smaller than days.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;DateTime withSeconds = 11.March(1977).At(12, 30, 45);
DateTime withMinutes = 11.March(1977).At(12, 30);
DateTime withHours = 11.March(1977).At(12);&lt;/pre&gt;

&lt;p&gt;We even have certain times of the day important enough to deserve a name on their own.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;DateTime midday = 28.August(2006).At(t =&amp;gt; t.Noon);
DateTime midnight = 30.September(2008).At(t =&amp;gt; t.MidNight);&lt;/pre&gt;

&lt;h2&gt;Where in the world is &lt;a href="#geeknote"&gt;*&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;It took some time to figure out &lt;em&gt;DateTime&lt;/em&gt; was not the best structure to deal with the artificial human-created trickeries that time zones are. Sometimes what we want to do is not performing some transformations between dates in different zones. We just want to specify exactly what we are creating. &lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;DateTimeOffset utcPlusTwo = 11.March(1977).At(15, 30, 45).In(TimeSpan.FromHours(2)));
DateTimeOffset utc = 11.March(1977).At(13, 30, 45).InUtc())&lt;/pre&gt;

&lt;h2&gt;The arrow of time&lt;/h2&gt;

&lt;p&gt;Time passes. And spans of time needs to be measured and compared. Another set of extension methods allows elegant creation of &lt;em&gt;Timespans&lt;/em&gt;.&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;TimeSpan weeks = 2.Weeks();
TimeSpan days = 3.Days();
TimeSpan hours = 4.Hours();
TimeSpan minutes = 5.Minutes();
TimeSpan seconds = 6.Seconds();
TimeSpan allUnits = 5.Days().Hours(4).Minutes(3).Seconds(2).Milliseconds(1);&lt;/pre&gt;

&lt;h2&gt;Get It While Fresh&lt;/h2&gt;

&lt;p&gt;You can get this first 0.1 release downloading the binaries from the project’s &lt;a href="https://www.assembla.com/spaces/testing-commons/documents/a2t6Ys0oWr4i2AeJe4gwI3/download/a2t6Ys0oWr4i2AeJe4gwI3"&gt;File Area&lt;/a&gt; or using the &lt;a href="http://nuget.org/List/Packages/Testing.Commons"&gt;NuGet package&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a name="geeknote"&gt;&lt;/a&gt;Geek Note:&lt;/p&gt;

  &lt;p&gt;If the reader’s mind complete the phrase with “Carmen Sandiego” we have one of three cases:&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;old nerdy individual &lt;/li&gt;

    &lt;li&gt;really nerdy individual &lt;/li&gt;

    &lt;li&gt;&lt;a href="http://www.facebook.com/carmensandiego"&gt;facebook&lt;/a&gt; infected individual &lt;/li&gt;
  &lt;/ol&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-3600416229857156281?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/MquYBQY9u2Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/3600416229857156281/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=3600416229857156281" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3600416229857156281?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3600416229857156281?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/MquYBQY9u2Y/testingcommons-its-matter-of-time.html" title="Testing.Commons. It’s a matter of time" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/08/testingcommons-its-matter-of-time.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQBQXY9eip7ImA9WhdXFEo.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-3161295512220194355</id><published>2011-08-27T22:52:00.001+02:00</published><updated>2011-08-27T22:52:30.862+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-27T22:52:30.862+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Unit Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing.Commons" /><category scheme="http://www.blogger.com/atom/ns#" term="Open Source" /><title>A Little more OSS</title><content type="html">&lt;p&gt;As the reader might have notice, I am a big advocate of testing. During the years that I have been practicing some flavor of testing I have been developing, borrowing and using small little classes (or bigger ones) and techniques to make my life easier and my code suck a little less.&lt;/p&gt;  &lt;p&gt;I have decided that I might as well share them with more people and, who knows, the benefit might become mutual. That, and the fact that my code will be improved as it makes its way into the new projects, is why I am launching &lt;a href="https://www.assembla.com/spaces/testing-commons/wiki"&gt;Testing.Commons&lt;/a&gt;.&lt;/p&gt;  &lt;h2&gt;Testing.Commons&lt;/h2&gt;  &lt;p&gt;This project will contains code that helps and supports testing in any way. No external dependencies on any framework or tool should be needed.&lt;/p&gt;  &lt;h2&gt;Testing.Commons.NUnit&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://nunit.com/"&gt;NUnit&lt;/a&gt; is my weapon of choice when it comes to unit testing and I even use it to drive some other types of tests. One of the features I have come to love the most is the ability to extend its assertion model with custom-developed constraints. This project will contain, most than anything, some useful custom constraints I have used though the years.&lt;/p&gt;  &lt;h2&gt;Tool changes&lt;/h2&gt;  &lt;p&gt;This may sound a little harsh and will leave some people disappointed, but I will focus my efforts only in .Net 4 as there are newer features that I definitely want to explore, such as dynamic and default parameters, for their potential to improve code expressiveness and clarity.&lt;/p&gt;  &lt;p&gt;I have been using &lt;a href="http://subversion.apache.org/"&gt;Subversion&lt;/a&gt; for some time and used Google code to host my other OSS project: &lt;a href="http://code.google.com/p/nmoneys/"&gt;NMoneys&lt;/a&gt;.     &lt;br /&gt;Not that I have been let down or limited in any way by the tools or the hosting, but I a willing to get my head around Distributed Version Control Systems. Everyone is jumping onto &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt; and &lt;a href="https://github.com/"&gt;github&lt;/a&gt; and that is all fine. I am not (for the moment). I will give Git hosting in &lt;a href="https://www.assembla.com/"&gt;Assembla&lt;/a&gt; a try. If it does not work for me I can always change, can’t I? We are blesses with multiple very cheap (free) hosting choices, time to take advantage at last, right?&lt;/p&gt;  &lt;p&gt;NuGet has been proved mature enough to be considered as the solely delivery method of libraries such as these, so I will continue leveraging two dependent packages. I am still no decided whether I am going to support Ruby Gems, but no door is closed.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-3161295512220194355?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/y2_rZx4uO98" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/3161295512220194355/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=3161295512220194355" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3161295512220194355?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3161295512220194355?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/y2_rZx4uO98/little-more-oss.html" title="A Little more OSS" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/08/little-more-oss.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYHR3c9cSp7ImA9WhdTGU4.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-536204290902042298</id><published>2011-07-17T22:55:00.001+02:00</published><updated>2011-07-17T22:55:36.969+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-17T22:55:36.969+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NDC" /><category scheme="http://www.blogger.com/atom/ns#" term="Conferences" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Dead rich soon? Not with this Attitude</title><content type="html">&lt;p&gt;Everyone of us dreams with this success stories: self-made, luck-stricken, hard working average Joe –or Jane– that once in a while hits the jackpot of a very successful application that makes him rich overnight (and still doing his –or her– dishes).&lt;/p&gt;  &lt;p&gt;Certainly, I do not know what it takes, but to be honest with you, odds are against me in every front, so place your bets anywhere else. I mean it. Not kidding or being overly modest. I consider myself a good enough professional. I enjoy what I do and I possess a certain degree of passion. It just seems that I do not have it.   &lt;br /&gt;I will illustrate with a small anecdote. Of course, I do not imply that had I did differently I would be swimming in gold, or that the guy that actually did it is (I hope he is not, for the sake of my own sanity)&lt;/p&gt;  &lt;p&gt;I have been attending to conferences for 4 years. The technological landscape has changed substantially, but something has remained constant: my desire to be prepared and organized. I would meticulously prepare my schedule in advance and load it onto my handheld device of the season.&lt;/p&gt;  &lt;p&gt;My first experience was a bit nightmarish: the conference site would not offer the chance to export the session to a calendar application, so I had to enter by hand all information regarding titles, abstract, location and speaker on appointment items in Outlook and sync it with my PDA (Windows Mobile at that time). I might have lost a couple of afternoons doing so. It looked kind of cool, but to tell you the truth I was reverting back to good old printed program with an circle surrounding the session title.&lt;/p&gt;  &lt;p&gt;Subsequent experiences improved as conferences realized that people might want to be prepared and offered a way to export session as iCal items. That improved the process but I only had to tweak it to have it displayed in a sensible way.&lt;/p&gt;  &lt;p&gt;This year, broken the chains of Outlook and Windows I went “into the cloud” and prepared everything in Google Calendar. Did it improve the process? Hardly. And again, the problem of changes of agenda and my own schedule being useless manifested themselves,&lt;/p&gt;  &lt;p&gt;The process is dead simple: have an overview of the sessions, pick the ones you are interested in and consult your schedule multiple times to figure out which room are you heading onto. And yet I wasted my own time 4 years in a row. Did I ever think of making my life easier with an application that did the job for me? Not a single one. What do you think I am? A programmer? So you can imagine my absolute face of utter disbelief and I guess you could hear the “SPLASH! But… of course!” when I saw all people checking their schedule in a app for the conference that did exactly what I wasted my time doing.   &lt;br /&gt;Its name is &lt;a href="http://www.oktaset.com/"&gt;Oktaset&lt;/a&gt;, the front-end runs on multiple platforms (iOS, Android and Windows Phone) and supported this year’s &lt;a href="https://market.android.com/details?id=com.oktaset"&gt;NDC&lt;/a&gt; and the &lt;a href="https://market.android.com/details?id=com.oktaset.conference.techedna"&gt;Tech-Ed&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I had the business case but I did not have the vision. They did. And they executed brilliantly. Shame on me. But when your brain does not click, it does not click.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-536204290902042298?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/itV3kEWaBJk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/536204290902042298/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=536204290902042298" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/536204290902042298?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/536204290902042298?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/itV3kEWaBJk/dead-rich-soon-not-with-this-attitude.html" title="Dead rich soon? Not with this Attitude" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/07/dead-rich-soon-not-with-this-attitude.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYHRn09eip7ImA9WhZaFEo.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-3434892122828973525</id><published>2011-06-30T23:41:00.001+02:00</published><updated>2011-06-30T23:42:17.362+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-30T23:42:17.362+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NMoneys" /><title>NMoneys goes 2.0 and Gets Company</title><content type="html">&lt;p&gt;Wow, after a 1.6 version I decided to jump straight to 2.0.    &lt;br /&gt;Is it that big of a change? Well, not really, maybe a &lt;a href="http://code.google.com/p/nmoneys/wiki/Changelog#2.0.0.0"&gt;couple&lt;/a&gt; of breaking changes and features. But NMoneys 2.0 is just a side dish, the entrée is… NMoneys.Exchange 1.0&lt;/p&gt;  &lt;h2&gt;Is NMoneys Already Dead?&lt;/h2&gt;  &lt;p&gt;Not a chance! &lt;em&gt;NMoneys.Exchange&lt;/em&gt; might steal some of its older brother’s thunder for some time, but &lt;em&gt;NMoneys&lt;/em&gt; still plays the star role.&lt;/p&gt;  &lt;h2&gt;Why Another Project?&lt;/h2&gt;  &lt;p&gt;Well, when NMoneys got its &lt;a href="http://www.codeproject.com/KB/dotnet/NMoneys.aspx"&gt;CodeProject article&lt;/a&gt;, just about the fist thing people asked was: “Why can’t you exchange currencies?”.&lt;/p&gt;  &lt;p&gt;As it is stated in the vision of NMoneys, currency exchange was not in my radar. For one, I did not know the rules for the operations (I still don't) and the data needed is so volatile that companies make money out of providing services around it. So, clearly not a candidate for a library.&lt;/p&gt;  &lt;p&gt;But since people asked, I started thinking. Why not? I turned the petition into an excuse to sketch an API… and the result is NMoneys.Exchange, which sits right of top on NMoney’s foundations: &lt;em&gt;Money&lt;/em&gt; and &lt;em&gt;CurrencyIsoCode&lt;/em&gt; and that will have a whole different lifecycle than NMoneys itself, with different releases, packages, but still close to its older brother.&lt;/p&gt;  &lt;h2&gt;What’s inside?&lt;/h2&gt;  &lt;p&gt;NMoneys.Exchange is not more than a framework that allows applying exchange rates to monetary quantities. I will repeat it again: “it’s a framework, not a service”. You need to be a developer to use it, just as you need to be a developer to use a library like NMoneys.&lt;/p&gt;  &lt;p&gt;When imported into your project (alongside NMoneys) it offers a couple extensibility points in the shape of the Convert() and TryConvert() extension methods over Money. From those extensibility points you can use the provided To() method that will make things happen.&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;var tenEuro = new Money(10m, CurrencyIsoCode.EUR);

var tenDollar = tenEuro.Convert().To(CurrencyIsoCode.USD);
var tenPounds = tenEuro.Convert().To(Currency.Gbp);&lt;/pre&gt;

&lt;p&gt;Is that it? That easy? Then why all the fuss with exchange rates and services and your reluctance to implement it? Well, if you look at it closely it is not doing the right thing, unless the exchange rates between EUR, USD and GBP is 1, which I suspect it isn’t. By default, the framework does no harm, but not the correct thing either. Because correct in this context is not something a library can do, as rates change by the minute.&lt;/p&gt;

&lt;p&gt;the trick is providing some exchange rates. How? Either implementing an interface, or using an included implementation of that interface and letting the framework know of it. This example shows how to use the included implementation, include some invented conversion rate and configure that provider:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;var customProvider = new TabulatedExchangeRateProvider();
customProvider.Add(CurrencyIsoCode.EUR, CurrencyIsoCode.USD, 0);

ExchangeRateProvider.Factory = () =&amp;gt; customProvider;

var tenEuro = new Money(10m, CurrencyIsoCode.EUR);
var zeroDollars = tenEuro.Convert().To(CurrencyIsoCode.USD);&lt;/pre&gt;

&lt;p&gt;How does one plug his favorite data feed? Implement a custom IExchangeRateProvider and configure the factory as in the previous example.&lt;/p&gt;

&lt;p&gt;As I stated before, I have not become wiser with time and I still do not know the rules for applying rates to monetary quantities. What I have done, in the same extensibile spirit is provide a default implementation that does not harm (or so I believe) using the default decimal multiplication, and leave open the extension of the class that does the work: ExchangeRate. In this example, we subclass ExchangeRate to perform fake custom arithmetic:&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class CustomRateArithmetic : ExchangeRate
{
    public CustomRateArithmetic(CurrencyIsoCode from, CurrencyIsoCode to, decimal rate) : base(from, to, rate) { }

    public override Money Apply(Money from)
    {
        return new Money(0m, To);
    }
}&lt;/pre&gt;

&lt;p&gt;If you&amp;#160; want to know more supported scenarios, go to the &lt;a href="http://code.google.com/p/nmoneys/wiki/ExchangeQuickStart"&gt;Quickstart&lt;/a&gt; that lives under the project &lt;a href="http://code.google.com/p/nmoneys/w/list"&gt;Wiki&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Me Likes. Where?&lt;/h2&gt;

&lt;p&gt;You can go and get it from the project’s &lt;a href="http://code.google.com/p/nmoneys/downloads/detail?name=NMoneys.Exchange.1.0.0.0-bin.zip"&gt;Dowload Area&lt;/a&gt;&amp;#160;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" border="0" align="left" src="https://www.google.com/chart?chs=150x150&amp;amp;cht=qr&amp;amp;chl=//nmoneys.googlecode.com/files/NMoneys.Exchange.1.0.0.0-bin.zip" /&gt;.&lt;/p&gt;

&lt;p&gt;It also got its own &lt;a href="http://nuget.org/List/Packages/NMoneys.Exchange"&gt;Nuget package&lt;/a&gt; and &lt;a href="https://rubygems.org/gems/nmoneys-exchange"&gt;gem&lt;/a&gt;. Download it, use it and do not wait to provide feedback!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-3434892122828973525?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/fCSNMh56ejE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/3434892122828973525/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=3434892122828973525" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3434892122828973525?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/3434892122828973525?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/fCSNMh56ejE/nmoneys-goes-20-and-gets-company.html" title="NMoneys goes 2.0 and Gets Company" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/06/nmoneys-goes-20-and-gets-company.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0AGQX0-cSp7ImA9WhZbF0o.&quot;"><id>tag:blogger.com,1999:blog-2779955313707490982.post-5588406282305805183</id><published>2011-06-22T21:42:00.000+02:00</published><updated>2011-06-22T21:42:00.359+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-22T21:42:00.359+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NDC" /><category scheme="http://www.blogger.com/atom/ns#" term="Conferences" /><title>NDC 2011. And Day 3</title><content type="html">&lt;p&gt;My head was still spinning from the party of the day before. Not because of heavy drinking of wild partying (there was none of those) but because the stream of unleashed energy that Rob Ashton is. A quiet beer can turn into a heated discussion decorated with jewels such as “Javascript is the f… second coming of The Messiah”. Heretic, yes… but by Jove was funny!&lt;/p&gt;  &lt;h2&gt;Package Management deep-dive with Open Wrap&lt;/h2&gt;  &lt;p&gt;For this short last day I decided to look at Open Wrap again. My first contact with it was not very successful… and neither was this second one.&lt;/p&gt;  &lt;p&gt;I agree that demoing nightly builds and bragging about it is nice. When things go as planned. Which was not the case. I have seen Sebastian, the speaker, have the same problems in another session and it’s not cool at all and projects an unprofessional image.&lt;/p&gt;  &lt;p&gt;Problems aside I liked the tool and some of the ideas behind it but I won’t be using it for my projects as I do not like the idea of my package manager taking over my project’s build.&lt;/p&gt;  &lt;h2&gt;CQRS in the Wild&lt;/h2&gt;  &lt;p&gt;I was not expecting this session to become one of my favorites of the conference, so it is nicer when it catches you by surprise.    &lt;br /&gt;What made it become a favorite? Well, almost everything: the topic is interesting to me, the problem domain is familiar, the trade-offs are similar, there’s empathy to the approach to the solution, details of the solution were at the right level given the session’s time constraints, the speaker did a great job communicating the process and was extremely honest with the problems that they are facing and have not solved yet.&lt;/p&gt;  &lt;p&gt;And besides the framework that he is using is Open Source. Another alternative to look into if and when the need comes.&lt;/p&gt;  &lt;h2&gt;Making your Rails App Sing&lt;/h2&gt;  &lt;p&gt;I knew this talk was almost completely away from my range of experience, but &lt;a href="http://blog.wekeroad.com/"&gt;Rob&lt;/a&gt; is really enjoyable to listen to and I was not in the mood for more Javascript.&lt;/p&gt;  &lt;p&gt;The session had almost anything to do with Rails but with a bunch of services you can use from a Rails application or from another sort of application (given there is a hook or you are in the mood to deal with a REST-y API) to solve problems that someone building a site selling some content might face. He spoke from his experience with his own business but I can see myself considering some of the services showcased in the future.&lt;/p&gt;  &lt;h2&gt;The Three Amigos&lt;/h2&gt;  &lt;p&gt;And another session for entertaining purposes only (almost). It is always fun to watch three guys having fun on stage and sharing jokes and laughs. The idea was sort of a competition between the ASP.NET MVC + Entity Framework platform and Ruby on Rails in order to build a simplistic web application.&lt;/p&gt;  &lt;p&gt;The application/technology&amp;#160; part was kind irrelevant and was an excuse to make fun of each other for a while. I have to point out that starting with Rails is easy (and blazing fast to get started once you are comfortable to spend lots of time in the console), but so it is with MVC scaffolding and EF code first. I have to point out the amount of goodness that was released recently in the MVC ecosystem that have substantially changed how to start a quick and dirty project and yet have something that can scale further the drag and drop data-source plus a grid.&lt;/p&gt;  &lt;h2&gt;Unit Testing with Auto-Fixture&lt;/h2&gt;  &lt;p&gt;Last session of an amazing conference. Luck was that the schedule was changed some time ago so that I could watch the session of someone I have been following from some time: &lt;a href="http://blog.ploeh.dk/"&gt;Mark Seeman&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Some time ago a former colleague of mine pointed me the project that was the subject of the talk: &lt;a href="http://autofixture.codeplex.com/"&gt;AutoFixture&lt;/a&gt;. It looks great on paper and the dimension he was presenting was using the tool as a way to create your subject under test in a “maintainable manner”. And I quote it because I was left with the impression that the problem to solve has other alternative solutions that are, in my opinion, orders of magnitude simpler, less intrusive and more self-explaining. But hey, whatever push your boat.&lt;/p&gt;  &lt;p&gt;Once again I have to be picky with the example chosen. Yes, it was guiding the audience towards the need to use the tool being presented, but the process, labeled as TDD, has little to do with TDD: why on Earth would anyone driving the implementation of an interface come up with a first set of tests that has nothing to do with the interface being test-driven? A more strict TDD would have most likely taken the developer towards another (simpler) solution. But that would have not made the tool appear as a desired solution.&lt;/p&gt;  &lt;p&gt;All in all, I think AutoFixture is pretty elegant and I liked the session but I could not let the bitch in me go off a sample, could I?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2779955313707490982-5588406282305805183?l=dgondotnet.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YetAnotherLayerOfIndirection/~4/8alYAZcmmUE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dgondotnet.blogspot.com/feeds/5588406282305805183/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2779955313707490982&amp;postID=5588406282305805183" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5588406282305805183?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2779955313707490982/posts/default/5588406282305805183?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YetAnotherLayerOfIndirection/~3/8alYAZcmmUE/ndc-2011-and-day-3.html" title="NDC 2011. And Day 3" /><author><name>Daniel González</name><uri>http://www.blogger.com/profile/13468563783321963413</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://dgondotnet.blogspot.com/2011/06/ndc-2011-and-day-3.html</feedburner:origLink></entry></feed>

