<?xml version="1.0" encoding="utf-8"?><rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Coding for Fun and Profit</title><link>http://uglybugger.org/</link><description>uglybugger's notes of shared grief and despair</description><language>en-AU</language><copyright>Copyright (C) Andrew Harcourt. All rights reserved.</copyright><managingEditor>andrewh@uglybugger.org</managingEditor><lastBuildDate>Thu, 05 Oct 2017 12:00:00 +1000</lastBuildDate><image><url>https://gravatar.com/avatar/26c73be81cda35268fb6f8aeb3f3664e?s=200</url><title>Coding for Fun and Profit</title><link>http://uglybugger.org/</link></image><a10:id>http://www.uglybugger.org</a10:id><a10:link href="http://uglybugger.org/" /><item><guid isPermaLink="false">introducing_stack_mechanics</guid><link>http://uglybugger.org/software/post/introducing_stack_mechanics</link><author>andrewh@uglybugger.org</author><title>Introducing Stack Mechanics</title><description>&lt;p&gt;After living under a rock for far too long, I'm excited to introduce &lt;a href="http://stackmechanics.com"&gt;Stack Mechanics&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've teamed up with two great friends of mine, &lt;a href="http://damianm.com"&gt;Damian Maclennan&lt;/a&gt; and
&lt;a href="https://nblumhardt.com/"&gt;Nick Blumhardt&lt;/a&gt; to launch a series of deep-dive courses in distributed
systems, microservices architectures and continuous delivery.&lt;/p&gt;

&lt;p&gt;Don't panic - I'm not leaving ThoughtWorks :)&lt;/p&gt;

&lt;p&gt;The longer version: Damian, Nick and I, alongside numerous other great engineers, have spent
a lot of time solving the hard problems that organisations encounter when trying to move away
from monolithic, legacy systems. We've seen lots of places like the potential that microservices
offer with respect to organisational agility and independence, but generally they've been completely
unprepared for the inherent complexities in such systems and how to manage the trade-offs. Usually we
weren't lucky enough for it to be a green-fields project, and as a result we've all inherited our
share of legacy, tighly-coupled systems with ugly, scary integrations, unknown black boxes, business logic
hidden in integration layers (or ESBs, or stored procedures, or BPM layers), and with the many
and various failure modes inherent in such ecosystems.&lt;/p&gt;

&lt;p&gt;We arrived at a set of practices, patterns, techniques and tools that helped us solve these kinds of
problems and we've had a lot of success at it. Unfortunately, we still see so many organisations
making the same kinds of mistakes, through the best of intentions, that we first encountered many
years ago. Many teams start off well but are unaware of the pitfalls; many have no idea how to
even get started.&lt;/p&gt;

&lt;p&gt;We've decided to get together and offer deep-dive training based on our real-world experiences. We're
kicking off in November 2017 with a three-day, hands-on workshop on .NET architecture, microservices,
distributed systems and devops. There will be both theory and practical sessions, covering topics
like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design Patterns for maintainable software&lt;/li&gt;
&lt;li&gt;Test Driven Development&lt;/li&gt;
&lt;li&gt;DevOps practices such as monitoring and instrumentation&lt;/li&gt;
&lt;li&gt;Continuous delivery&lt;/li&gt;
&lt;li&gt;Configuration patterns&lt;/li&gt;
&lt;li&gt;REST API implementation&lt;/li&gt;
&lt;li&gt;Microservices&lt;/li&gt;
&lt;li&gt;Asynchronous messaging&lt;/li&gt;
&lt;li&gt;Scaling and caching&lt;/li&gt;
&lt;li&gt;Legacy system integration and migration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Attendees will work with us and together to build an actual ecosystem to solve a small but real-world
problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tickets.lup.com.au/stackmechanics-brisbane"&gt;Book your ticket for the November 2017 (Brisbane) workshop&lt;/a&gt; now
to lock in early-bird pricing.&lt;/p&gt;

&lt;p&gt;We'll be scheduling other workshops in other cities (and probably some more in Brisbane), so
register your interest in other dates and cities via &lt;a href="https://stackmechanics.com/"&gt;stackmechanics.com&lt;/a&gt;,
follow us on Twitter via &lt;a href="https://twitter.com/stack_mechanics"&gt;@stack_mechanics&lt;/a&gt;
and on Facebook as &lt;a href="https://www.facebook.com/stackmechanics/"&gt;Stack Mechanics&lt;/a&gt;.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 05 Oct 2017 12:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/introducing_stack_mechanics" /><a10:updated>2017-10-05T12:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;After living under a rock for far too long, I'm excited to introduce &lt;a href="http://stackmechanics.com"&gt;Stack Mechanics&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've teamed up with two great friends of mine, &lt;a href="http://damianm.com"&gt;Damian Maclennan&lt;/a&gt; and
&lt;a href="https://nblumhardt.com/"&gt;Nick Blumhardt&lt;/a&gt; to launch a series of deep-dive courses in distributed
systems, microservices architectures and continuous delivery.&lt;/p&gt;

&lt;p&gt;Don't panic - I'm not leaving ThoughtWorks :)&lt;/p&gt;

&lt;p&gt;The longer version: Damian, Nick and I, alongside numerous other great engineers, have spent
a lot of time solving the hard problems that organisations encounter when trying to move away
from monolithic, legacy systems. We've seen lots of places like the potential that microservices
offer with respect to organisational agility and independence, but generally they've been completely
unprepared for the inherent complexities in such systems and how to manage the trade-offs. Usually we
weren't lucky enough for it to be a green-fields project, and as a result we've all inherited our
share of legacy, tighly-coupled systems with ugly, scary integrations, unknown black boxes, business logic
hidden in integration layers (or ESBs, or stored procedures, or BPM layers), and with the many
and various failure modes inherent in such ecosystems.&lt;/p&gt;

&lt;p&gt;We arrived at a set of practices, patterns, techniques and tools that helped us solve these kinds of
problems and we've had a lot of success at it. Unfortunately, we still see so many organisations
making the same kinds of mistakes, through the best of intentions, that we first encountered many
years ago. Many teams start off well but are unaware of the pitfalls; many have no idea how to
even get started.&lt;/p&gt;

&lt;p&gt;We've decided to get together and offer deep-dive training based on our real-world experiences. We're
kicking off in November 2017 with a three-day, hands-on workshop on .NET architecture, microservices,
distributed systems and devops. There will be both theory and practical sessions, covering topics
like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design Patterns for maintainable software&lt;/li&gt;
&lt;li&gt;Test Driven Development&lt;/li&gt;
&lt;li&gt;DevOps practices such as monitoring and instrumentation&lt;/li&gt;
&lt;li&gt;Continuous delivery&lt;/li&gt;
&lt;li&gt;Configuration patterns&lt;/li&gt;
&lt;li&gt;REST API implementation&lt;/li&gt;
&lt;li&gt;Microservices&lt;/li&gt;
&lt;li&gt;Asynchronous messaging&lt;/li&gt;
&lt;li&gt;Scaling and caching&lt;/li&gt;
&lt;li&gt;Legacy system integration and migration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Attendees will work with us and together to build an actual ecosystem to solve a small but real-world
problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tickets.lup.com.au/stackmechanics-brisbane"&gt;Book your ticket for the November 2017 (Brisbane) workshop&lt;/a&gt; now
to lock in early-bird pricing.&lt;/p&gt;

&lt;p&gt;We'll be scheduling other workshops in other cities (and probably some more in Brisbane), so
register your interest in other dates and cities via &lt;a href="https://stackmechanics.com/"&gt;stackmechanics.com&lt;/a&gt;,
follow us on Twitter via &lt;a href="https://twitter.com/stack_mechanics"&gt;@stack_mechanics&lt;/a&gt;
and on Facebook as &lt;a href="https://www.facebook.com/stackmechanics/"&gt;Stack Mechanics&lt;/a&gt;.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">command_line_add_bindingredirect</guid><link>http://uglybugger.org/software/post/command_line_add_bindingredirect</link><author>andrewh@uglybugger.org</author><title>Command-line Add-BindingRedirect</title><description>&lt;p&gt;One of the things I try to do as part of a build pipeline is to have automatic package
updates. My usual pattern is something along the lines of a CI build that runs on every
commit and every night, plus a Canary build that updates all the packages to their latest
respective versions.&lt;/p&gt;

&lt;p&gt;The sequence looks something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Canary build:
&lt;ol&gt;
&lt;li&gt;pulls the lastest of the project from the &lt;code&gt;master&lt;/code&gt; branch;&lt;/li&gt;
&lt;li&gt;runs &lt;code&gt;nuget.exe update&lt;/code&gt; or equivalent;&lt;/li&gt;
&lt;li&gt;then compiles the code and runs the unit tests.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If everything passes, it does (roughly) this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git checkout -b update-packages
git add -A .
git commit -m "Automatic package update"
git push -f origin update-packages


# Note: There's a bit more error-checking around non-merged branches and so on,
# but that's fundamentally it.
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The CI build then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;picks up the changes in the &lt;code&gt;update-packages&lt;/code&gt; branch;&lt;/li&gt;
&lt;li&gt;compiles the code (yes, again), to make sure that we didn't miss anything in the previous commit);&lt;/li&gt;
&lt;li&gt;runs the unit tests;&lt;/li&gt;
&lt;li&gt;deploys the package to a CI environment;&lt;/li&gt;
&lt;li&gt;runs the integration tests; and&lt;/li&gt;
&lt;li&gt;if all is well, merges the &lt;code&gt;update-packages&lt;/code&gt; branch back down to &lt;code&gt;master&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For what it's worth, if a &lt;code&gt;master&lt;/code&gt; build is green (and they pretty much all should go green if you're
building your pull requests) then out the door it goes. You &lt;em&gt;do&lt;/em&gt; trust your test suite, don't you? ;)&lt;/p&gt;

&lt;p&gt;All of this can be done with stock TeamCity build steps with the exception of one thing: the call
to &lt;code&gt;nuget.exe update&lt;/code&gt; doesn't add binding redirects and there's no way to do that from the console.
The &lt;code&gt;Add-BindingRedirect&lt;/code&gt; PowerShell command is built into the NuGet extension to Visual Studio and
there's no way to run it from the command line.&lt;/p&gt;

&lt;p&gt;That's always been a bit of a nuisance and I've hand-rolled hacky solutions to this several times
in the past so I've re-written a slightly nicer solution and open-sourced it. You can find
the &lt;a href="https://github.com/uglybugger/Add-BindingRedirect"&gt;Add-BindingRedirect&lt;/a&gt; project on GitHub. Releases
are downloadable from the &lt;a href="https://github.com/uglybugger/Add-BindingRedirect/releases"&gt;Add-BindingRedirect releases page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pull requests are welcome :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 04 Oct 2016 11:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/command_line_add_bindingredirect" /><a10:updated>2016-10-04T11:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;One of the things I try to do as part of a build pipeline is to have automatic package
updates. My usual pattern is something along the lines of a CI build that runs on every
commit and every night, plus a Canary build that updates all the packages to their latest
respective versions.&lt;/p&gt;

&lt;p&gt;The sequence looks something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Canary build:
&lt;ol&gt;
&lt;li&gt;pulls the lastest of the project from the &lt;code&gt;master&lt;/code&gt; branch;&lt;/li&gt;
&lt;li&gt;runs &lt;code&gt;nuget.exe update&lt;/code&gt; or equivalent;&lt;/li&gt;
&lt;li&gt;then compiles the code and runs the unit tests.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If everything passes, it does (roughly) this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git checkout -b update-packages
git add -A .
git commit -m "Automatic package update"
git push -f origin update-packages


# Note: There's a bit more error-checking around non-merged branches and so on,
# but that's fundamentally it.
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The CI build then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;picks up the changes in the &lt;code&gt;update-packages&lt;/code&gt; branch;&lt;/li&gt;
&lt;li&gt;compiles the code (yes, again), to make sure that we didn't miss anything in the previous commit);&lt;/li&gt;
&lt;li&gt;runs the unit tests;&lt;/li&gt;
&lt;li&gt;deploys the package to a CI environment;&lt;/li&gt;
&lt;li&gt;runs the integration tests; and&lt;/li&gt;
&lt;li&gt;if all is well, merges the &lt;code&gt;update-packages&lt;/code&gt; branch back down to &lt;code&gt;master&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For what it's worth, if a &lt;code&gt;master&lt;/code&gt; build is green (and they pretty much all should go green if you're
building your pull requests) then out the door it goes. You &lt;em&gt;do&lt;/em&gt; trust your test suite, don't you? ;)&lt;/p&gt;

&lt;p&gt;All of this can be done with stock TeamCity build steps with the exception of one thing: the call
to &lt;code&gt;nuget.exe update&lt;/code&gt; doesn't add binding redirects and there's no way to do that from the console.
The &lt;code&gt;Add-BindingRedirect&lt;/code&gt; PowerShell command is built into the NuGet extension to Visual Studio and
there's no way to run it from the command line.&lt;/p&gt;

&lt;p&gt;That's always been a bit of a nuisance and I've hand-rolled hacky solutions to this several times
in the past so I've re-written a slightly nicer solution and open-sourced it. You can find
the &lt;a href="https://github.com/uglybugger/Add-BindingRedirect"&gt;Add-BindingRedirect&lt;/a&gt; project on GitHub. Releases
are downloadable from the &lt;a href="https://github.com/uglybugger/Add-BindingRedirect/releases"&gt;Add-BindingRedirect releases page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pull requests are welcome :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">configinjector_2_2_is_out</guid><link>http://uglybugger.org/software/post/configinjector_2_2_is_out</link><author>andrewh@uglybugger.org</author><title>ConfigInjector 2.2 is out</title><description>&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 2.2 is out and available via the &lt;a href="nuget.org"&gt;nuget.org&lt;/a&gt; feed.&lt;/p&gt;

&lt;p&gt;This release is a small tweak to allow exclusion of settings keys via expressions as well as via simple strings.
Thanks to &lt;a href="http://damianm.com/"&gt;Damian Maclennan&lt;/a&gt; for this one :).&lt;/p&gt;

&lt;p&gt;To exclude settings keys via exact string matches, as per before:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ConfigurationConfigurator.RegisterConfigurationSettings()
                         .FromAssemblies(ThisAssembly)
                         .RegisterWithContainer(configSetting =&amp;gt; builder.RegisterInstance(configSetting)
                                                                        .AsSelf()
                                                                        .SingleInstance())
                         .ExcludeSettingKeys("DontCareAboutThis", "DontCareAboutThat"))
                         .DoYourThing();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To exclude settings keys via expression matches:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ConfigurationConfigurator.RegisterConfigurationSettings()
                         .FromAssemblies(ThisAssembly)
                         .RegisterWithContainer(configSetting =&amp;gt; builder.RegisterInstance(configSetting)
                                                                        .AsSelf()
                                                                        .SingleInstance())
                         .ExcludeSettingKeys(k =&amp;gt; k.StartsWith("DontCare"))
                         .DoYourThing();
&lt;/code&gt;&lt;/pre&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 06 Sep 2016 11:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/configinjector_2_2_is_out" /><a10:updated>2016-09-06T11:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 2.2 is out and available via the &lt;a href="nuget.org"&gt;nuget.org&lt;/a&gt; feed.&lt;/p&gt;

&lt;p&gt;This release is a small tweak to allow exclusion of settings keys via expressions as well as via simple strings.
Thanks to &lt;a href="http://damianm.com/"&gt;Damian Maclennan&lt;/a&gt; for this one :).&lt;/p&gt;

&lt;p&gt;To exclude settings keys via exact string matches, as per before:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ConfigurationConfigurator.RegisterConfigurationSettings()
                         .FromAssemblies(ThisAssembly)
                         .RegisterWithContainer(configSetting =&amp;gt; builder.RegisterInstance(configSetting)
                                                                        .AsSelf()
                                                                        .SingleInstance())
                         .ExcludeSettingKeys("DontCareAboutThis", "DontCareAboutThat"))
                         .DoYourThing();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To exclude settings keys via expression matches:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ConfigurationConfigurator.RegisterConfigurationSettings()
                         .FromAssemblies(ThisAssembly)
                         .RegisterWithContainer(configSetting =&amp;gt; builder.RegisterInstance(configSetting)
                                                                        .AsSelf()
                                                                        .SingleInstance())
                         .ExcludeSettingKeys(k =&amp;gt; k.StartsWith("DontCare"))
                         .DoYourThing();
&lt;/code&gt;&lt;/pre&gt;
</a10:content></item><item><guid isPermaLink="false">introducing_notdeadyet</guid><link>http://uglybugger.org/software/post/introducing_notdeadyet</link><author>andrewh@uglybugger.org</author><title>Introducing NotDeadYet</title><description>&lt;p&gt;&lt;a href="https://github.com/uglybugger/NotDeadYet"&gt;NotDeadYet&lt;/a&gt; is a simple, lightweight
library to allow you to quickly add a health-checking endpoint to your .NET
application.&lt;/p&gt;

&lt;p&gt;It has integrations for ASP.NET MVC, WebApi and Nancy.&lt;/p&gt;

&lt;h3&gt;Why do I want this?&lt;/h3&gt;

&lt;p&gt;To easily generate something like this: &lt;a href="http://www.uglybugger.org/healthcheck"&gt;http://www.uglybugger.org/healthcheck&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When scaling out a web applications, one of the first pieces of kit encountered is a load balancer. When deploying a new version of application we generally pull one machine out of the load-balanced pool, upgrade it and then put it back into the pool before deploying to the next one.&lt;/p&gt;

&lt;p&gt;NotDeadYet makes it easy to give load balancers a custom endpoint to do health checks. If we monitor just the index page of our application, it's quite likely that we'll put the instance back into the pool before it's properly warmed up. It would be a whole lot nicer if we had an easy way to get the load balancer to wait until, for instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can connect to any databases we need.&lt;/li&gt;
&lt;li&gt;Redis is available.&lt;/li&gt;
&lt;li&gt;We've precompiled any Razor views we care about.&lt;/li&gt;
&lt;li&gt;The CPU on the instance has stopped spiking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NotDeadYet makes it easy to add a &lt;code&gt;/healthcheck&lt;/code&gt; endpoint that will return a 503 until the instance is ready to go, and a 200 once all is well. This plays nicely with New Relic, Amazon's ELB, Pingdom and most other monitoring and load balancing tools.&lt;/p&gt;

&lt;h3&gt;Awesome! How do I get it?&lt;/h3&gt;

&lt;p&gt;Getting the package:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package NotDeadYet
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In your code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(ThisAssembly)
    .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Doing a health check&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;var results = healthChecker.Check();
if (results.Status == HealthCheckStatus.Okay)
{
    // Hooray!
} else {
    // Boo!
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Adding your own, custom health checks:&lt;/h3&gt;

&lt;p&gt;By default, NotDeadYet comes with a single &lt;code&gt;ApplicationIsOnline&lt;/code&gt; health check which just confirms that the application pool is online. Adding your own (which is the point, after all) is trivial. Just add a class that implements the &lt;code&gt;IHealthCheck&lt;/code&gt; interface and off you go.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class NeverCouldGetTheHangOfThursdays : IHealthCheck
{
    public string Description
    {
        get { return "This app doesn't work on Thursdays."; }
    }

    public void Check()
    {
        // Example: just throw if it's a Thursday
        if (DateTimeOffset.Now.DayOfWeek == DayOfWeek.Thursday)
        {
            throw new HealthCheckFailedException("I never could get the hang of Thursdays.");
        }

        // ... otherwise we're fine.
    }

    public void Dispose()
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or a slightly more realistic example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; public class CanConnectToSqlDatabase : IHealthCheck
{
    public string Description
    {
        get { return "Our SQL Server database is available and we can run a simple query on it."; }
    }

    public void Check()
    {
        // We really should be using ConfigInjector here ;)
        var connectionString = ConfigurationManager.ConnectionStrings["MyDatabaseConnectionString"].ConnectionString;

        // Do a really simple query to confirm that the server is up and we can hit our database            
        using (var connection = new SqlConnection(connectionString))
        {
            var command = new SqlCommand("SELECT 1", connection);
            command.ExecuteScalar();
        }
    }

    public void Dispose()
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There's no need to add exception handling in your health check - if it throws, NotDeadYet will catch the exception, wrap it up nicely and report that the health check has failed.&lt;/p&gt;

&lt;h2&gt;Framework integration&lt;/h2&gt;

&lt;h3&gt;Integrating with MVC&lt;/h3&gt;

&lt;p&gt;In your Package Manager Console:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package NotDeadYet.MVC4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, in your RouteConfig.cs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var thisAssembly = typeof (MvcApplication).Assembly;
var notDeadYetAssembly = typeof (IHealthChecker).Assembly;

var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(thisAssembly, notDeadYetAssembly)
    .Build();

routes.RegisterHealthCheck(healthChecker);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Integrating with Nancy&lt;/h3&gt;

&lt;p&gt;In your Package Manager Console:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package NotDeadYet.Nancy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, in your bootstrapper:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var thisAssembly = typeof (Bootstrapper).Assembly;
var notDeadYetAssembly = typeof (IHealthChecker).Assembly;

var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(thisAssembly, notDeadYetAssembly)
    .Build();

container.Register(healthChecker);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;FAQ&lt;/h2&gt;

&lt;h3&gt;How do I query it?&lt;/h3&gt;

&lt;p&gt;Once you've hooked up your integration of choice (currently MVC or Nancy), just point your monitoring tool at &lt;code&gt;/healthcheck&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;If you point a browser at it you'll observe a 200 response if all's well and a 503 if not. This plays nicely with load balancers (yes, including Amazon's Elastic Load Balancer) which, by default, expect a 200 response code from a monitoring endpoint before they'll add an instance to the pool.&lt;/p&gt;

&lt;h3&gt;Does this work with X load balancer?&lt;/h3&gt;

&lt;p&gt;If your load balancer can be configured to expect a 200 response from a monitoring endpoint, then yes :)&lt;/p&gt;

&lt;h3&gt;Can I change the monitoring endpoint?&lt;/h3&gt;

&lt;p&gt;Of course. In MVC land, it looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(typeof(MvcApplication).Assembly)
    .Build();

routes.RegisterHealthCheck(healthChecker, "/someCustomEndpoint");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and in Nancy land it looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HealthCheckNancyModule.EndpointName = "/someCustomEndpoint";
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Does this with with my IoC container of choice?&lt;/h3&gt;

&lt;p&gt;NotDeadYet is designed to work both with and without an IoC container. There's a different configuration method on the &lt;code&gt;HealthCheckerBuilder&lt;/code&gt; class called &lt;code&gt;WithHealthChecks&lt;/code&gt; which takes a &lt;code&gt;Func&amp;lt;IHealthCheck[]&amp;gt;&lt;/code&gt; parameter. This is designed so that you can wire it in to your container like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class HealthCheckModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        base.Load(builder);

        builder.RegisterAssemblyTypes(ThisAssembly, typeof (IHealthCheck).Assembly)
            .Where(t =&amp;gt; t.IsAssignableTo&amp;lt;IHealthCheck&amp;gt;())
            .As&amp;lt;IHealthCheck&amp;gt;()
            .InstancePerDependency();

        builder.Register(CreateHealthChecker)
            .As&amp;lt;IHealthChecker&amp;gt;()
            .SingleInstance();
    }

    private static IHealthChecker CreateHealthChecker(IComponentContext c)
    {
        var componentContext = c.Resolve&amp;lt;IComponentContext&amp;gt;();

        return new HealthCheckerBuilder()
            .WithHealthChecks(componentContext.Resolve&amp;lt;IHealthCheck[]&amp;gt;)
            .WithLogger((ex, message) =&amp;gt; componentContext.Resolve&amp;lt;ILogger&amp;gt;().Error(ex, message))
            .Build();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This example is for Autofac but you can easily see how to hook it up to your container of choice.&lt;/p&gt;

&lt;h3&gt;Why don't the health checks show stack traces when they fail?&lt;/h3&gt;

&lt;p&gt;For the same reason that we usually try to avoid showing a stack trace on an error page.&lt;/p&gt;

&lt;h3&gt;Can I log the stack traces to somewhere else, then?&lt;/h3&gt;

&lt;p&gt;You can wire in any logger you like. In this example below, we're using &lt;a href="http://serilog.net/"&gt;Serilog&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var serilogLogger = new LoggerConfiguration()
    .WriteTo.ColoredConsole()
    .WriteTo.Seq("http://localhost:5341")
    .CreateLogger();

return new HealthCheckerBuilder()
    .WithLogger((ex, message) =&amp;gt; serilogLogger.Error(ex, message))
    .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Do the health checks have a timeout?&lt;/h3&gt;

&lt;p&gt;They do. All the health checks are run in parallel and there is a five-second timeout on all of them.&lt;/p&gt;

&lt;p&gt;You can configure the timeout like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(typeof(MvcApplication).Assembly)
    .WithTimeout(TimeSpan.FromSeconds(10))
    .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;What does the output from the endpoint look like?&lt;/h3&gt;

&lt;p&gt;It's JSON and looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "Status": "Okay",
  "Results": [
    {
      "Status": "Okay",
      "Name": "ApplicationIsRunning",
      "Description": "Checks whether the application is running. If this check can run then it should pass.",
      "ElapsedTime": "00:00:00.0000006"
    },
    {
      "Status": "Okay",
      "Name": "RssFeedsHealthCheck",
      "Description": "RSS feeds are available and have non-zero items.",
      "ElapsedTime": "00:00:00.0005336"
    }
  ],
  "Message": "All okay",
  "Timestamp": "2015-11-14T11:42:35.3040908+00:00",
  "NotDeadYet": "0.0.10.0"
}
&lt;/code&gt;&lt;/pre&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sat, 02 Apr 2016 10:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/introducing_notdeadyet" /><a10:updated>2016-04-02T10:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;&lt;a href="https://github.com/uglybugger/NotDeadYet"&gt;NotDeadYet&lt;/a&gt; is a simple, lightweight
library to allow you to quickly add a health-checking endpoint to your .NET
application.&lt;/p&gt;

&lt;p&gt;It has integrations for ASP.NET MVC, WebApi and Nancy.&lt;/p&gt;

&lt;h3&gt;Why do I want this?&lt;/h3&gt;

&lt;p&gt;To easily generate something like this: &lt;a href="http://www.uglybugger.org/healthcheck"&gt;http://www.uglybugger.org/healthcheck&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When scaling out a web applications, one of the first pieces of kit encountered is a load balancer. When deploying a new version of application we generally pull one machine out of the load-balanced pool, upgrade it and then put it back into the pool before deploying to the next one.&lt;/p&gt;

&lt;p&gt;NotDeadYet makes it easy to give load balancers a custom endpoint to do health checks. If we monitor just the index page of our application, it's quite likely that we'll put the instance back into the pool before it's properly warmed up. It would be a whole lot nicer if we had an easy way to get the load balancer to wait until, for instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can connect to any databases we need.&lt;/li&gt;
&lt;li&gt;Redis is available.&lt;/li&gt;
&lt;li&gt;We've precompiled any Razor views we care about.&lt;/li&gt;
&lt;li&gt;The CPU on the instance has stopped spiking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NotDeadYet makes it easy to add a &lt;code&gt;/healthcheck&lt;/code&gt; endpoint that will return a 503 until the instance is ready to go, and a 200 once all is well. This plays nicely with New Relic, Amazon's ELB, Pingdom and most other monitoring and load balancing tools.&lt;/p&gt;

&lt;h3&gt;Awesome! How do I get it?&lt;/h3&gt;

&lt;p&gt;Getting the package:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package NotDeadYet
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In your code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(ThisAssembly)
    .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Doing a health check&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;var results = healthChecker.Check();
if (results.Status == HealthCheckStatus.Okay)
{
    // Hooray!
} else {
    // Boo!
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Adding your own, custom health checks:&lt;/h3&gt;

&lt;p&gt;By default, NotDeadYet comes with a single &lt;code&gt;ApplicationIsOnline&lt;/code&gt; health check which just confirms that the application pool is online. Adding your own (which is the point, after all) is trivial. Just add a class that implements the &lt;code&gt;IHealthCheck&lt;/code&gt; interface and off you go.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class NeverCouldGetTheHangOfThursdays : IHealthCheck
{
    public string Description
    {
        get { return "This app doesn't work on Thursdays."; }
    }

    public void Check()
    {
        // Example: just throw if it's a Thursday
        if (DateTimeOffset.Now.DayOfWeek == DayOfWeek.Thursday)
        {
            throw new HealthCheckFailedException("I never could get the hang of Thursdays.");
        }

        // ... otherwise we're fine.
    }

    public void Dispose()
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or a slightly more realistic example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; public class CanConnectToSqlDatabase : IHealthCheck
{
    public string Description
    {
        get { return "Our SQL Server database is available and we can run a simple query on it."; }
    }

    public void Check()
    {
        // We really should be using ConfigInjector here ;)
        var connectionString = ConfigurationManager.ConnectionStrings["MyDatabaseConnectionString"].ConnectionString;

        // Do a really simple query to confirm that the server is up and we can hit our database            
        using (var connection = new SqlConnection(connectionString))
        {
            var command = new SqlCommand("SELECT 1", connection);
            command.ExecuteScalar();
        }
    }

    public void Dispose()
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There's no need to add exception handling in your health check - if it throws, NotDeadYet will catch the exception, wrap it up nicely and report that the health check has failed.&lt;/p&gt;

&lt;h2&gt;Framework integration&lt;/h2&gt;

&lt;h3&gt;Integrating with MVC&lt;/h3&gt;

&lt;p&gt;In your Package Manager Console:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package NotDeadYet.MVC4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, in your RouteConfig.cs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var thisAssembly = typeof (MvcApplication).Assembly;
var notDeadYetAssembly = typeof (IHealthChecker).Assembly;

var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(thisAssembly, notDeadYetAssembly)
    .Build();

routes.RegisterHealthCheck(healthChecker);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Integrating with Nancy&lt;/h3&gt;

&lt;p&gt;In your Package Manager Console:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package NotDeadYet.Nancy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then, in your bootstrapper:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var thisAssembly = typeof (Bootstrapper).Assembly;
var notDeadYetAssembly = typeof (IHealthChecker).Assembly;

var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(thisAssembly, notDeadYetAssembly)
    .Build();

container.Register(healthChecker);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;FAQ&lt;/h2&gt;

&lt;h3&gt;How do I query it?&lt;/h3&gt;

&lt;p&gt;Once you've hooked up your integration of choice (currently MVC or Nancy), just point your monitoring tool at &lt;code&gt;/healthcheck&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;If you point a browser at it you'll observe a 200 response if all's well and a 503 if not. This plays nicely with load balancers (yes, including Amazon's Elastic Load Balancer) which, by default, expect a 200 response code from a monitoring endpoint before they'll add an instance to the pool.&lt;/p&gt;

&lt;h3&gt;Does this work with X load balancer?&lt;/h3&gt;

&lt;p&gt;If your load balancer can be configured to expect a 200 response from a monitoring endpoint, then yes :)&lt;/p&gt;

&lt;h3&gt;Can I change the monitoring endpoint?&lt;/h3&gt;

&lt;p&gt;Of course. In MVC land, it looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(typeof(MvcApplication).Assembly)
    .Build();

routes.RegisterHealthCheck(healthChecker, "/someCustomEndpoint");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and in Nancy land it looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HealthCheckNancyModule.EndpointName = "/someCustomEndpoint";
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Does this with with my IoC container of choice?&lt;/h3&gt;

&lt;p&gt;NotDeadYet is designed to work both with and without an IoC container. There's a different configuration method on the &lt;code&gt;HealthCheckerBuilder&lt;/code&gt; class called &lt;code&gt;WithHealthChecks&lt;/code&gt; which takes a &lt;code&gt;Func&amp;lt;IHealthCheck[]&amp;gt;&lt;/code&gt; parameter. This is designed so that you can wire it in to your container like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class HealthCheckModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        base.Load(builder);

        builder.RegisterAssemblyTypes(ThisAssembly, typeof (IHealthCheck).Assembly)
            .Where(t =&amp;gt; t.IsAssignableTo&amp;lt;IHealthCheck&amp;gt;())
            .As&amp;lt;IHealthCheck&amp;gt;()
            .InstancePerDependency();

        builder.Register(CreateHealthChecker)
            .As&amp;lt;IHealthChecker&amp;gt;()
            .SingleInstance();
    }

    private static IHealthChecker CreateHealthChecker(IComponentContext c)
    {
        var componentContext = c.Resolve&amp;lt;IComponentContext&amp;gt;();

        return new HealthCheckerBuilder()
            .WithHealthChecks(componentContext.Resolve&amp;lt;IHealthCheck[]&amp;gt;)
            .WithLogger((ex, message) =&amp;gt; componentContext.Resolve&amp;lt;ILogger&amp;gt;().Error(ex, message))
            .Build();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This example is for Autofac but you can easily see how to hook it up to your container of choice.&lt;/p&gt;

&lt;h3&gt;Why don't the health checks show stack traces when they fail?&lt;/h3&gt;

&lt;p&gt;For the same reason that we usually try to avoid showing a stack trace on an error page.&lt;/p&gt;

&lt;h3&gt;Can I log the stack traces to somewhere else, then?&lt;/h3&gt;

&lt;p&gt;You can wire in any logger you like. In this example below, we're using &lt;a href="http://serilog.net/"&gt;Serilog&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var serilogLogger = new LoggerConfiguration()
    .WriteTo.ColoredConsole()
    .WriteTo.Seq("http://localhost:5341")
    .CreateLogger();

return new HealthCheckerBuilder()
    .WithLogger((ex, message) =&amp;gt; serilogLogger.Error(ex, message))
    .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Do the health checks have a timeout?&lt;/h3&gt;

&lt;p&gt;They do. All the health checks are run in parallel and there is a five-second timeout on all of them.&lt;/p&gt;

&lt;p&gt;You can configure the timeout like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var healthChecker = new HealthCheckerBuilder()
    .WithHealthChecksFromAssemblies(typeof(MvcApplication).Assembly)
    .WithTimeout(TimeSpan.FromSeconds(10))
    .Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;What does the output from the endpoint look like?&lt;/h3&gt;

&lt;p&gt;It's JSON and looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "Status": "Okay",
  "Results": [
    {
      "Status": "Okay",
      "Name": "ApplicationIsRunning",
      "Description": "Checks whether the application is running. If this check can run then it should pass.",
      "ElapsedTime": "00:00:00.0000006"
    },
    {
      "Status": "Okay",
      "Name": "RssFeedsHealthCheck",
      "Description": "RSS feeds are available and have non-zero items.",
      "ElapsedTime": "00:00:00.0005336"
    }
  ],
  "Message": "All okay",
  "Timestamp": "2015-11-14T11:42:35.3040908+00:00",
  "NotDeadYet": "0.0.10.0"
}
&lt;/code&gt;&lt;/pre&gt;
</a10:content></item><item><guid isPermaLink="false">sensitive_setting_support_in_configinjector</guid><link>http://uglybugger.org/software/post/sensitive_setting_support_in_configinjector</link><author>andrewh@uglybugger.org</author><title>Sensitive setting support in ConfigInjector</title><description>&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 2.1 has been released with support for sensitive settings.&lt;/p&gt;

&lt;p&gt;This is a pretty simple feature: if you have a sensitive setting and want to be cautious about logging it or otherwise
writing it to an insecure location, you can now flag it as &lt;code&gt;IsSensitive&lt;/code&gt; and optionally override the &lt;code&gt;SanitizedValue&lt;/code&gt;
property.&lt;/p&gt;

&lt;p&gt;If you just want to mark a setting as sensitive, just override the &lt;code&gt;IsSensitive&lt;/code&gt; property to return true. This will
allow you to make your own judgements in your own code as to how you should deal with that setting. You can, of course,
still choose to log it - it's just an advisory property.&lt;/p&gt;

&lt;p&gt;If you want to be a bit more serious, you can also override the &lt;code&gt;SanitizedValue&lt;/code&gt; property to return a sanitized version
of the value. By default, if you're logging settings to anywhere you should log the &lt;code&gt;SanitizedValue&lt;/code&gt; property rather than
just the &lt;code&gt;Value&lt;/code&gt; one.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class FooApiKey: ConfigurationSetting&amp;lt;string&amp;gt;
{
    public override bool IsSensitive =&amp;gt; true;

    public override string SanitizedValue =&amp;gt; "********";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's worth noting that &lt;em&gt;these properties do not change the behaviour of ConfigInjector&lt;/em&gt;; they simply allow us to be a bit more
judicious when we're dealing with these settings.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Wed, 30 Mar 2016 10:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/sensitive_setting_support_in_configinjector" /><a10:updated>2016-03-30T10:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 2.1 has been released with support for sensitive settings.&lt;/p&gt;

&lt;p&gt;This is a pretty simple feature: if you have a sensitive setting and want to be cautious about logging it or otherwise
writing it to an insecure location, you can now flag it as &lt;code&gt;IsSensitive&lt;/code&gt; and optionally override the &lt;code&gt;SanitizedValue&lt;/code&gt;
property.&lt;/p&gt;

&lt;p&gt;If you just want to mark a setting as sensitive, just override the &lt;code&gt;IsSensitive&lt;/code&gt; property to return true. This will
allow you to make your own judgements in your own code as to how you should deal with that setting. You can, of course,
still choose to log it - it's just an advisory property.&lt;/p&gt;

&lt;p&gt;If you want to be a bit more serious, you can also override the &lt;code&gt;SanitizedValue&lt;/code&gt; property to return a sanitized version
of the value. By default, if you're logging settings to anywhere you should log the &lt;code&gt;SanitizedValue&lt;/code&gt; property rather than
just the &lt;code&gt;Value&lt;/code&gt; one.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class FooApiKey: ConfigurationSetting&amp;lt;string&amp;gt;
{
    public override bool IsSensitive =&amp;gt; true;

    public override string SanitizedValue =&amp;gt; "********";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's worth noting that &lt;em&gt;these properties do not change the behaviour of ConfigInjector&lt;/em&gt;; they simply allow us to be a bit more
judicious when we're dealing with these settings.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">talk_video_back_to_basics_simple_elegant_beautiful_code</guid><link>http://uglybugger.org/software/post/talk_video_back_to_basics_simple_elegant_beautiful_code</link><author>andrewh@uglybugger.org</author><title>Talk video: Back to basics: simple, elegant, beautiful code</title><description>&lt;p&gt;This is the video of the talk I gave at DDD Brisbane 2015.&lt;/p&gt;

&lt;p&gt;As a consultant I see so many companies using the latest and greatest buzzwords, forking out
staggering amounts of cash for hardware and tooling and generally throwing anything they can
at the wall to see what sticks. The problem? Their teams still struggle to produce high-quality
output and are often incurring unsustainable technical debt. Codebases are still impossible to
navigate and there's always that underlying dread that one day soon someone is going to
discover what a mess everything is.&lt;/p&gt;

&lt;p&gt;How can this happen? It wasn't supposed to be this hard! Don't we all know all this stuff by now?&lt;/p&gt;

&lt;p&gt;Let's take a look at some patterns and practices to reduce the cognitive load of navigating a
codebase, maintaining existing features and adding new ones, and all while shipping high-quality
products. Fast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=h9AZJflsbvw"&gt;&lt;img alt="Back to basics: simple, elegant, beautiful code" src="https://img.youtube.com/vi/h9AZJflsbvw/maxresdefault.jpg" class="img-responsive" /&gt;&lt;/a&gt;&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Fri, 25 Mar 2016 10:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/talk_video_back_to_basics_simple_elegant_beautiful_code" /><a10:link rel="image" href="https://img.youtube.com/vi/h9AZJflsbvw/maxresdefault.jpg" /><a10:updated>2016-03-25T10:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;This is the video of the talk I gave at DDD Brisbane 2015.&lt;/p&gt;

&lt;p&gt;As a consultant I see so many companies using the latest and greatest buzzwords, forking out
staggering amounts of cash for hardware and tooling and generally throwing anything they can
at the wall to see what sticks. The problem? Their teams still struggle to produce high-quality
output and are often incurring unsustainable technical debt. Codebases are still impossible to
navigate and there's always that underlying dread that one day soon someone is going to
discover what a mess everything is.&lt;/p&gt;

&lt;p&gt;How can this happen? It wasn't supposed to be this hard! Don't we all know all this stuff by now?&lt;/p&gt;

&lt;p&gt;Let's take a look at some patterns and practices to reduce the cognitive load of navigating a
codebase, maintaining existing features and adding new ones, and all while shipping high-quality
products. Fast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=h9AZJflsbvw"&gt;&lt;img alt="Back to basics: simple, elegant, beautiful code" src="https://img.youtube.com/vi/h9AZJflsbvw/maxresdefault.jpg" class="img-responsive" /&gt;&lt;/a&gt;&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">whats_new_in_configinjector_2_0</guid><link>http://uglybugger.org/software/post/whats_new_in_configinjector_2_0</link><author>andrewh@uglybugger.org</author><title>What's new in ConfigInjector 2.0</title><description>&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 2.0 has hit the NuGet feed.&lt;/p&gt;

&lt;p&gt;What's new? A handful of things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for overriding settings via environment variables (useful for regression suites on build servers).&lt;/li&gt;
&lt;li&gt;Support for loading settings from existing objects.&lt;/li&gt;
&lt;li&gt;Logging hooks to allow callers to record where settings were loaded from and what their values were.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are some breaking changes with respect to namespaces so it's a major version bump but unless you're doing
anything really custom it should still be a straight-forward upgrade.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Mon, 14 Dec 2015 10:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/whats_new_in_configinjector_2_0" /><a10:updated>2015-12-14T10:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 2.0 has hit the NuGet feed.&lt;/p&gt;

&lt;p&gt;What's new? A handful of things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for overriding settings via environment variables (useful for regression suites on build servers).&lt;/li&gt;
&lt;li&gt;Support for loading settings from existing objects.&lt;/li&gt;
&lt;li&gt;Logging hooks to allow callers to record where settings were loaded from and what their values were.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are some breaking changes with respect to namespaces so it's a major version bump but unless you're doing
anything really custom it should still be a straight-forward upgrade.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">building_tweets_from_the_vault_twitter_oauth</guid><link>http://uglybugger.org/software/post/building_tweets_from_the_vault_twitter_oauth</link><author>andrewh@uglybugger.org</author><title>Building Tweets from the Vault: Twitter OAuth</title><description>&lt;p&gt;In &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_nancyfx_tips_and_tricks"&gt;Building Tweets from the Vault: NancyFX tips and tricks&lt;/a&gt; we took
a look at some of the refactoring-friendly approaches we can take when building a NancyFX application.&lt;/p&gt;

&lt;p&gt;In this post we'll see a very simple example of how Tweets from the Vault uses Twitter and &lt;a href="https://tweetinvi.codeplex.com/"&gt;Tweetinvi&lt;/a&gt;, a
nice-to-call .NET library for Twitter. Tweetinvi has a whole lot more features than authentication but authentication in general is the
main focus of this post, so here goes.&lt;/p&gt;

&lt;p&gt;I'll state in advance that this advice only briefly touches upon some really elementary application security. I'll write
a bit more about that in subsequent posts but please don't treat this advice as anything other than a few brief pointers
on the most basic of things. Do your homework. This stuff is important.&lt;/p&gt;

&lt;h1&gt;Requiring authentication in NancyFX&lt;/h1&gt;

&lt;p&gt;To begin with, our Nancy application has a base module class from which almost all others derive:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public abstract class AuthenticatedModule : RoutedModule
{
    protected AuthenticatedModule()
    {
        this.RequiresAuthentication();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our AuthenticatedModule just demands authentication and leaves everything else to its derived classes. It's worth noting that there's also a convention test
(which we'll discuss in another post) that asserts that &lt;em&gt;every single module&lt;/em&gt; in the app must explicitly derive from either AuthenticatedModule or
UnauthenticatedModule so as to leave no room for "Oh, I forgot to set the security on that one."&lt;/p&gt;

&lt;p&gt;In Tweets from the Vault, we're using NancyFX's StatelessAuthentication hook. We actually add an item to the request pipeline to check for 401 responses and
send a redirect. In this way, our individual modules can just demand an authenticated user and return a 401 if not. It's up to the rest of our pipeline to
figure out that we should probably present a kinder response.&lt;/p&gt;

&lt;p&gt;In our bootstrapper:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected override void ApplicationStartup(ILifetimeScope container, IPipelines pipelines)
{
    ConfigureLogging(container);
    using (Log.Logger.BeginTimedOperation("Application starting"))
    {
        // A bunch of irrelevant stuff elided here
        ConfigureAuth(pipelines);
    }
}

private static void ConfigureAuth(IPipelines pipelines)
{
    // Yes, we're using the container as a service locator here. We're resolving
    // a .SingleInstance component once in a bootstrapper so I'm okay with that.
    var authenticator = IoC.Container.Resolve&amp;lt;Authenticator&amp;gt;();

    StatelessAuthentication.Enable(pipelines,
                                   new StatelessAuthenticationConfiguration(authenticator.Authenticate));

    pipelines.AfterRequest.AddItemToEndOfPipeline(ctx =&amp;gt;
    {
        if (ctx.Response.StatusCode == HttpStatusCode.Unauthorized)
        {
            var response = new RedirectResponse(Route.For&amp;lt;SignIn&amp;gt;());
            ctx.Response = response;
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's have a look at what this is doing. We can see that the item is being added to the &lt;em&gt;end&lt;/em&gt; of the pipeline. That means that it will be executed
after our module has done its thing and returned. If the module does an early exit and returns a 401, that will be observable in
ctx.Response.StatusCode and we'll mess with it; otherwise we'll just pass the response straight through.&lt;/p&gt;

&lt;p&gt;If we've observed a 401, we clobber the 401 response with a 302 and bounce the user back to the SignIn page using the Route.For expression that
we looked at in &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_nancyfx_tips_and_tricks"&gt;Building Tweets from the Vault: NancyFX tips and tricks&lt;/a&gt;.
It's noteworthy that the browser will never see a 401; just a 302.&lt;/p&gt;

&lt;h1&gt;What about Twitter and OAuth?&lt;/h1&gt;

&lt;p&gt;The assumption I'm making here is that you'll actually want to do something on behalf of a user using the Twitter API. That's pretty obvious as
it's what Tweets from the Vault does, but I'm going to state up-front: if all you want is an identity via OAuth, this is a harder way to do it
than you need. If you want API access, however, then read on.&lt;/p&gt;

&lt;p&gt;The first thing you'll need is an application on Twitter. Go to &lt;a href="https://apps.twitter.com/"&gt;apps.twitter.com&lt;/a&gt; to create one.&lt;/p&gt;

&lt;p&gt;The next thing you'll need is an x.509 certificate. You'll be telling Twitter to pass keys to access other people's accounts via
GET parameters, so don't be sending those around the place in plaintext. Incidentally, Twitter &lt;em&gt;does&lt;/em&gt; support localhost as a valid
redirect URL target, so you'll be fine for your own testing. Just make sure that you never present a sign-in/sign-up page other than
via HTTPS, and likewise make sure your callback URL is HTTPS as well.&lt;/p&gt;

&lt;p&gt;You'll also want the Tweetinvi package:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package Tweetinvi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once we've hit our SignIn page, it creates a Twitter sign-in credentials bundle using Tweetinvi. This isn't &lt;em&gt;exactly&lt;/em&gt; the code in Tweets from the Vault
as there are a few abstractions here and there - I've inlined a few things - but it's pretty close. In our SignIn module:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// You'll want to stash these somehow as there's a single-use token in there
// that you'll need to decode the response.
var temporaryCredentials = TwitterCredentials.CreateCredentials(userAccessToken,
                                                                userAccessSecret,
                                                                _twitterConsumerKey,
                                                                _twitterConsumerSecret);
var authenticationUrl = CredentialsCreator.GetAuthorizationURLForCallback(temporaryCredentials, redirectUrl);

// Hack because the Tweetinvi library doesn't seem to support just authentication - it wants to make an
// authorize call all the time. This will happen anyway on the first time someone uses your app but
// forever after an authenticate call will just bounce straight back whereas an authorize call will
// continue to prompt.
authenticationUrl = authenticationUrl.Replace("oauth/authorize", "oauth/authenticate");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We redirect the user to that authenticationUrl, which will be somewhere on twitter.com, and Twitter will present them with an "Authorize this App" page.&lt;/p&gt;

&lt;p&gt;Then, in our SignInCallback module:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var temporaryCredentials = /* fetch these from wherever you stashed them */
var userCredentials = CredentialsCreator.GetCredentialsFromCallbackURL(callbackUrl, temporaryCredentials);
var twitterUser = User.GetLoggedUser(userCredentials);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point, we have a valid Twitter user who's been verified for us by Twitter (thank you :) ) We'll also have a set of keys to allow us to make
API calls as that user to the extent permitted by the privileges that your app was granted by the user.&lt;/p&gt;

&lt;p&gt;Of course, if the user declines to authorise the Twitter app to use their account then you'll get back a different
response. Be sure to handle that.&lt;/p&gt;

&lt;h1&gt;Now what?&lt;/h1&gt;

&lt;p&gt;Now we have a user who's just presented us with a valid set of callback tokens from Twitter via a redirect URL. That's nice, but we shouldn't be leaving
those lying around. What we should be doing is generating our own authentication token of some sort and sending that back as a cookie. (Remember to
give people some way to destroy that cookie once they leave a machine, too - you need a "Sign out" button[1]!)&lt;/p&gt;

&lt;p&gt;A good way to do this is using a JSON Web Token or similar. There are a bunch of libraries (and opinions) out there on The One True Way&amp;trade; to do it
but the general principle is roughly the same as HTTP cookies: you shove a bunch of claims into a JSON object, sign it and give it to the browser. When
it makes a request it can supply that via a cookie.&lt;/p&gt;

&lt;p&gt;The JWT standard doesn't specify encryption - it's about sending information in plaintext but making it verifiable. That said, if you don't have to
inter-operate with anyone else (i.e. you're just doing your own sign-on, not implementing SSO across a group of sites) then go ahead and encrypt it.
It will help prevent other people stickybeaking into what you've bundled into there but still let you use someone else's library code rather than
hand-rolling your own. It should go without saying[2] that if you're going to put any sensitive information into it then 1) have a careful think
about whether you actually need to do that, and 2) make sure you're using a reputable encryption algorithm with a decent-length key.&lt;/p&gt;

&lt;p&gt;Using this approach you can put pretty much anything into your token. As a general rule, I'd like to be able to load a page and only hit
persistent storage for data specific to that page. Loading a user's name, profile picture URL or anything else that is part of the ambient
experience goes into the encrypted token. This means that I can render most pages without hitting a dbo.Users or similar. The token doesn't
need to be readable by anyone else but it does need to be relatively small as it's going to be transmitted by the browser on every request.
Also think about what you'll do in the case of wanting to disable a user account - if you're not checking dbo.Users every request then how
will you know to return a 403?&lt;/p&gt;

&lt;p&gt;Be sensible. Don't create another ViewState. Don't treat it like session state[3].&lt;/p&gt;

&lt;h1&gt;So we're done?&lt;/h1&gt;

&lt;p&gt;Not quite. You'll probably want to create your own representation of a user once you have a confirmed Twitter identifier. I'd also use the Twitter
64-bit int as your foreign key, not the username, as that may well change.&lt;/p&gt;

&lt;p&gt;It's worth bearing in mind that Twitter's OAuth solution &lt;em&gt;does not provide users' email addresses&lt;/em&gt; so that's something you'll have to either request
for yourself or live without. That's up to you :) Likewise, we're relying on Twitter's anti-spam measures to prevent malicious sign-ups. That's
not unreasonable in the first instance but don't expect it to be perfect.&lt;/p&gt;

&lt;p&gt;In the next post in this series, we'll take a look at some interesting domain event modelling as part of implementing payments using Stripe.&lt;/p&gt;

&lt;p&gt;[1] And it should generate a POST request, not a GET one, but that's a story for another day.&lt;/p&gt;

&lt;p&gt;[2] Hence, of course, needing to say it...&lt;/p&gt;

&lt;p&gt;[3] An evil to be discussed some other time...&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sun, 01 Feb 2015 21:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/building_tweets_from_the_vault_twitter_oauth" /><a10:updated>2015-02-01T21:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;In &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_nancyfx_tips_and_tricks"&gt;Building Tweets from the Vault: NancyFX tips and tricks&lt;/a&gt; we took
a look at some of the refactoring-friendly approaches we can take when building a NancyFX application.&lt;/p&gt;

&lt;p&gt;In this post we'll see a very simple example of how Tweets from the Vault uses Twitter and &lt;a href="https://tweetinvi.codeplex.com/"&gt;Tweetinvi&lt;/a&gt;, a
nice-to-call .NET library for Twitter. Tweetinvi has a whole lot more features than authentication but authentication in general is the
main focus of this post, so here goes.&lt;/p&gt;

&lt;p&gt;I'll state in advance that this advice only briefly touches upon some really elementary application security. I'll write
a bit more about that in subsequent posts but please don't treat this advice as anything other than a few brief pointers
on the most basic of things. Do your homework. This stuff is important.&lt;/p&gt;

&lt;h1&gt;Requiring authentication in NancyFX&lt;/h1&gt;

&lt;p&gt;To begin with, our Nancy application has a base module class from which almost all others derive:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public abstract class AuthenticatedModule : RoutedModule
{
    protected AuthenticatedModule()
    {
        this.RequiresAuthentication();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our AuthenticatedModule just demands authentication and leaves everything else to its derived classes. It's worth noting that there's also a convention test
(which we'll discuss in another post) that asserts that &lt;em&gt;every single module&lt;/em&gt; in the app must explicitly derive from either AuthenticatedModule or
UnauthenticatedModule so as to leave no room for "Oh, I forgot to set the security on that one."&lt;/p&gt;

&lt;p&gt;In Tweets from the Vault, we're using NancyFX's StatelessAuthentication hook. We actually add an item to the request pipeline to check for 401 responses and
send a redirect. In this way, our individual modules can just demand an authenticated user and return a 401 if not. It's up to the rest of our pipeline to
figure out that we should probably present a kinder response.&lt;/p&gt;

&lt;p&gt;In our bootstrapper:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protected override void ApplicationStartup(ILifetimeScope container, IPipelines pipelines)
{
    ConfigureLogging(container);
    using (Log.Logger.BeginTimedOperation("Application starting"))
    {
        // A bunch of irrelevant stuff elided here
        ConfigureAuth(pipelines);
    }
}

private static void ConfigureAuth(IPipelines pipelines)
{
    // Yes, we're using the container as a service locator here. We're resolving
    // a .SingleInstance component once in a bootstrapper so I'm okay with that.
    var authenticator = IoC.Container.Resolve&amp;lt;Authenticator&amp;gt;();

    StatelessAuthentication.Enable(pipelines,
                                   new StatelessAuthenticationConfiguration(authenticator.Authenticate));

    pipelines.AfterRequest.AddItemToEndOfPipeline(ctx =&amp;gt;
    {
        if (ctx.Response.StatusCode == HttpStatusCode.Unauthorized)
        {
            var response = new RedirectResponse(Route.For&amp;lt;SignIn&amp;gt;());
            ctx.Response = response;
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's have a look at what this is doing. We can see that the item is being added to the &lt;em&gt;end&lt;/em&gt; of the pipeline. That means that it will be executed
after our module has done its thing and returned. If the module does an early exit and returns a 401, that will be observable in
ctx.Response.StatusCode and we'll mess with it; otherwise we'll just pass the response straight through.&lt;/p&gt;

&lt;p&gt;If we've observed a 401, we clobber the 401 response with a 302 and bounce the user back to the SignIn page using the Route.For expression that
we looked at in &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_nancyfx_tips_and_tricks"&gt;Building Tweets from the Vault: NancyFX tips and tricks&lt;/a&gt;.
It's noteworthy that the browser will never see a 401; just a 302.&lt;/p&gt;

&lt;h1&gt;What about Twitter and OAuth?&lt;/h1&gt;

&lt;p&gt;The assumption I'm making here is that you'll actually want to do something on behalf of a user using the Twitter API. That's pretty obvious as
it's what Tweets from the Vault does, but I'm going to state up-front: if all you want is an identity via OAuth, this is a harder way to do it
than you need. If you want API access, however, then read on.&lt;/p&gt;

&lt;p&gt;The first thing you'll need is an application on Twitter. Go to &lt;a href="https://apps.twitter.com/"&gt;apps.twitter.com&lt;/a&gt; to create one.&lt;/p&gt;

&lt;p&gt;The next thing you'll need is an x.509 certificate. You'll be telling Twitter to pass keys to access other people's accounts via
GET parameters, so don't be sending those around the place in plaintext. Incidentally, Twitter &lt;em&gt;does&lt;/em&gt; support localhost as a valid
redirect URL target, so you'll be fine for your own testing. Just make sure that you never present a sign-in/sign-up page other than
via HTTPS, and likewise make sure your callback URL is HTTPS as well.&lt;/p&gt;

&lt;p&gt;You'll also want the Tweetinvi package:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package Tweetinvi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once we've hit our SignIn page, it creates a Twitter sign-in credentials bundle using Tweetinvi. This isn't &lt;em&gt;exactly&lt;/em&gt; the code in Tweets from the Vault
as there are a few abstractions here and there - I've inlined a few things - but it's pretty close. In our SignIn module:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// You'll want to stash these somehow as there's a single-use token in there
// that you'll need to decode the response.
var temporaryCredentials = TwitterCredentials.CreateCredentials(userAccessToken,
                                                                userAccessSecret,
                                                                _twitterConsumerKey,
                                                                _twitterConsumerSecret);
var authenticationUrl = CredentialsCreator.GetAuthorizationURLForCallback(temporaryCredentials, redirectUrl);

// Hack because the Tweetinvi library doesn't seem to support just authentication - it wants to make an
// authorize call all the time. This will happen anyway on the first time someone uses your app but
// forever after an authenticate call will just bounce straight back whereas an authorize call will
// continue to prompt.
authenticationUrl = authenticationUrl.Replace("oauth/authorize", "oauth/authenticate");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We redirect the user to that authenticationUrl, which will be somewhere on twitter.com, and Twitter will present them with an "Authorize this App" page.&lt;/p&gt;

&lt;p&gt;Then, in our SignInCallback module:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var temporaryCredentials = /* fetch these from wherever you stashed them */
var userCredentials = CredentialsCreator.GetCredentialsFromCallbackURL(callbackUrl, temporaryCredentials);
var twitterUser = User.GetLoggedUser(userCredentials);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point, we have a valid Twitter user who's been verified for us by Twitter (thank you :) ) We'll also have a set of keys to allow us to make
API calls as that user to the extent permitted by the privileges that your app was granted by the user.&lt;/p&gt;

&lt;p&gt;Of course, if the user declines to authorise the Twitter app to use their account then you'll get back a different
response. Be sure to handle that.&lt;/p&gt;

&lt;h1&gt;Now what?&lt;/h1&gt;

&lt;p&gt;Now we have a user who's just presented us with a valid set of callback tokens from Twitter via a redirect URL. That's nice, but we shouldn't be leaving
those lying around. What we should be doing is generating our own authentication token of some sort and sending that back as a cookie. (Remember to
give people some way to destroy that cookie once they leave a machine, too - you need a "Sign out" button[1]!)&lt;/p&gt;

&lt;p&gt;A good way to do this is using a JSON Web Token or similar. There are a bunch of libraries (and opinions) out there on The One True Way&amp;trade; to do it
but the general principle is roughly the same as HTTP cookies: you shove a bunch of claims into a JSON object, sign it and give it to the browser. When
it makes a request it can supply that via a cookie.&lt;/p&gt;

&lt;p&gt;The JWT standard doesn't specify encryption - it's about sending information in plaintext but making it verifiable. That said, if you don't have to
inter-operate with anyone else (i.e. you're just doing your own sign-on, not implementing SSO across a group of sites) then go ahead and encrypt it.
It will help prevent other people stickybeaking into what you've bundled into there but still let you use someone else's library code rather than
hand-rolling your own. It should go without saying[2] that if you're going to put any sensitive information into it then 1) have a careful think
about whether you actually need to do that, and 2) make sure you're using a reputable encryption algorithm with a decent-length key.&lt;/p&gt;

&lt;p&gt;Using this approach you can put pretty much anything into your token. As a general rule, I'd like to be able to load a page and only hit
persistent storage for data specific to that page. Loading a user's name, profile picture URL or anything else that is part of the ambient
experience goes into the encrypted token. This means that I can render most pages without hitting a dbo.Users or similar. The token doesn't
need to be readable by anyone else but it does need to be relatively small as it's going to be transmitted by the browser on every request.
Also think about what you'll do in the case of wanting to disable a user account - if you're not checking dbo.Users every request then how
will you know to return a 403?&lt;/p&gt;

&lt;p&gt;Be sensible. Don't create another ViewState. Don't treat it like session state[3].&lt;/p&gt;

&lt;h1&gt;So we're done?&lt;/h1&gt;

&lt;p&gt;Not quite. You'll probably want to create your own representation of a user once you have a confirmed Twitter identifier. I'd also use the Twitter
64-bit int as your foreign key, not the username, as that may well change.&lt;/p&gt;

&lt;p&gt;It's worth bearing in mind that Twitter's OAuth solution &lt;em&gt;does not provide users' email addresses&lt;/em&gt; so that's something you'll have to either request
for yourself or live without. That's up to you :) Likewise, we're relying on Twitter's anti-spam measures to prevent malicious sign-ups. That's
not unreasonable in the first instance but don't expect it to be perfect.&lt;/p&gt;

&lt;p&gt;In the next post in this series, we'll take a look at some interesting domain event modelling as part of implementing payments using Stripe.&lt;/p&gt;

&lt;p&gt;[1] And it should generate a POST request, not a GET one, but that's a story for another day.&lt;/p&gt;

&lt;p&gt;[2] Hence, of course, needing to say it...&lt;/p&gt;

&lt;p&gt;[3] An evil to be discussed some other time...&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">building_tweets_from_the_vault_nancyfx_tips_and_tricks</guid><link>http://uglybugger.org/software/post/building_tweets_from_the_vault_nancyfx_tips_and_tricks</link><author>andrewh@uglybugger.org</author><title>Building Tweets from the Vault: NancyFX tips and tricks</title><description>&lt;p&gt;In &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_azure_teamcity_and_octopus"&gt;Building Tweets from the Vault: Azure, TeamCity and Octopus&lt;/a&gt;, I wrote about the hosting and infrastructure
choices I made for &lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt;. This article will cover a bit more
about the framework choices, notably NancyFX.&lt;/p&gt;

&lt;h1&gt;NancyFX&lt;/h1&gt;

&lt;p&gt;NancyFX may sound like a bit more of an esoteric choice, especially to the Microsoft-or-die crowd. I've been having a pretty
fair amount of success with Nancy, however. I love the way that it just gets out of the road and provides a close-to-the-metal
experience for the common case but makes it simple to extend behaviour.&lt;/p&gt;

&lt;p&gt;By all means, it's not perfect - I'm not a huge fan of "dynamic, dynamic everywhere" - but it's way better than MVC for my
needs. The upgrade path is a whole lot less troublesome, too - the best advice I've found for upgrading between major versions
of MVC is to create a new project and copy the old content across.&lt;/p&gt;

&lt;h2&gt;Application structure&lt;/h2&gt;

&lt;p&gt;The equivalent of an MVC controller in NancyFX is the module. In a typical MVC controller, there are lots (usually far too many)
methods (controller actions) that do different things. While this isn't strictly a feature of the framework, all the sample code
tends to guide people down the path of having lots of methods on an average controller, with a correspondingly large number of
dependencies.&lt;/p&gt;

&lt;p&gt;In MVC, routing to controller actions is taken care of my convention, defaulting to the controller's type name and method name. For
instance, the /Home/About path would (by default) map to the About() method on the HomeController class.&lt;/p&gt;

&lt;p&gt;Nancy routes are wired up a little bit differently. Each module gets to register the routes that it can handle in its constructors,
so if I were to want to emulate the above behaviour I'd do something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class HomeModule : NancyModule
{
    public HomeModule()
    {
        Get["/Home/Index"] = args =&amp;gt; /* some implementation here */;
        Get["/Home/About"] = args =&amp;gt; /* some implementation here */;
        Get["/Home/Contact"] = args =&amp;gt; /* some implementation here */;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obviously, if we want the same Nancy module to handle more than one route then we just wire up additional routes in the module's
constructor and we're good.&lt;/p&gt;

&lt;p&gt;This is nice in a way but it's also a very easy way to cut yourself and I tend to not be a fan. Not only that, but it still leads
us down the path of violating the Single Responsibility Principle in our module.&lt;/p&gt;

&lt;p&gt;My preference is to have &lt;strong&gt;one action per module&lt;/strong&gt; and to name and namespace each module according to its route. Thus my application's
filesystem structure would look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;app
    Home
        Index.cs
        About.cs
        Contact.cs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes it incredibly easy to navigate around the application and I never have to wonder about which controller/module/HTTP handler
is serving a request for a particular path.&lt;/p&gt;

&lt;p&gt;My About.cs file would therefore look something like this (for now):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class About : NancyModule
{
    public About()
    {
        Get["/Home/About"] = args =&amp;gt; /* some implementation here */;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;RoutedModule&lt;/h2&gt;

&lt;p&gt;One problem with the above approach is that it's not refactoring-friendly. If I were to change the name of the About class then I'd also need
to edit the route registration's magic string. Magic strings are bad, mmmkay?&lt;/p&gt;

&lt;p&gt;A simple approach for the common case (remembering that it's still easy to manually register additional routes) is to just derive the name
of the route from the name and namespace of the module. (Hey, I didn't say that &lt;em&gt;all&lt;/em&gt; of MVC was bad.)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public abstract class RoutedModule : NancyModule
{
    protected RoutedModule()
    {
        var route = Route.For(GetType());
        Get[route, true] = (args, ct) =&amp;gt; HandleGet(args, ct);
        Post[route, true] = (args, ct) =&amp;gt; HandlePost(args, ct);
    }

    protected virtual async Task&amp;lt;dynamic&amp;gt; HandleGet(dynamic args, CancellationToken ct)
    {
        return (dynamic) View[ViewName];
    }

    protected virtual Task&amp;lt;dynamic&amp;gt; HandlePost(dynamic args, CancellationToken ct)
    {
        throw new NotSupportedException();
    }

    protected virtual string ViewName
    {
        get { return this.ViewName(); }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This now allows for our About.cs file to look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class About : RoutedModule
{
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Routes&lt;/h2&gt;

&lt;p&gt;We're not quite there yet. I'm not a fan of magic strings and in the above example you can see a call to a static Route.For method.
That method is where the useful behaviour is, and it looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static class Route
{
    private static readonly string _baseNamespace = typeof (Index).Namespace;

    public static string For&amp;lt;TModule&amp;gt;() where TModule : RoutedModule
    {
        return For(typeof (TModule));
    }

    public static string For(Type moduleType)
    {
        var route = moduleType.FullName
                              .Replace(_baseNamespace, string.Empty)
                              .Replace(".", "/")
                              .Replace("//", "/")
                              .ToLowerInvariant();
        return route;
    }

    public static string ViewName(this RoutedModule module)
    {
        // Left as an exercise for the reader :)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This allows us to have a completely refactor-friendly route to an individual action. There are a couple of similar routing efforts
for MVC, notably in MVC.Contrib and &lt;a href="https://github.com/uglybugger/MvcNavigationHelpers"&gt;MvcNavigationHelpers&lt;/a&gt;, but this lightweight approach doesn't require building and parsing of
expression trees. (It's worth noting that it doesn't account for a full route value dictionary, either, but you can add that if
you like.)&lt;/p&gt;

&lt;p&gt;In our views, our URLs can now be generated like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;a class="navbar-brand" href="@(Route.For&amp;lt;Index&amp;gt;())"&amp;gt;
    Tweets from the Vault
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and in our modules, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;return new RedirectResponse(Route.For&amp;lt;Index&amp;gt;());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A quick ^R^R (Refactor, Rename, for all you ReSharper Luddites) of any of our modules and you can see that we haven't broken any of our links
or redirects.&lt;/p&gt;

&lt;p&gt;In the next post in this series, we'll take a quick look at authenticating with Twitter using OAuth.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Mon, 19 Jan 2015 21:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/building_tweets_from_the_vault_nancyfx_tips_and_tricks" /><a10:updated>2015-01-19T21:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;In &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_azure_teamcity_and_octopus"&gt;Building Tweets from the Vault: Azure, TeamCity and Octopus&lt;/a&gt;, I wrote about the hosting and infrastructure
choices I made for &lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt;. This article will cover a bit more
about the framework choices, notably NancyFX.&lt;/p&gt;

&lt;h1&gt;NancyFX&lt;/h1&gt;

&lt;p&gt;NancyFX may sound like a bit more of an esoteric choice, especially to the Microsoft-or-die crowd. I've been having a pretty
fair amount of success with Nancy, however. I love the way that it just gets out of the road and provides a close-to-the-metal
experience for the common case but makes it simple to extend behaviour.&lt;/p&gt;

&lt;p&gt;By all means, it's not perfect - I'm not a huge fan of "dynamic, dynamic everywhere" - but it's way better than MVC for my
needs. The upgrade path is a whole lot less troublesome, too - the best advice I've found for upgrading between major versions
of MVC is to create a new project and copy the old content across.&lt;/p&gt;

&lt;h2&gt;Application structure&lt;/h2&gt;

&lt;p&gt;The equivalent of an MVC controller in NancyFX is the module. In a typical MVC controller, there are lots (usually far too many)
methods (controller actions) that do different things. While this isn't strictly a feature of the framework, all the sample code
tends to guide people down the path of having lots of methods on an average controller, with a correspondingly large number of
dependencies.&lt;/p&gt;

&lt;p&gt;In MVC, routing to controller actions is taken care of my convention, defaulting to the controller's type name and method name. For
instance, the /Home/About path would (by default) map to the About() method on the HomeController class.&lt;/p&gt;

&lt;p&gt;Nancy routes are wired up a little bit differently. Each module gets to register the routes that it can handle in its constructors,
so if I were to want to emulate the above behaviour I'd do something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class HomeModule : NancyModule
{
    public HomeModule()
    {
        Get["/Home/Index"] = args =&amp;gt; /* some implementation here */;
        Get["/Home/About"] = args =&amp;gt; /* some implementation here */;
        Get["/Home/Contact"] = args =&amp;gt; /* some implementation here */;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obviously, if we want the same Nancy module to handle more than one route then we just wire up additional routes in the module's
constructor and we're good.&lt;/p&gt;

&lt;p&gt;This is nice in a way but it's also a very easy way to cut yourself and I tend to not be a fan. Not only that, but it still leads
us down the path of violating the Single Responsibility Principle in our module.&lt;/p&gt;

&lt;p&gt;My preference is to have &lt;strong&gt;one action per module&lt;/strong&gt; and to name and namespace each module according to its route. Thus my application's
filesystem structure would look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;app
    Home
        Index.cs
        About.cs
        Contact.cs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes it incredibly easy to navigate around the application and I never have to wonder about which controller/module/HTTP handler
is serving a request for a particular path.&lt;/p&gt;

&lt;p&gt;My About.cs file would therefore look something like this (for now):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class About : NancyModule
{
    public About()
    {
        Get["/Home/About"] = args =&amp;gt; /* some implementation here */;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;RoutedModule&lt;/h2&gt;

&lt;p&gt;One problem with the above approach is that it's not refactoring-friendly. If I were to change the name of the About class then I'd also need
to edit the route registration's magic string. Magic strings are bad, mmmkay?&lt;/p&gt;

&lt;p&gt;A simple approach for the common case (remembering that it's still easy to manually register additional routes) is to just derive the name
of the route from the name and namespace of the module. (Hey, I didn't say that &lt;em&gt;all&lt;/em&gt; of MVC was bad.)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public abstract class RoutedModule : NancyModule
{
    protected RoutedModule()
    {
        var route = Route.For(GetType());
        Get[route, true] = (args, ct) =&amp;gt; HandleGet(args, ct);
        Post[route, true] = (args, ct) =&amp;gt; HandlePost(args, ct);
    }

    protected virtual async Task&amp;lt;dynamic&amp;gt; HandleGet(dynamic args, CancellationToken ct)
    {
        return (dynamic) View[ViewName];
    }

    protected virtual Task&amp;lt;dynamic&amp;gt; HandlePost(dynamic args, CancellationToken ct)
    {
        throw new NotSupportedException();
    }

    protected virtual string ViewName
    {
        get { return this.ViewName(); }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This now allows for our About.cs file to look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class About : RoutedModule
{
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Routes&lt;/h2&gt;

&lt;p&gt;We're not quite there yet. I'm not a fan of magic strings and in the above example you can see a call to a static Route.For method.
That method is where the useful behaviour is, and it looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static class Route
{
    private static readonly string _baseNamespace = typeof (Index).Namespace;

    public static string For&amp;lt;TModule&amp;gt;() where TModule : RoutedModule
    {
        return For(typeof (TModule));
    }

    public static string For(Type moduleType)
    {
        var route = moduleType.FullName
                              .Replace(_baseNamespace, string.Empty)
                              .Replace(".", "/")
                              .Replace("//", "/")
                              .ToLowerInvariant();
        return route;
    }

    public static string ViewName(this RoutedModule module)
    {
        // Left as an exercise for the reader :)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This allows us to have a completely refactor-friendly route to an individual action. There are a couple of similar routing efforts
for MVC, notably in MVC.Contrib and &lt;a href="https://github.com/uglybugger/MvcNavigationHelpers"&gt;MvcNavigationHelpers&lt;/a&gt;, but this lightweight approach doesn't require building and parsing of
expression trees. (It's worth noting that it doesn't account for a full route value dictionary, either, but you can add that if
you like.)&lt;/p&gt;

&lt;p&gt;In our views, our URLs can now be generated like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;a class="navbar-brand" href="@(Route.For&amp;lt;Index&amp;gt;())"&amp;gt;
    Tweets from the Vault
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and in our modules, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;return new RedirectResponse(Route.For&amp;lt;Index&amp;gt;());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A quick ^R^R (Refactor, Rename, for all you ReSharper Luddites) of any of our modules and you can see that we haven't broken any of our links
or redirects.&lt;/p&gt;

&lt;p&gt;In the next post in this series, we'll take a quick look at authenticating with Twitter using OAuth.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">building_tweets_from_the_vault_yet_another_bootstrap_site</guid><link>http://uglybugger.org/software/post/building_tweets_from_the_vault_yet_another_bootstrap_site</link><author>andrewh@uglybugger.org</author><title>Building Tweets from the Vault: yet another Bootstrap site?</title><description>&lt;p&gt;There's even a &lt;a href="http://yetanotherbootstrapsite.tumblr.com"&gt;Tumblr for this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The reality, however, is that Bootstrap is incredibly popular for good reason. It's responsive
out-of-the-box, is delivered via other people's CDNs (for which I thank you :) ) and provides a relatively familiar UI
paradigm.&lt;/p&gt;

&lt;p&gt;In keeping with the "minimum viable product" theme, Bootstrap allows for very quick... err... bootstrapping of a pleasant,
clean, simple web application with the minimum of fuss.&lt;/p&gt;

&lt;p&gt;This is just a quick post to get the "Yet another Bootstrap site?" question out of the way. In the next post in this series
I'll look in a bit more detail at NancyFX and some sneaky tricks to make it refactoring-friendly.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sat, 17 Jan 2015 21:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/building_tweets_from_the_vault_yet_another_bootstrap_site" /><a10:link href="http://uglybugger.org/software/post/building_tweets_from_the_vault_yet_another_bootrap_site" /><a10:updated>2015-01-17T21:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;There's even a &lt;a href="http://yetanotherbootstrapsite.tumblr.com"&gt;Tumblr for this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The reality, however, is that Bootstrap is incredibly popular for good reason. It's responsive
out-of-the-box, is delivered via other people's CDNs (for which I thank you :) ) and provides a relatively familiar UI
paradigm.&lt;/p&gt;

&lt;p&gt;In keeping with the "minimum viable product" theme, Bootstrap allows for very quick... err... bootstrapping of a pleasant,
clean, simple web application with the minimum of fuss.&lt;/p&gt;

&lt;p&gt;This is just a quick post to get the "Yet another Bootstrap site?" question out of the way. In the next post in this series
I'll look in a bit more detail at NancyFX and some sneaky tricks to make it refactoring-friendly.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">building_tweets_from_the_vault_azure_teamcity_and_octopus</guid><link>http://uglybugger.org/software/post/building_tweets_from_the_vault_azure_teamcity_and_octopus</link><author>andrewh@uglybugger.org</author><title>Building Tweets from the Vault: Azure, TeamCity and Octopus</title><description>&lt;p&gt;In the previous post in this series, &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_minimum_viable_product"&gt;Building Tweets from the Vault: Minimum Viable Product&lt;/a&gt;, I wrote about the absolute
minimum feature set to get &lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; off the ground.&lt;/p&gt;

&lt;p&gt;In this post I'm going to write a bit more about some of the technology choices. So... what were they, and why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetbrains.com/teamcity"&gt;TeamCity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.octopusdeploy.com/"&gt;Octopus Deploy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NancyFX&lt;/li&gt;
&lt;li&gt;Bootstrap&lt;/li&gt;
&lt;li&gt;Tweetinvi&lt;/li&gt;
&lt;li&gt;Stripe + Stripe.NET&lt;/li&gt;
&lt;li&gt;Serilog + &lt;a href="http://www.getseq.net/"&gt;Seq&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Azure + TeamCity + Octopus Deploy&lt;/h1&gt;

&lt;p&gt;Obviously, I was going to need a hosting platform that was easy to get started with but that could scale if (when? ha!) my app
hits the big-time. The app (and the article you're currently reading) is running on Azure VM-hosted IIS deployed to via
Octopus Deploy.&lt;/p&gt;

&lt;p&gt;To ship a feature &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git add -A .
git commit -m "Added some feature"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;TeamCity will pick up that change, build it, run my tests, push a package to Octopus Deploy and then deploy that package to my
test environment. A quick sanity-check there[1] and then it gets promoted to the live Azure environment. Using this tool suite
a change can go from my MacBook to production via a sensible build + test + deploy pipeline in under two minutes.&lt;/p&gt;

&lt;p&gt;For anything more complicated, I'll use a feature branch. TeamCity will automatically pick up and build refs/heads/* so all of
my branches get the same treatment, all the way through to packaging in Octopus and deploying to a test site.&lt;/p&gt;

&lt;p&gt;Hotfixes are treated in the same way as feature branches. If I have to revert to any particular revision, it's simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git checkout some-hash
git checkout -b hotfix-some-fix
git add -A .
git commit -m "Fixed some bug"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That build will go straight to my test environment through the normal build + test + deploy pipeline and I can then tell
Octopus to promote that hotfix package to production. No mess; no fuss.&lt;/p&gt;

&lt;p&gt;In the next posts in this series, I'll write a bit about Bootstrap and NancyFX.&lt;/p&gt;

&lt;p&gt;[1] I trust my test suite. You should trust yours, too - or write better ones ;)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 15 Jan 2015 21:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/building_tweets_from_the_vault_azure_teamcity_and_octopus" /><a10:updated>2015-01-15T21:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;In the previous post in this series, &lt;a href="http://www.uglybugger.org/software/post/building_tweets_from_the_vault_minimum_viable_product"&gt;Building Tweets from the Vault: Minimum Viable Product&lt;/a&gt;, I wrote about the absolute
minimum feature set to get &lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; off the ground.&lt;/p&gt;

&lt;p&gt;In this post I'm going to write a bit more about some of the technology choices. So... what were they, and why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jetbrains.com/teamcity"&gt;TeamCity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.octopusdeploy.com/"&gt;Octopus Deploy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NancyFX&lt;/li&gt;
&lt;li&gt;Bootstrap&lt;/li&gt;
&lt;li&gt;Tweetinvi&lt;/li&gt;
&lt;li&gt;Stripe + Stripe.NET&lt;/li&gt;
&lt;li&gt;Serilog + &lt;a href="http://www.getseq.net/"&gt;Seq&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Azure + TeamCity + Octopus Deploy&lt;/h1&gt;

&lt;p&gt;Obviously, I was going to need a hosting platform that was easy to get started with but that could scale if (when? ha!) my app
hits the big-time. The app (and the article you're currently reading) is running on Azure VM-hosted IIS deployed to via
Octopus Deploy.&lt;/p&gt;

&lt;p&gt;To ship a feature &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git add -A .
git commit -m "Added some feature"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;TeamCity will pick up that change, build it, run my tests, push a package to Octopus Deploy and then deploy that package to my
test environment. A quick sanity-check there[1] and then it gets promoted to the live Azure environment. Using this tool suite
a change can go from my MacBook to production via a sensible build + test + deploy pipeline in under two minutes.&lt;/p&gt;

&lt;p&gt;For anything more complicated, I'll use a feature branch. TeamCity will automatically pick up and build refs/heads/* so all of
my branches get the same treatment, all the way through to packaging in Octopus and deploying to a test site.&lt;/p&gt;

&lt;p&gt;Hotfixes are treated in the same way as feature branches. If I have to revert to any particular revision, it's simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git checkout some-hash
git checkout -b hotfix-some-fix
git add -A .
git commit -m "Fixed some bug"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That build will go straight to my test environment through the normal build + test + deploy pipeline and I can then tell
Octopus to promote that hotfix package to production. No mess; no fuss.&lt;/p&gt;

&lt;p&gt;In the next posts in this series, I'll write a bit about Bootstrap and NancyFX.&lt;/p&gt;

&lt;p&gt;[1] I trust my test suite. You should trust yours, too - or write better ones ;)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">building_tweets_from_the_vault_minimum_viable_product</guid><link>http://uglybugger.org/software/post/building_tweets_from_the_vault_minimum_viable_product</link><author>andrewh@uglybugger.org</author><title>Building Tweets from the Vault: Minimum Viable Product</title><description>&lt;p&gt;&lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; is a service that will take a random[1] historical item from your
RSS feeds and tweet a link to it.&lt;/p&gt;

&lt;p&gt;When I started building the service, my goals were simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solve my own problem&lt;/li&gt;
&lt;li&gt;Get to a minimum viable product as quickly as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this series of posts I'm going to look at each of those points in a little more detail.&lt;/p&gt;

&lt;h2&gt;Solve my own problem&lt;/h2&gt;

&lt;p&gt;There's a bunch of content in my blog that is still very relevant today. Lots of stuff on agile; lots on software principles and
some valuable odds and ends that were starting to be lost to the archives.&lt;/p&gt;

&lt;p&gt;I have IFTTT tweeting content as soon as it hits my RSS feeds, which is great, and obviously that leads to people's visiting
those posts while that tweet appears in their timeline. Once that tweet falls off their timeline, though, all bets are off - nobody's
likely to see that tweet ever again.&lt;/p&gt;

&lt;p&gt;I wanted a solution that would periodically fish out a historical but relevant article and tweet a link to it and there wasn't
a service that did that for me in a way that I liked. The closest I could find was an outdated Wordpress plugin (and I don't use
Wordpress). Well... I blog mostly about software so why wouldn't I write one for myself? And, if I were to write one for myself,
perhaps I could tweak it a bit and make it useful to other people. And thus, &lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; was born.&lt;/p&gt;

&lt;h2&gt;Mimimum viable product&lt;/h2&gt;

&lt;p&gt;The minimum viable product for me was pretty simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign in using a Twitter account&lt;/li&gt;
&lt;li&gt;Set up a small, recurring payment&lt;/li&gt;
&lt;li&gt;Add and remove RSS feeds&lt;/li&gt;
&lt;li&gt;On a schedule:
&lt;ul&gt;
&lt;li&gt;Pick a random article from that set of RSS feeds&lt;/li&gt;
&lt;li&gt;Tweet it&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's pretty much it.&lt;/p&gt;

&lt;p&gt;In the next post in this series, I'll start looking at some of the technology choices for the app.&lt;/p&gt;

&lt;p&gt;[1] For a given definition of "random".&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 13 Jan 2015 21:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/building_tweets_from_the_vault_minimum_viable_product" /><a10:updated>2015-01-13T21:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;&lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; is a service that will take a random[1] historical item from your
RSS feeds and tweet a link to it.&lt;/p&gt;

&lt;p&gt;When I started building the service, my goals were simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solve my own problem&lt;/li&gt;
&lt;li&gt;Get to a minimum viable product as quickly as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this series of posts I'm going to look at each of those points in a little more detail.&lt;/p&gt;

&lt;h2&gt;Solve my own problem&lt;/h2&gt;

&lt;p&gt;There's a bunch of content in my blog that is still very relevant today. Lots of stuff on agile; lots on software principles and
some valuable odds and ends that were starting to be lost to the archives.&lt;/p&gt;

&lt;p&gt;I have IFTTT tweeting content as soon as it hits my RSS feeds, which is great, and obviously that leads to people's visiting
those posts while that tweet appears in their timeline. Once that tweet falls off their timeline, though, all bets are off - nobody's
likely to see that tweet ever again.&lt;/p&gt;

&lt;p&gt;I wanted a solution that would periodically fish out a historical but relevant article and tweet a link to it and there wasn't
a service that did that for me in a way that I liked. The closest I could find was an outdated Wordpress plugin (and I don't use
Wordpress). Well... I blog mostly about software so why wouldn't I write one for myself? And, if I were to write one for myself,
perhaps I could tweak it a bit and make it useful to other people. And thus, &lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; was born.&lt;/p&gt;

&lt;h2&gt;Mimimum viable product&lt;/h2&gt;

&lt;p&gt;The minimum viable product for me was pretty simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign in using a Twitter account&lt;/li&gt;
&lt;li&gt;Set up a small, recurring payment&lt;/li&gt;
&lt;li&gt;Add and remove RSS feeds&lt;/li&gt;
&lt;li&gt;On a schedule:
&lt;ul&gt;
&lt;li&gt;Pick a random article from that set of RSS feeds&lt;/li&gt;
&lt;li&gt;Tweet it&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's pretty much it.&lt;/p&gt;

&lt;p&gt;In the next post in this series, I'll start looking at some of the technology choices for the app.&lt;/p&gt;

&lt;p&gt;[1] For a given definition of "random".&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">tweets_from_the_vault</guid><link>http://uglybugger.org/software/post/tweets_from_the_vault</link><author>andrewh@uglybugger.org</author><title>Tweets from the Vault</title><description>&lt;p&gt;I built a thing!&lt;/p&gt;

&lt;p&gt;I keep linking people to old blog posts of mine. Sometimes it's to solve a problem that was solved a long time ago; other times it's
to make a point that the argument they're having isn't new. Either way, there's a whole bunch of valuable content locked up with
nothing but an "Archives" link on a web site to show that it ever existed.&lt;/p&gt;

&lt;p&gt;I went looking for a way to re-publish some of this content and couldn't find anything that did what I wanted. Thus,
&lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;Tweets from the Vault is a paid service that will pick a random item out of any set of RSS feeds you give it and tweet it from your
account.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2015._2015._01._07._1300._1000.LandingPage.png/" alt="Landing Page Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2015._2015._01._07._1300._1000.Dashboard.png/" alt="Dashboard Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;I've priced the lowest plan of one tweet per day at $1/month. That's less than the average person would spend on electricity to power
their laptop for the month, and way less than you'd spend on even a half-decent coffee.&lt;/p&gt;

&lt;p&gt;You'll be seeing it in my Twitter feed - and I hope I'll see it in yours :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Wed, 07 Jan 2015 13:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/tweets_from_the_vault" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2015._2015._01._07._1300._1000.LandingPage.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2015._2015._01._07._1300._1000.Dashboard.png/" /><a10:updated>2015-01-07T13:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I built a thing!&lt;/p&gt;

&lt;p&gt;I keep linking people to old blog posts of mine. Sometimes it's to solve a problem that was solved a long time ago; other times it's
to make a point that the argument they're having isn't new. Either way, there's a whole bunch of valuable content locked up with
nothing but an "Archives" link on a web site to show that it ever existed.&lt;/p&gt;

&lt;p&gt;I went looking for a way to re-publish some of this content and couldn't find anything that did what I wanted. Thus,
&lt;a href="https://tweetsfromthevault.com"&gt;Tweets from the Vault&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;Tweets from the Vault is a paid service that will pick a random item out of any set of RSS feeds you give it and tweet it from your
account.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2015._2015._01._07._1300._1000.LandingPage.png/" alt="Landing Page Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2015._2015._01._07._1300._1000.Dashboard.png/" alt="Dashboard Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;I've priced the lowest plan of one tweet per day at $1/month. That's less than the average person would spend on electricity to power
their laptop for the month, and way less than you'd spend on even a half-decent coffee.&lt;/p&gt;

&lt;p&gt;You'll be seeing it in my Twitter feed - and I hope I'll see it in yours :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">am_i_interviewing_you_heres_what_im_going_to_ask</guid><link>http://uglybugger.org/software/post/am_i_interviewing_you_heres_what_im_going_to_ask</link><author>andrewh@uglybugger.org</author><title>Am I interviewing you? Here's what I'm going to ask.</title><description>&lt;p&gt;If you have an interview scheduled with me, here's what I'm going to ask you.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 20 Mar 2014 10:45:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/am_i_interviewing_you_heres_what_im_going_to_ask" /><a10:updated>2014-03-20T10:45:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;If you have an interview scheduled with me, here's what I'm going to ask you.&lt;/p&gt;

&lt;p&gt;This is a tongue-in-cheek guide to interviewing with anyone. There'll be some fun poked, some snark and some genuine
advice. I'll leave it to you to decide which is which :)&lt;/p&gt;

&lt;p&gt;So... Hi! Firstly, if you've arrived here because you're doing your homework, good for you. Have a point. Have two, even.
I'm feeling generous today.&lt;/p&gt;

&lt;p&gt;I do a lot of interviews. Depressingly, even with all the advice available to them, people still fall down on the
same things time after time after time. If you're diligent enough to be doing your homework by reading this, you
should be fine :)  If you're reading this after your interview with a sinking feeling in your stomach... well...
this homework was probably due yesterday. Sorry.&lt;/p&gt;

&lt;h1&gt;Be on time.&lt;/h1&gt;

&lt;p&gt;If we're interviewing in person, &lt;strong&gt;be on time&lt;/strong&gt;. I'll be there. If we're interviewing via Skype, I will add you as a
contact at &lt;em&gt;precisely&lt;/em&gt; our scheduled time. Expect this. &lt;strong&gt;Be online.&lt;/strong&gt; Failing at time zone calculations for any position
in the software industry does not bode well.&lt;/p&gt;

&lt;p&gt;If you're horrified that I even have to say this then have another point :)&lt;/p&gt;

&lt;h1&gt;Ask me questions.&lt;/h1&gt;

&lt;p&gt;With respect to consulting, I want you to treat me as you'd treat a client. The questions you ask in advance and during the interview
will help both of us. It will help you understand if you're answering my questions well, and it will help me understand that you know
what questions to ask.&lt;/p&gt;

&lt;p&gt;Ask me about stuff you're curious about. Ask me about pretty much anything. Just show that you can hold a conversation and elicit
useful knowledge about a topic at the same time.&lt;/p&gt;

&lt;p&gt;Ask me about anything that helps you decide whether we're a good cultural fit. I'll be asking you similar questions and fair's fair.&lt;/p&gt;

&lt;h1&gt;I'm hiring colleagues, not minions. I want to like you.&lt;/h1&gt;

&lt;p&gt;I'll be hoping that you'd like to work with me. Your mission is to make me want to work with you. I'm looking for people who are
interesting, engaging and fun to hang out with. I want people on my teams who &lt;em&gt;other people will want to work with&lt;/em&gt;. We'll probably be
spending a fair bit of time together and I'd like that time to be enjoyable for all parties.&lt;/p&gt;

&lt;h1&gt;I'm going to ask you about what you're strongest in.&lt;/h1&gt;

&lt;p&gt;There's no value in finding weaknesses in things you've already told me you're not great at. That's fine. If you say you hate
Windows Forms then why would I ask esoteric questions about it? That serves neither of us well. (Besides, I hate WinForms, too.)
I'm going to play to your strengths. If your strengths are strong, good for you. If your strengths are weak then I don't need
to dig much further.&lt;/p&gt;

&lt;p&gt;If you tell me you rate yourself as a thought leader in a space, I expect you to be able to teach it to me from first principles
because &lt;strong&gt;that's what your clients will be paying four figures per day for&lt;/strong&gt;. If you tell me, for instance, that you're a
thought leader on an open-source framework, I'll assume you're a committer to it and ask you what you last pushed.&lt;/p&gt;

&lt;p&gt;If you're good at something, say so. It's your opportunity to show knowledge and enthusiasm. If you're not good at something, say
so and we'll move on. That's perfectly okay and I won't hold it against you. Don't bluff. I'll call.&lt;/p&gt;

&lt;h1&gt;I'm going to ask about what &lt;em&gt;you're&lt;/em&gt; interested in, not what &lt;em&gt;I'm&lt;/em&gt; interested in.&lt;/h1&gt;

&lt;p&gt;I want you to get enthusiastic about something. Teach me something. Make &lt;em&gt;me&lt;/em&gt; enthusiastic about/interested in something. Creating
enthusiasm and engagement in other people is a life skill, not just a consulting one. I'm hiring for that skill.&lt;/p&gt;

&lt;h1&gt;I will expect you to know your fundamentals.&lt;/h1&gt;

&lt;p&gt;In the .NET space, this means that I'm going to ask you about the CLR, stack, heap, memory allocation, garbage collection, generics and
all the other stuff that you use day in and day out.&lt;/p&gt;

&lt;p&gt;In the agile space I'm going to ask you for &lt;em&gt;opinions&lt;/em&gt; about Scrum, Kanban, lean and so on. You're going to need to discuss these, not
just parrot the definition of a user story.&lt;/p&gt;

&lt;p&gt;We'll cover lots of other topics but not knowing your fundamentals is a cardinal sin. It's akin to stealing from your client and it's...
not a behaviour I'd encourage. They're called fundamentals for a reason :)&lt;/p&gt;

&lt;h1&gt;If you'll be paid to write code then, yes, I will expect you to write code.&lt;/h1&gt;

&lt;p&gt;You're probably interviewing for some kind of software engineering position. Be prepared to demonstrate that you can walk the walk.&lt;/p&gt;

&lt;h1&gt;Final notes.&lt;/h1&gt;

&lt;p&gt;People generally take this kind of advice in one of two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They're offended because some of it applies to them.&lt;/li&gt;
&lt;li&gt;They're horrified that it would apply to anybody.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're the latter then we'll probably have war stories to share, heaps to chat about and I'll be looking forward to meeting you. If
you're the former then even if you're offended by what I've written I hope it's constructive in one way or another for you.
&lt;a href="http://www.youtube.com/watch?v=AjUmULa0R-8"&gt;Have fun storming the castle!&lt;/a&gt;&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">brisbane_azure_user_group_talk_on_azure_service_bus_made_easy</guid><link>http://uglybugger.org/software/post/brisbane_azure_user_group_talk_on_azure_service_bus_made_easy</link><author>andrewh@uglybugger.org</author><title>Brisbane Azure User Group talk on Azure Service Bus Made Easy</title><description>&lt;p&gt;Damian Maclennan and I did a talk at the Brisbane Azure User Group on Azure Service Bus Made Easy. Here's the video :)&lt;/p&gt;

&lt;p&gt;&lt;a target="_blank" href="https://www.youtube.com/watch?v=7LFu6r9tA9s"&gt;&lt;img alt="Azure Service Bus Made Easy" src="https://img.youtube.com/vi/7LFu6r9tA9s/maxresdefault.jpg" class="img-responsive" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here are Damian's slides from the night:&lt;/p&gt;

&lt;p&gt;&lt;a target="_blank" href="http://www.slideshare.net/DamianMaclennan/introducing-nimbus"&gt;&lt;img src="https://cdn.slidesharecdn.com/ss_thumbnails/introducingnimbus-140305185106-phpapp01-thumbnail-4.jpg" alt="Azure Service Bus Made Easy" class="img-responsive"/&gt;&lt;/a&gt;&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 18 Mar 2014 13:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/brisbane_azure_user_group_talk_on_azure_service_bus_made_easy" /><a10:updated>2014-03-18T13:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Damian Maclennan and I did a talk at the Brisbane Azure User Group on Azure Service Bus Made Easy. Here's the video :)&lt;/p&gt;

&lt;p&gt;&lt;a target="_blank" href="https://www.youtube.com/watch?v=7LFu6r9tA9s"&gt;&lt;img alt="Azure Service Bus Made Easy" src="https://img.youtube.com/vi/7LFu6r9tA9s/maxresdefault.jpg" class="img-responsive" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here are Damian's slides from the night:&lt;/p&gt;

&lt;p&gt;&lt;a target="_blank" href="http://www.slideshare.net/DamianMaclennan/introducing-nimbus"&gt;&lt;img src="https://cdn.slidesharecdn.com/ss_thumbnails/introducingnimbus-140305185106-phpapp01-thumbnail-4.jpg" alt="Azure Service Bus Made Easy" class="img-responsive"/&gt;&lt;/a&gt;&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">support_for_long_running_handlers_in_nimbus</guid><link>http://uglybugger.org/software/post/support_for_long_running_handlers_in_nimbus</link><author>andrewh@uglybugger.org</author><title>Support for long-running handlers in Nimbus</title><description>&lt;p&gt;Shiny, new feature: Nimbus now allows command/event/request handlers the option to run for extended time periods.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 13 Mar 2014 11:30:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/support_for_long_running_handlers_in_nimbus" /><a10:updated>2014-03-13T11:30:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Shiny, new feature: Nimbus now allows command/event/request handlers the option to run for extended time periods.&lt;/p&gt;

&lt;p&gt;From day zero Nimbus has supported competing command handlers, allowing us to spin up an arbitrary number of handlers
to increase throughput. One issue that we've run into is to do with the way that we have to deal with reliable
handling of messages and how and when retries are attempted.&lt;/p&gt;

&lt;p&gt;You'd think (naively) that a normal workflow would looks something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pop a command from the queue.&lt;/li&gt;
&lt;li&gt;Handle that command.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But what happens when the command handler goes bang? We need some way of putting that command back onto the queue for
someone else to attempt. Again, a naive approach would be something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pop a command from the queue.&lt;/li&gt;
&lt;li&gt;Handle that command.&lt;/li&gt;
&lt;li&gt;If that command goes bang, put it back onto the queue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So... where does the command live during Step #2? The only place for it to live is on the node that's actually doing the work - and
this is a problem. If that node simply throws an exception then we could catch it and put the message back onto the queue. But what
if the power goes out? Or a disk goes crunch? (Or crackle, given that we're in SSD-land now?) &lt;em&gt;What if that node never comes back?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If that node never comes back, the message never gets re-enqueued, which means we've violated our delivery guarantee. Oops.&lt;/p&gt;

&lt;p&gt;Thankfully, that's not how it works. Under the covers, the Azure Message Bus does some clever stuff for us. The actual workflow
looks something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tentatively pop a message from the head of the queue.&lt;/li&gt;
&lt;li&gt;Attempt to handle that message.&lt;/li&gt;
&lt;li&gt;If we succeed, call BrokeredMessage.Complete()&lt;/li&gt;
&lt;li&gt;If we fail, call BrokeredMessage.Abandon()&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The missing piece in this puzzle is still what happens if the power goes out. In this case, the Azure Message Bus will automatically
re-queue the message after a certain time period (called the peek-lock timeout) and won't allow the original (now-timed-out) handler
to call either .Complete() or .Abandon() on the message any more. In essence, it's saying "You get XX seconds to handle the message
and if I don't hear back from you one way or the other before that time elapses then I'll assume you've vanished and will give
someone else a chance to handle it."&lt;/p&gt;

&lt;h1&gt;So what's the problem, then?&lt;/h1&gt;

&lt;p&gt;The problem arises when we have a command handler that legitimately takes longer than the peek-lock timeout to do its thing. We've
seen this scenario in the wild with people doing things like Selenium-based screen-scraping of legacy web sites, really long-running
aggregate queries or ETL operations on databases and a bunch of other scenarios.&lt;/p&gt;

&lt;p&gt;Let's have a look at our PizzaMaker as an example. Here's our IncomingOrderHandler class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class IncomingOrderHandler : IHandleCommand&amp;lt;OrderPizzaCommand&amp;gt;
{
    private readonly IPizzaMaker _pizzaMaker;

    public IncomingOrderHandler(IPizzaMaker pizzaMaker)
    {
        _pizzaMaker = pizzaMaker;
    }

    public async Task Handle(OrderPizzaCommand busCommand)
    {
        await _pizzaMaker.MakePizzaForCustomer(busCommand.CustomerName);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and our PizzaMaker looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class PizzaMaker : IPizzaMaker
{
    private readonly IBus _bus;

    public PizzaMaker(IBus bus)
    {
        _bus = bus;
    }

    public async Task MakePizzaForCustomer(string customerName)
    {
        await _bus.Publish(new NewOrderRecieved {CustomerName = customerName});
        Console.WriteLine("Hi {0}! I'm making your pizza now!", customerName);

        await Task.Delay(TimeSpan.FromSeconds(45));

        await _bus.Publish(new PizzaIsReady {CustomerName = customerName});
        Console.WriteLine("Hey, {0}! Your pizza's ready!", customerName);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's say that the peek-lock timeout is set to 30 seconds and making a pizza takes 45 seconds. What will happen in this case is
that the first handler will be spun up and given the command instance to handle. It will start to do its thing and all is well and
good. Thirty seconds later, the bus decides that that handler has died so it revokes its lock, puts the message back at the head
of the queue and promptly gives it to someone else.&lt;/p&gt;

&lt;p&gt;After another 15 seconds, the first handler will finish (presumably successfully) and will attempt to call .Complete() on its
message, which will make it throw an exception as it no longer holds a lock. What's worse is that this will repeat until the
maximum number of delivery attemps has been exceeded.&lt;/p&gt;

&lt;p&gt;We've just made five pizzas for the one order. And none of them has been recorded as successful. Oops.&lt;/p&gt;

&lt;h1&gt;What do I have to do to make it all Just Work&amp;trade;?&lt;/h1&gt;

&lt;p&gt;All you need to do is implement the ILongRunningHandler interface on your handler class. Let's update our IncomingOrderHandler
example from earlier:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class IncomingOrderHandler : IHandleCommand&amp;lt;OrderPizzaCommand&amp;gt;, ILongRunningHandler  // Note the additional interface
{
    private readonly IPizzaMaker _pizzaMaker;

    public IncomingOrderHandler(IPizzaMaker pizzaMaker)
    {
        _pizzaMaker = pizzaMaker;
    }

    public async Task Handle(OrderPizzaCommand busCommand)
    {
        await _pizzaMaker.MakePizzaForCustomer(busCommand.CustomerName);
    }

    // Note the new method
    public bool IsAlive
    {
        get { return true; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The ILongRunningHandler interface has a single, read-only property on it: IsAlive. All you need to do is return true if your
handler is still happily executing or false if it's not. In this case, we've taken the very naive approach of just returning
true but it might make more sense, for instance, to ask our PizzaMaker instance if they still have an order for the customer
in the works.&lt;/p&gt;

&lt;p&gt;Under the covers, Nimbus will automatically renew the lock it's taken out on the message for you so that you can take as long
as you like to handle it.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">the_readify_firehose_an_aggregated_feed_of_a_bunch_of_random_readifarians</guid><link>http://uglybugger.org/software/post/the_readify_firehose_an_aggregated_feed_of_a_bunch_of_random_readifarians</link><author>andrewh@uglybugger.org</author><title>The Readify Firehose: An aggregated feed of a bunch of random Readifarians</title><description>&lt;p&gt;In true Readify style, we had the idea for a thing the other day and launched it the next morning.
It's a small thing but still a thing.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Wed, 12 Mar 2014 12:45:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/the_readify_firehose_an_aggregated_feed_of_a_bunch_of_random_readifarians" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._03._12._1245._1000.TheFirehose.jpg/" /><a10:updated>2014-03-12T12:45:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;In true Readify style, we had the idea for a thing the other day and launched it the next morning.
It's a small thing but still a thing.&lt;/p&gt;

&lt;p&gt;Well, we built it, launched it, got a bunch of people to agree that it was a good idea, populated it
and publicised it. That was Thursday night/Friday morning.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._03._12._1245._1000.TheFirehose.jpg/" alt="The Firehose"/&gt;&lt;/p&gt;

&lt;p&gt;The Readify Firehose is a simple aggregated RSS feed of a bunch of participating Readify consultants
and other bloggers. It's entirely opt-in so you may or may not find your favourite author there (yet) but
we hope it's useful.&lt;/p&gt;

&lt;p&gt;You can have a look around at &lt;a href="http://readify-firehose.azurewebsites.net"&gt;readify-firehose.azurewebsites.net&lt;/a&gt; or
&lt;a href="http://readify-firehose.azurewebsites.net/Feed/Rss/50"&gt;subscribe directly to the feed&lt;/a&gt;.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">your_domain_model_is_too_big_for_ram</guid><link>http://uglybugger.org/software/post/your_domain_model_is_too_big_for_ram</link><author>andrewh@uglybugger.org</author><title>Your domain model is too big for RAM</title><description>&lt;p&gt;Here's the video from my DDD Brisbane 2013 talk.&lt;/p&gt;

&lt;p&gt;&lt;a target="_blank" href="https://www.youtube.com/watch?v=MuxTsnQ2e0o"&gt;&lt;img alt="Your domain model is too big for RAM (and other fallacies)" src="https://img.youtube.com/vi/MuxTsnQ2e0o/maxresdefault.jpg" class="img-responsive" /&gt;&lt;/a&gt;&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 11 Mar 2014 13:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/your_domain_model_is_too_big_for_ram" /><a10:updated>2014-03-11T13:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Here's the video from my DDD Brisbane 2013 talk.&lt;/p&gt;

&lt;p&gt;&lt;a target="_blank" href="https://www.youtube.com/watch?v=MuxTsnQ2e0o"&gt;&lt;img alt="Your domain model is too big for RAM (and other fallacies)" src="https://img.youtube.com/vi/MuxTsnQ2e0o/maxresdefault.jpg" class="img-responsive" /&gt;&lt;/a&gt;&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">stopping_a_visual_studio_build_on_first_error</guid><link>http://uglybugger.org/software/post/stopping_a_visual_studio_build_on_first_error</link><author>andrewh@uglybugger.org</author><title>Stopping a Visual Studio build on first error</title><description>&lt;p&gt;I can't believe I've lived without this for so long.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sat, 08 Mar 2014 20:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/stopping_a_visual_studio_build_on_first_error" /><a10:updated>2014-03-08T20:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I can't believe I've lived without this for so long.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://einaregilsson.com/stop-build-on-first-error-in-visual-studio-2010/"&gt;Einar Egilsson&lt;/a&gt; has written a wonderfully-useful
little plugin for Visual Studio that will allow you to stop the entire build process as soon as there's a single project that
fails.&lt;/p&gt;

&lt;p&gt;This helps when you have a solution with tens (Hundreds? Please don't do that.) of projects in them and there's a compilation
failure in one of the core projects upon which most of the others depend. You know that the build's going to fail but often
it's just too much hassle to stop it manually - especially if you're on a keyboard that doesn't have a Break key.&lt;/p&gt;

&lt;p&gt;The plugin has been around for a few years now and I can't believe I've never searched for something like it before today.&lt;/p&gt;

&lt;p&gt;You can get the plugin from the &lt;a href="http://visualstudiogallery.msdn.microsoft.com/91aaa139-5d3c-43a7-b39f-369196a84fa5"&gt;Visual Studio Gallery&lt;/a&gt;.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">configinjector_now_supports_static_loading_of_settings</guid><link>http://uglybugger.org/software/post/configinjector_now_supports_static_loading_of_settings</link><author>andrewh@uglybugger.org</author><title>ConfigInjector now supports static loading of settings</title><description>&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 1.1 has just been released.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 06 Mar 2014 19:45:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/configinjector_now_supports_static_loading_of_settings" /><a10:updated>2014-03-06T19:45:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;&lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;ConfigInjector&lt;/a&gt; 1.1 has just been released.&lt;/p&gt;

&lt;p&gt;It now supports static loading of individual settings so you can grab settings directly from your app/web.config files without
using the dreaded magic strings of ConfigurationManager.AppSettings.&lt;/p&gt;

&lt;p&gt;This is a necessary feature but please give some serious thought to whether it's a good idea in your particular case. If you genuinely need
access to settings before your container is wired up, go ahead. If you're using ConfigInjector as a settings service locator across your entire
app, you're holding it wrong :)&lt;/p&gt;

&lt;p&gt;Here's how:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var setting = DefaultSettingsReader.Get&amp;lt;SimpleIntSetting&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ConfigInjector will make an intelligent guess at defaults. It will, for instance, walk the call stack that invoked it and look for assemblies
that contain settings and value parsers. If you have custom value parsers it will pick those up, too, provided that they're not off in a
satellite assembly somewhere.&lt;/p&gt;

&lt;p&gt;If you need to globally change the default behaviour, create a class that implements IStaticSettingReaderStrategy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class MyCustomSettingsReaderStrategy : IStaticSettingReaderStrategy
{
    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and use use this to wire it up:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;DefaultSettingsReader.SetStrategy(new MyCustomSettingsReaderStrategy());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you're using ConfigInjector and like it, please let me know. There's Disqus below and there's always Twitter :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">request_and_response_with_nimbus</guid><link>http://uglybugger.org/software/post/request_and_response_with_nimbus</link><author>andrewh@uglybugger.org</author><title>Request and response with Nimbus</title><description>&lt;p&gt;In this article we're going to have a look at the request/response patterns available in Nimbus.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Wed, 05 Mar 2014 19:45:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/request_and_response_with_nimbus" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._03._05._1945._1000.Scenario_01.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._03._05._1945._1000.Scenario_02.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._03._05._1945._1000.Scenario_03.png/" /><a10:updated>2014-03-05T19:45:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;In this article we're going to have a look at the request/response patterns available in Nimbus.&lt;/p&gt;

&lt;p&gt;We've already seen &lt;a href="http://www.uglybugger.org/software/post/command_handling_with_nimbus"&gt;Command handling with Nimbus&lt;/a&gt; and
&lt;a href="http://www.uglybugger.org/Software/Post/eventing_with_nimbus"&gt;Eventing with Nimbus&lt;/a&gt; about command and event patterns respectively;
now it's time to take a look at the last key messaging pattern you'll need to understand: request/response.&lt;/p&gt;

&lt;p&gt;To get this out of the way right up-front, let's be blunt: request/response via a service bus is the subject of religious wars. There
are people who argue adamantly that you simply shouldn't do it (possibly because their tools of choice don't support it very well ;) ) and
there are others who are in the camp of "do it but use it judiciously". I'm in the latter. Sometimes my app &lt;em&gt;needs&lt;/em&gt; to ask someone a question
&lt;em&gt;and wait for a response&lt;/em&gt; before continuing. Get over it.&lt;/p&gt;

&lt;p&gt;Anyway, down to business.&lt;/p&gt;

&lt;p&gt;The first item on our list is a simple request/response. In other words, we ask a question and we wait for an answer. One key principle
here is that &lt;strong&gt;requests should not change the state of your domain&lt;/strong&gt;. In other words, requests are a &lt;em&gt;question&lt;/em&gt;, not an &lt;em&gt;instruction&lt;/em&gt;; a &lt;em&gt;query&lt;/em&gt;,
not a &lt;em&gt;command&lt;/em&gt;. There are some exceptions to this rule but if you're well-enough versed in messaging patterns to identify these (usually but not
exclusively the try/do pattern) then this primer really isn't for you.&lt;/p&gt;

&lt;p&gt;Let's take another look at our inspirational text messaging app. If you're not familiar with it, now would be a good time to have a quick
flick back to the previous two posts in the series. Go ahead. I'll wait :)&lt;/p&gt;

&lt;p&gt;So a customer has just signed up for our inspirational text message service and we're in the process of taking a payment. Our initial payment
processing code might look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task BillCustomer(Guid customerId, Money amount)
{
    await _bus.Send(new BillCustomerCommand(customerId, amount));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and our handler code might look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class BillCustomerCommandHandler: IHandleCommand&amp;lt;BillCustomerCommand&amp;gt;
{

    ...

    [PCIAuditable]
    public async Task Handle(BillCustomerCommand busCommand)
    {
        var customerId = busCommand.CustomerId;
        var amount = busCommand.Amount;

        var creditCardDetails = _secureVault.ExtractSecuredCreditCardDetails(customerId);

        var fraudCheckResponse = await _bus.Request(new FraudCheckRequest(creditCardDetails, amount));

        if (fraudCheckResponse.IsFraudulent)
        {
            await _bus.Publish(new FraudulentTransactionAttemptEvent(customerId, amount));
        }
        else
        {
            _cardGateway.ProcessPayment(creditCardDetails, amount);
            await _bus.Publish(new TransactionCompletedEvent(customerId, amount));
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what's going on here? We can see that our handler plucks card details from some kind of secure vault (this isn't a PCI-compliance
tutorial but nonetheless &lt;em&gt;please, please, please don't pass credit card numbers around in the clear&lt;/em&gt;) and performs a fraud check on
the potential transaction. The fraud check could involve the number of times we've seen that credit card number in the past few minutes,
the number of different names we've seen associated with the card, the variation in amounts... the list is endless. Let's assume for the
sake of this scenario that we have a great little service that just gives us a boolean IsFraudulent response and we can act on that.&lt;/p&gt;

&lt;h1&gt;Scenario #1: Single fraud-checking service&lt;/h1&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._03._05._1945._1000.Scenario_01.png/" alt="Single fraud-checking service"/&gt;&lt;/p&gt;

&lt;p&gt;In this scenario we have our app server talking to our fraud-checking service. We'll ignore our web server for now. It still exists but
doesn't play a part in this scenario.&lt;/p&gt;

&lt;p&gt;This is actually pretty straight-forward: we have one app server (or many; it doesn't matter) asking questions and one fraud-checking
service responding. But, as per usual, business is booming and we need to scale up in a hurry.&lt;/p&gt;

&lt;h1&gt;Scenario #2: Multiple fraud-checking services&lt;/h1&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._03._05._1945._1000.Scenario_02.png/" alt="Multiple fraud-checking services"/&gt;&lt;/p&gt;

&lt;p&gt;We've already done pretty much everything we need to do to scale this out. Our code doesn't need to change; our requestor doesn't need
to know that its requests are being handled by more than one responder and our responders don't need to know of each others' existence.
Just add more fraud checkers and we're all good.&lt;/p&gt;

&lt;p&gt;Only one instance of a fraud checker will receive a copy of each request so, as per our command pattern, we get load-balancing for free.&lt;/p&gt;

&lt;h1&gt;Scenario #3: Multicast request/response (a.k.a. Black-balling)&lt;/h1&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._03._05._1945._1000.Scenario_03.png/" alt="Black-balling"/&gt;&lt;/p&gt;

&lt;p&gt;Let's now say that we want our fraud checking to take a different shape. We don't have a single fraud-checking service any more; we
have a series of different fraud checkers that each do different things. One might do a "number of times this card number has been
seen in the last minute" check and another might do an "Is this a known-compromised card?" check.&lt;/p&gt;

&lt;p&gt;In this scenario, we might just want to ask "Does anybody object to this transaction?" and let different services reply as they will.&lt;/p&gt;

&lt;p&gt;The first cut of our billing handler could now look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class BillCustomerCommandHandler: IHandleCommand&amp;lt;BillCustomerCommand&amp;gt;
{

    ...

    [PCIAuditable]
    public async Task Handle(BillCustomerCommand busCommand)
    {
        var customerId = busCommand.CustomerId;
        var amount = busCommand.Amount;

        var creditCardDetails = _secureVault.ExtractSecuredCreditCardDetails(customerId);

        var fraudCheckResponses = await _bus.MulticastRequest(new FraudCheckRequest(creditCardDetails, amount),
                                                              TimeSpan.FromSeconds(1));

        if (fraudCheckResponses.Any())
        {
            await _bus.Publish(new FraudulentTransactionAttemptEvent(customerId, amount));
        }
        else
        {
            _cardGateway.ProcessPayment(creditCardDetails, amount);
            await _bus.Publish(new TransactionCompletedEvent(customerId, amount));
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's take a closer look.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var fraudCheckResponses = await _bus.MulticastRequest(new FraudCheckRequest(creditCardDetails, amount),
                                                      TimeSpan.FromSeconds(1));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This line of code is now fetching an IEnumerable&amp;lt;FraudCheckResponse&amp;gt; from our fraud checking services rather than a single response. We're
waiting for one second and then checking if there were any responses received. This means that we can now use a "black-ball" style pattern
(also known as "speak now or forever hold your peace") and simply allow any objectors to object within a specified timeout. If nobody objects
then the transaction is presumed non-fraudulent and we process it as per normal.&lt;/p&gt;

&lt;p&gt;One optimisation we can now make is that we can choose to take:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first response.&lt;/li&gt;
&lt;li&gt;The first n responses.&lt;/li&gt;
&lt;li&gt;All the responses within the specified timeout.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case, a slightly tidied version could look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var isFraudulent = await _bus.MulticastRequest(new FraudCheckRequest(creditCardDetails, amount),
                                                TimeSpan.FromSeconds(1))
                             .Any();

if (isFraudulent)
{
    await _bus.Publish(new FraudulentTransactionAttemptEvent(customerId, amount));
}
else
{
    _cardGateway.ProcessPayment(creditCardDetails, amount);
    await _bus.Publish(new TransactionCompletedEvent(customerId, amount));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the call to .Any(). Nimbus will &lt;em&gt;opportunistically return responses off the wire as soon as they arrive&lt;/em&gt;, meaning that your
calls to Enumerator.GetNext() will only block until there's another message waiting (or the timeout elapses). If we're only interested in
whether anyone replies, &lt;em&gt;any&lt;/em&gt; reply is enough for us to drop through immediately. If nobody replies saying that the transaction is
fraudulent then we simply drop through after one second and continue on our merry way.&lt;/p&gt;

&lt;p&gt;We could also use some kind of .Where(response &amp;eq;&amp;gt; response.LikelihoodOfFraud &amp;gt; 0.5M).Any() or even a quorum/voting system - it's entirely
up to you.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">eventing_with_nimbus</guid><link>http://uglybugger.org/software/post/eventing_with_nimbus</link><author>andrewh@uglybugger.org</author><title>Eventing with Nimbus</title><description>&lt;p&gt;In this article we're going to have a look at some of the eventing patterns we have in Nimbus&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 27 Feb 2014 19:45:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/eventing_with_nimbus" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_01a.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_01b.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_02.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_03a.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_03b.png/" /><a10:updated>2014-02-27T19:45:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;In this article we're going to have a look at some of the eventing patterns we have in Nimbus&lt;/p&gt;

&lt;p&gt;In &lt;a href="http://www.uglybugger.org/software/post/command_handling_with_nimbus"&gt;Command handling with Nimbus&lt;/a&gt; we saw how we deal with
fire-and-forget commands. This time around we care about events. They're still fire-and-forget, but the difference is that
whereas commands are consumed by only one consumer, events are consumed by multiple consumers. They're broadcast. Mostly.&lt;/p&gt;

&lt;p&gt;To reuse our scenario from our previous example, let's imagine that we have a subscription-based web site that sends inspirational
text messages to people's phones each morning.&lt;/p&gt;

&lt;h1&gt;Scenario #1: Monolithic web application (aka Another Big Ball of Mud&amp;trade;).&lt;/h1&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_01a.png/" alt="Big Ball of Mud"/&gt;&lt;/p&gt;

&lt;p&gt;We have a web application that handles everything from sign-up (ignoring for now where and how our data are stored) through to billing
and the actual sending of text messages. That's not so great in general, but let's have a look at a few simple rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When a customer signs up they should be sent a welcome text message.&lt;/li&gt;
&lt;li&gt;When a customer signs up we should bill them for their first month's subscription immediately.&lt;/li&gt;
&lt;li&gt;Every morning at 0700 local time each customer should be sent an inspirational text.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Business is great. (It really is amazing what people will pay for, isn't it?) Actually... business is so great that we need to start
scaling ourselves out. As we said before, let's ignore the bit about where we store our data and assume that there's just a repository
somewhere that isn't anywhere near struggling yet. Unfortunately, our web-server-that-does-all-the-things is starting to chug quite
a bit and we're getting a bit worried that we won't see out the month before it falls over.&lt;/p&gt;

&lt;p&gt;But hey, it's only a web server, right? And we know about web farms, don't we? Web servers are easy!&lt;/p&gt;

&lt;p&gt;We provision another one...&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_01b.png/" alt="Multiple servers means multiple text messages"/&gt;&lt;/p&gt;

&lt;p&gt;... and things start to go just a little bit wrong.&lt;/p&gt;

&lt;p&gt;Our sign-up still works fine - the customer will hit either one web server or the other - and our
welcome message and initial invoice get generated perfectly happily, too. Unfortunately, every
morning, &lt;strong&gt;our customer is now going to receive two messages&lt;/strong&gt;: one from each web server. This is
irritating for them and potentially quite expensive for us - we've just doubled our SMS delivery costs.
If we were to add a third (or tenth) web server then we'd end up sending our customer three (or ten)
texts per morning. This is going to get old &lt;em&gt;really&lt;/em&gt; quickly.&lt;/p&gt;

&lt;h1&gt;Scenario #2: Distributed architecture: a first cut&lt;/h1&gt;

&lt;p&gt;The obvious mistake here is that our web servers are responsible for way more than they should be. Web servers
should... well... serve web pages. Let's re-work our architecture to something sensible.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_02.png/" alt="Web servers backed by single application server"/&gt;&lt;/p&gt;

&lt;p&gt;We're getting there. This doesn't look half-bad except that we've now simply moved our problem of scaling
to one layer down. We can have as many web servers as we want, now, but as soon as we start scaling out
our app servers we run into the same problem as in Scenario #2.&lt;/p&gt;

&lt;h1&gt;Scenario 3: Distributed event handlers&lt;/h1&gt;

&lt;p&gt;Our next step is to separate some responsibilities onto different servers. Let's have a look at what that might
look like:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_03a.png/" alt="Single distributed worker for each action"/&gt;&lt;/p&gt;

&lt;p&gt;This looks pretty good. We've split the load away from our app server onto a couple of different servers that
have their own responsibilities.&lt;/p&gt;

&lt;p&gt;This is the first example that's actually worth writing some sample code for. Our code in this scenario could
look something like this in our sign-up logic:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task SignUp(CustomerDetails newCustomer)
{
    // do sign-up stuff
    await _bus.Publish(new CustomerSignedUpEvent(newCustomer));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and with these two handlers for the CustomerSignedUpEvent:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namespace WhenACustomerSignsUp
{
    public class SendThemAWelcomeEmail: IHandleMulticastEvent&amp;lt;CustomerSignedUpEvent&amp;gt;
    {
        public async Task Handle&amp;lt;CustomerSignedUpEvent&amp;gt;(CustomerSignedUpEvent busEvent)
        {
            // send the customer an email
        }
    }

    public class GenerateAnInvoiceForThem: IHandleMulticastEvent&amp;lt;CustomerSignedUpEvent&amp;gt;
    {
        public async Task Handle&amp;lt;CustomerSignedUpEvent&amp;gt;(CustomerSignedUpEvent busEvent)
        {
            // generate an invoice for the customer
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We're actually in pretty good shape here. But business is, by now, booming, and we're generating more invoices
than our single invoicer can handle. So we scale it out...&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._27._1945._1000.Scenario_03b.png/" alt="Multiple distributed workers for some handlers"/&gt;&lt;/p&gt;

&lt;p&gt;... and wow, but do the phones start ringing. Can you spot what we've done? Yep, that's right - &lt;strong&gt;every instance
of our invoicer is happily sending our customers an invoice&lt;/strong&gt;. When we had one invoicer, each customer received
one invoice and all was well. When we moved to two invoicers, our customers each received two invoices for the
same service. If we were to scale to ten (or a thousand) invoicers then our customers would receive ten (or
a thousand) invoices.&lt;/p&gt;

&lt;p&gt;Our customers are not happy.&lt;/p&gt;

&lt;h1&gt;Scenario #4: Competing handlers&lt;/h1&gt;

&lt;p&gt;Here's where we introduce Nimbus' concept of a competing event handler. In this example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class GenerateAnInvoiceForThem: IHandleMulticastEvent&amp;lt;CustomerSignedUpEvent&amp;gt;
{
    public async Task Handle&amp;lt;CustomerSignedUpEvent&amp;gt;(CustomerSignedUpEvent busEvent)
    {
        // generate an invoice for the customer
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;we implement the IHandleMulticastEvent&amp;lt;&gt; interface. This means that every instance of our handler will receive
a copy of the message. That's great for updating read models, caches and so on, but not so great for taking
further action based on events.&lt;/p&gt;

&lt;p&gt;Thankfully, there's a simple solution. In this case we want to use a &lt;em&gt;competing&lt;/em&gt; event handler, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class GenerateAnInvoiceForThem: IHandleCompetingEvent&amp;lt;CustomerSignedUpEvent&amp;gt;
{
    public async Task Handle&amp;lt;CustomerSignedUpEvent&amp;gt;(CustomerSignedUpEvent busEvent)
    {
        // generate an invoice for the customer
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By telling Nimbus that we only want a single instance of each type of service to receive this event, we can
ensure that our customers will only receive one invoice no matter much much we scale out.&lt;/p&gt;

&lt;p&gt;A key concept to grasp here is that a single instance of &lt;em&gt;each service type&lt;/em&gt; will receive the message. In other
words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exactly one instance of our invoicer will see the event&lt;/li&gt;
&lt;li&gt;Exactly one instance of our welcomer will see the event&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Combining multicast and competing event handlers&lt;/h1&gt;

&lt;p&gt;It's entirely possible that our invoicer will want to keep an up-to-date list of customers for all sorts of
reasons. In this case, it's likely that our invoicer will want to receive a copy of the CustomerSignedUpEvent
even if it's not the instance that's going to generate an invoice this time around.&lt;/p&gt;

&lt;p&gt;Our invoicer code might now look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namespace WhenACustomerSignsUp
{
    public class GenerateAnInvoiceForThem: IHandleCompetingEvent&amp;lt;CustomerSignedUpEvent&amp;gt;
    {
        public async Task Handle&amp;lt;CustomerSignedUpEvent&amp;gt;(CustomerSignedUpEvent busEvent)
        {
            // only ONE instance of me will have this handler called
        }
    }

    public class RecordTheCustomerInMyLocalDatabase: IHandleMulticastEvent&amp;lt;CustomerSignedUpEvent&amp;gt;
    {
        public async Task Handle&amp;lt;CustomerSignedUpEvent&amp;gt;(CustomerSignedUpEvent busEvent)
        {
            // EVERY instance of me will have this handler called.
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So there we go. We now have a loosely-coupled system that we can scale out massively on demand, without
worrying about concurrency issues.&lt;/p&gt;

&lt;h1&gt;This is awesome! But how do we send our inspirational messages every morning?&lt;/h1&gt;

&lt;p&gt;Sneak peek: have a look at the SendAt(...) method on IBus. We'll cover that in another article shortly.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">command_handling_with_nimbus</guid><link>http://uglybugger.org/software/post/command_handling_with_nimbus</link><author>andrewh@uglybugger.org</author><title>Command handling with Nimbus</title><description>&lt;p&gt;We've had a quick introduction to Nimbus, so let's look at some messaging patterns in a bit more detail.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Wed, 26 Feb 2014 20:00:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/command_handling_with_nimbus" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._26._2000._1000.Scenario_01.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._26._2000._1000.Scenario_02.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2014._2014._02._26._2000._1000.Scenario_03.png/" /><a10:updated>2014-02-26T20:00:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;We've had a quick introduction to Nimbus, so let's look at some messaging patterns in a bit more detail.&lt;/p&gt;

&lt;p&gt;Picture this: you're running a successful company that sends people a "Good morning!" text message every day.
(It's amazing what people will pay for, isn't it?) People pay $5/month for your inspirational text message
and business is great.&lt;/p&gt;

&lt;p&gt;Let's say you have some clever logic that decides what to send people in the morning. Let's call that the Thinker.
The Thinker is quite fast and it can churn out many inspirational thoughts per second. The Thinker code initially
looks something like this:&lt;/p&gt;

&lt;h1&gt;Scenario 1: Big Ball of Mud&lt;/h1&gt;

&lt;pre&gt;&lt;code&gt;public class Thinker
{
    private readonly SMSGateway _smsGateway;

    public Thinker(SMSGateway smsGateway)
    {
        _smsGateway = smsGateway;
    }

    public void SendSomethingInspirational(Subscriber[] subscribers)
    {
        foreach (var subscriber in subscribers)
        {
            var inspirationalThought = ThinkOfSomethingNiceToSay();
            _smsGateway.SendSMS(subscriber.PhoneNumber, inspirationalThought);
        }
    }

    private string ThinkOfSomethingNiceToSay()
    {
        throw new NotImplementedException();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which means our logical design looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._26._2000._1000.Scenario_01.png/" alt="Thinker coupled to SMS gateway"/&gt;&lt;/p&gt;

&lt;p&gt;That's a bit silly - we've coupled our Thinker to our SMS gateway, which means two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Thinker can only generate messages as fast as the SMS gateway can receive them; and&lt;/li&gt;
&lt;li&gt;If the SMS gateway falls down, the Thinker can't work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's try decoupling them and see how we go.&lt;/p&gt;

&lt;h1&gt;Scenario 2: Decoupled Thinker from SMS gateway&lt;/h1&gt;

&lt;p&gt;In this scenario, our code looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Thinker
{
    private readonly IBus _bus;

    public Thinker(IBus bus)
    {
        _bus = bus;
    }

    public void SendSomethingInspirational(Subscriber[] subscribers)
    {
        foreach (var subscriber in subscribers)
        {
            var inspirationalThought = ThinkOfSomethingNiceToSay();
            _bus.Send(new SendSMSCommand(subscriber.PhoneNumber, inspirationalThought));
        }
    }

    private string ThinkOfSomethingNiceToSay()
    {
        throw new NotImplementedException();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and we have a handler that looks something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class SendSMSCommandHandler: IHandleCommand&amp;lt;SendSMSCommand&amp;gt;
{
    private readonly SMSGateway _smsGateway;

    public SendSMSCommandHandler(SMSGateway smsGateway)
    {
        _smsGateway = smsGateway;
    }

    public async Task Handle&amp;lt;T&amp;gt;(T)
    {
    }

    public async Task Handle(SendSMSCommand busCommand)
    {
        _smsGateway.SendSMS(busCommand.PhoneNumber, busCommand.Message);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our topology now looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._26._2000._1000.Scenario_02.png/" alt="Decoupled Thinker from SMS sender"/&gt;&lt;/p&gt;

&lt;p&gt;This is much better. In this scenario, our Thinker can generate inspirational thoughts as fast as it can think and
simply queue them for delivery. If the SMS gateway is slow or goes down, the Thinker isn't affected and the texts
can be delivered later by the retry logic built into the bus itself.&lt;/p&gt;

&lt;p&gt;What? Retry logic? Did we forget to mention that we get that for free? If your SendSMSCommandHandler class blows
up when it's trying to send a message, don't worry about handling exceptions or failing gracefully. Just fail. Nimbus
will catch any exception you throw and automatically put the message back onto the queue for another attempt. If the
gateway has a long outage, there are compensatory actions we can take pretty cheaply, too. (Dead letter queues are a
topic for another day, but they're there.)&lt;/p&gt;

&lt;p&gt;So... business is great, and we've hit the front page of Reddit. Everyone wants our inspirational thoughts. As far
as our Thinker is concerned, that's no problem - it can generate thousands of happy thoughts per second all morning.
Our telco's SMS delivery gateway looks like it's getting a bit swamped, though. Even though we've decoupled our Thinker
from our SMS sender, messages are still taking too long to arrive and the SMS gateway itself is just too slow.&lt;/p&gt;

&lt;h1&gt;Scenario 3: Scaling out our command handlers&lt;/h1&gt;

&lt;p&gt;This is where we discover that &lt;em&gt;distributed systems are pure awesome&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When designed well, a good system will allow us to scale parts out as necessary. We're going to scale out our SMS
sending architecture and solve our throughput problem. All we need to do is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spin up another SendSMSCommandHandler server; and&lt;/li&gt;
&lt;li&gt;Point it at a different telco's SMS gateway.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Job done.&lt;/p&gt;

&lt;p&gt;What - we didn't have to reconfigure our Thinker to send to two gateways? And what about the first SMS gateway? Doesn't
it need to know about load balancing? Well... no.&lt;/p&gt;

&lt;p&gt;This is what our system now looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2014._2014._02._26._2000._1000.Scenario_03.png/" alt="Scaled out SMS sender"/&gt;&lt;/p&gt;

&lt;p&gt;Stuff we get for free out of this design includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero code changes to our Thinker&lt;/li&gt;
&lt;li&gt;Zero code changes to our existing SMS sender&lt;/li&gt;
&lt;li&gt;Automatic, in-built load-balancing between our two SMS senders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implicit load-balancing is part and parcel of a queue-based system like Nimbus. Under the covers, there's a message queue
(we'll talk about queues soon) for each type of command. Every application instance that can handle that type of command
just pulls messages from the head of the command queue as fast as it can. This means that there's no load-balancer to
configure and there are no pools to balance - it all just works. If one handler is faster than another (say, for instance, you
have different hardware between the two) then the load will be automatically distributed between the two just because
each node will pull commands at a different rate.&lt;/p&gt;

&lt;p&gt;How cool is that?&lt;/p&gt;

&lt;p&gt;Stay tuned for more messaging patterns and how to use them with Nimbus.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">handler_interface_changes_in_nimbus_1_1</guid><link>http://uglybugger.org/software/post/handler_interface_changes_in_nimbus_1_1</link><author>andrewh@uglybugger.org</author><title>Handler interface changes in Nimbus 1.1</title><description>&lt;p&gt;We've tweaked the handler interfaces slightly for the 1.1 release of &lt;a href="https://github.com/DamianMac/Nimbus"&gt;Nimbus&lt;/a&gt;.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 25 Feb 2014 13:45:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/handler_interface_changes_in_nimbus_1_1" /><a10:updated>2014-02-25T13:45:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;We've tweaked the handler interfaces slightly for the 1.1 release of &lt;a href="https://github.com/DamianMac/Nimbus"&gt;Nimbus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the 1.0 series, handlers were void methods. I admit it: this was a design flaw. We thought it would make for a more simple
introduction to using the bus - and it did - but the trade-off was that it was much more complicated to do clever stuff.&lt;/p&gt;

&lt;p&gt;Consider this handler method:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void Handle(DoFooCommand busCommand)
{
    DoFoo();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pretty straight-forward, right? Except what happens when doing foo requires us to publish an event afterwards?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void Handle(DoFooCommand busCommand)
{
    DoFoo();
    _bus.Publish(new FooWasDoneEvent());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That doesn't look so bad, except that we've missed the fact that _bus.Publish actually returns a Task and executes asynchronously.
What if doing foo required us to ask a question first?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void Handle(DoFooCommand busCommand)
{
    var result = await _bus.Request(new WhoLastDidFooRequest());
    DoFoo(result.WhoDunnit);
    _bus.Publish(new FooWasDoneEvent());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now things are a bit more complicated. The above method won't compile, as it's not marked as async. But there's a simple fix, right?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async void Handle(DoFooCommand busCommand)
{
    var result = await _bus.Request(new WhoLastDidFooRequest());
    DoFoo(result.WhoDunnit);
    await _bus.Publish(new FooWasDoneEvent());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Problem solved. Except that it's not. Because although our code will compile and execute happily, what's going on under the covers
is that the Nimbus command dispatcher has no easy way of waiting for your async handler method to complete. As far as the dispatcher
is concerned, your handler executed successfully - and really quickly - and we then mark the message as successfully handled.&lt;/p&gt;

&lt;p&gt;Think about what happens in this example case below (courtesy of the immortal &lt;a href="http://kozmic.net/"&gt;Krzysztof Kozmic&lt;/a&gt; via
&lt;a href="https://github.com/DamianMac/Nimbus/issues/50"&gt;this GitHub issue&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async void Handle(DoFooCommand busCommand)
{
    throw new InvalidOperationException("HA HA HA, you can't catch me!");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As far as the dispatcher is concerned, your handler method executed just fine. And now we've broken our delivery guarantee. Not so good.&lt;/p&gt;

&lt;p&gt;The fix for this is simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task Handle(DoFooCommand busCommand)
{
    throw new InvalidOperationException("HA HA HA, you can't catch me!");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Done. Your method now returns a Task - which the Nimbus dispatcher can await - and if your handler throws then we know about it and can
handle it appropriately. So your actual handler would look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task Handle(DoFooCommand busCommand)
{
    var result = await _bus.Request(new WhoLastDidFooRequest());
    DoFoo(result.WhoDunnit);
    await _bus.Publish(new FooWasDoneEvent());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So why is this worth an article? Because in order to make this change, we've had to alter the IHandleCommand&lt;T&gt;, IHandleRequest&lt;T&gt; etc.
interfaces to have the handler methods return tasks. This:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface IHandleCommand&amp;lt;TBusCommand&amp;gt; where TBusCommand : IBusCommand
{
    void Handle(TBusCommand busCommand);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;is now this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface IHandleCommand&amp;lt;TBusCommand&amp;gt; where TBusCommand : IBusCommand
{
    Task Handle(TBusCommand busCommand);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This means that when you upgrade to the 1.1 versons of Nimbus you'll need to do a quick Ctrl-Shift-H for all your instances of "void Handle("
and replace them with "Task Handle(".&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">nimbus_what_is_it_and_why_should_i_care</guid><link>http://uglybugger.org/software/post/nimbus_what_is_it_and_why_should_i_care</link><author>andrewh@uglybugger.org</author><title>Nimbus: What is it and why should I care?</title><description>&lt;p&gt;So &lt;a href="http://damianm.com"&gt;Damian Maclennan&lt;/a&gt; and I built a thing. We're quite proud of it.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sun, 23 Feb 2014 15:55:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/nimbus_what_is_it_and_why_should_i_care" /><a10:updated>2014-02-23T15:55:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;So &lt;a href="http://damianm.com"&gt;Damian Maclennan&lt;/a&gt; and I built a thing. We're quite proud of it.&lt;/p&gt;

&lt;p&gt;At my current employer, Readify, we deal with a large number of problems whose solution is a distributed
system of one kind or another. We've used several messaging frameworks in past projects - everything from raw MSMQ
through to RabbitMQ, MassTransit, NServiceBus and all sorts of other odds and ends.&lt;/p&gt;

&lt;p&gt;All of them had their weak points and we kept finding that we had to write custom code no matter which framework
we chose.&lt;/p&gt;

&lt;p&gt;So... &lt;a href="https://twitter.com/damianm"&gt;@damianm&lt;/a&gt; and I built a thing. That thing is called
&lt;a href="https://github.com/DamianMac/Nimbus"&gt;Nimbus&lt;/a&gt;. And here's why you want to use it.&lt;/p&gt;

&lt;h1&gt;What is Nimbus?&lt;/h1&gt;

&lt;p&gt;Nimbus is a nice, easy-to-use service bus framework built on top of the Azure Message Bus and Windows Service Bus stack.&lt;/p&gt;

&lt;p&gt;It runs on both cloud-based service bus instances and on-premises installations of Windows service bus and will happily support federation between the two.&lt;/p&gt;

&lt;h1&gt;Why do I want it?&lt;/h1&gt;

&lt;h2&gt;It's easy to get up and running&lt;/h2&gt;

&lt;p&gt;Getting an instance up and running is fast and easy. You'll need an Azure account (free) and a service bus namespace if you don't have a local Windows Service Bus installation, after which:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package Nimbus
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;followed by some simple configuration code (just copy/paste and change your application name and connection string):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var connectionString = ConfigurationManager.AppSettings["AzureConnectionString"];
var typeProvider = new AssemblyScanningTypeProvider(Assembly.GetExecutingAssembly());
var messageHandlerFactory = new DefaultMessageHandlerFactory(typeProvider);

var bus = new BusBuilder().Configure()
                            .WithNames("TODO Change this to your application's name", Environment.MachineName)
                            .WithConnectionString(connectionString)
                            .WithTypesFrom(typeProvider)
                            .WithDefaultHandlerFactory(messageHandlerFactory)
                            .WithDefaultTimeout(TimeSpan.FromSeconds(10))
                            .Build();
bus.Start();
return bus;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's it. You're up and running.&lt;/p&gt;

&lt;h2&gt;It's &lt;em&gt;really&lt;/em&gt; easy to use&lt;/h2&gt;

&lt;p&gt;Want to send a command on the bus?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task SendSomeCommand()
{
    await _bus.Send(new DoSomethingCommand());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Want to handle that command?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class DoSomethingCommandHandler: IHandleCommand&amp;lt;DoSomethingCommand&amp;gt;
{
    public async Task Handle(DoSomethingCommand command)
    {
        //TODO: Do something useful here.
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;It supports both simple and complicated messaging patterns&lt;/h2&gt;

&lt;p&gt;Nimbus supports simple commanding and publish/subscribe in a way that you're probably familiar with if you've ever used NServiceBus or MassTransit.&lt;/p&gt;

&lt;p&gt;It also supports an elegant, awaitable request/response, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var response = await _bus.Request(new HowLongDoPizzasTakeRequest());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It also supports much more advanced patterns like publish and competing subscribe and multicast request/response. I'll cover each of these in subsequent articles.&lt;/p&gt;

&lt;h2&gt;Did we mention that it's free? And open-source? And awesome?&lt;/h2&gt;

&lt;p&gt;There's no "one message per second" limit or anything else with Nimbus. It's free. And open source. You can clone it for yourself if you want - and we'd love it if you did and had a play with it.&lt;/p&gt;

&lt;p&gt;If you'd like a feature, ask and we'll see what we can do. If you need a feature in a hurry, you can just code it up and send us a pull request.&lt;/p&gt;

&lt;p&gt;Please... have a look and let us know what you think.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">rss_as_a_primary_source_of_truth</guid><link>http://uglybugger.org/software/post/rss_as_a_primary_source_of_truth</link><author>andrewh@uglybugger.org</author><title>RSS as a primary source of truth</title><description>&lt;p&gt;I'm experimenting with making RSS my authoritative source for blog posts.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 18 Feb 2014 18:02:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/rss_as_a_primary_source_of_truth" /><a10:updated>2014-02-18T18:02:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I'm experimenting with making RSS my authoritative source for blog posts.&lt;/p&gt;

&lt;p&gt;I was thinking the other day about how RSS still seems to be the poor second cousin of most
blogging platforms. Everything (well, everything civilised) generates RSS feeds but it's done
as an after-thought, not as the primary experience.&lt;/p&gt;

&lt;p&gt;As a software engineer, I tend to consume most content directly from my RSS reader. I want that to be
the most polished experience. I also want to be able to set a bunch of ifttt.com recipies for different
feeds, including feeds of my own activities.&lt;/p&gt;

&lt;p&gt;I've also re-jigged the BlogMonster library to generate RSS as its primary source of truth. It still
works if you want to stick it on a web page, of course, but the underlying model is now a SyndicationFeed
and your individual blog posts are SyndicationItem instances. You can, of course, simply bind those to a
Razor view.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">introducing_configinjector</guid><link>http://uglybugger.org/software/post/introducing_configinjector</link><author>andrewh@uglybugger.org</author><title>Introducing ConfigInjector</title><description>&lt;p&gt;So I've been using this pattern for a while and promising to blog it for almost as long.&lt;/p&gt;

&lt;p&gt;Code is on &lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;GitHub&lt;/a&gt;; package is on &lt;a href="https://www.nuget.org/packages/ConfigInjector/"&gt;NuGet&lt;/a&gt;. Here you go :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Fri, 04 Oct 2013 13:35:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/introducing_configinjector" /><a10:updated>2013-10-04T13:35:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;So I've been using this pattern for a while and promising to blog it for almost as long.&lt;/p&gt;

&lt;p&gt;Code is on &lt;a href="https://github.com/uglybugger/ConfigInjector"&gt;GitHub&lt;/a&gt;; package is on &lt;a href="https://www.nuget.org/packages/ConfigInjector/"&gt;NuGet&lt;/a&gt;. Here you go :)&lt;/p&gt;

&lt;h2&gt;How application settings &lt;em&gt;should&lt;/em&gt; look:&lt;/h2&gt;

&lt;p&gt;Here's a class that needs some configuration settings:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class EmailSender : IEmailSender
{
    private readonly SmtpHostConfigurationSetting _smtpHost;
    private readonly SmtpPortConfigurationSetting _smtpPort;

    public EmailSender(SmtpHostConfigurationSetting smtpHost,
                        SmtpPortConfigurationSetting smtpPort)
    {
        _smtpHost = smtpHost;
        _smtpPort = smtpPort;
    }

    public void Send(MailMessage message)
    {
        // NOTE the way we can use our strongly-typed settings directly as
        // a string and int respectively
        using (var client = new SmtpClient(_smtpHost, _smtpPort))
        {
            client.Send(message);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's how we declare the settings:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// This will give us a strongly-typed string setting.
public class SmtpHostConfigurationSetting : ConfigurationSetting&amp;lt;string&amp;gt;
{
}

// This will give us a strongly-typed int setting.
public class SmtpPortConfigurationSetting : ConfigurationSetting&amp;lt;int&amp;gt;
{
    protected override IEnumerable&amp;lt;string&amp;gt; ValidationErrors(int value)
    {
        if (value &amp;lt;= 0) yield return "TCP port numbers cannot be negative.";
        if (value &amp;gt; 65535) yield return "TCP port numbers cannot be greater than 65535.";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here's how we set them in our [web|app].config:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;appSettings&amp;gt;
    &amp;lt;add key="SmtpHostConfigurationSetting" value="localhost" /&amp;gt;
    &amp;lt;add key="SmtpPortConfigurationSetting" value="25" /&amp;gt;
  &amp;lt;/appSettings&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... and here's how we provide mock values for them in our unit tests:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var smtpHost = new SmtpHostConfigurationSetting {Value = "smtp.example.com"};
var smtpPort = new SmtpPortConfigurationSetting {Value = 25};

var emailSender = new EmailSender(smtpHost, smtpPort);

emailSender.Send(someTestMessage);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Getting started&lt;/h2&gt;

&lt;p&gt;In the NuGet Package Manager Console, type:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package ConfigInjector
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then run up the configurator like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ConfigurationConfigurator
    .RegisterConfigurationSettings()
    .FromAssemblies(/* TODO: Provide a list of assemblies to scan for configuration settings here  */)
    .RegisterWithContainer(configSetting =&amp;gt; /* TODO: Register this instance with your container here */ )
    .DoYourThing();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can pick your favourite container from the list below or roll your own.&lt;/p&gt;

&lt;h3&gt;Getting started with Autofac&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;var builder = new ContainerBuilder();

builder.RegisterType&amp;lt;DeepThought&amp;gt;();

ConfigurationConfigurator
    .RegisterConfigurationSettings()
    .FromAssemblies(typeof (DeepThought).Assembly)
    .RegisterWithContainer(configSetting =&amp;gt; builder.RegisterInstance(configSetting)
                                                   .AsSelf()
                                                   .SingleInstance())
    .DoYourThing();

return builder.Build();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Getting started with Castle Windsor&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;var container = new WindsorContainer();

container.Register(Component.For&amp;lt;DeepThought&amp;gt;());

ConfigurationConfigurator
    .RegisterConfigurationSettings()
    .FromAssemblies(typeof (DeepThought).Assembly)
    .RegisterWithContainer(configSetting =&amp;gt; container.Register(Component.For(configSetting.GetType())
                                                                        .Instance(configSetting)
                                                                        .LifestyleSingleton()))
    .DoYourThing();

return container;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Getting started with Ninject&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;var kernel = new StandardKernel();

kernel.Bind&amp;lt;DeepThought&amp;gt;().ToSelf();

ConfigurationConfigurator
    .RegisterConfigurationSettings()
    .FromAssemblies(typeof (DeepThought).Assembly)
    .RegisterWithContainer(configSetting =&amp;gt; kernel.Bind(configSetting.GetType())
                                                  .ToConstant(configSetting))
    .DoYourThing();

return kernel;
&lt;/code&gt;&lt;/pre&gt;
</a10:content></item><item><guid isPermaLink="false">quick_demonstration_of_continuous_delivery</guid><link>http://uglybugger.org/software/post/quick_demonstration_of_continuous_delivery</link><author>andrewh@uglybugger.org</author><title>Quick demonstration of continuous delivery</title><description>&lt;p&gt;I'm running &lt;a href="https://github.com/Readify/MakingLegacyApplicationsAwesome"&gt;Readify's Making Legacy Apps Awesome&lt;/a&gt;
workshop right now.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Wed, 24 Jul 2013 08:51:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/quick_demonstration_of_continuous_delivery" /><a10:updated>2013-07-24T08:51:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I'm running &lt;a href="https://github.com/Readify/MakingLegacyApplicationsAwesome"&gt;Readify's Making Legacy Apps Awesome&lt;/a&gt;
workshop right now.&lt;/p&gt;

&lt;p&gt;Part of making legacy apps easy to maintain is getting a deployment pipeline functioning.&lt;/p&gt;

&lt;p&gt;This post is a quick demo of how easy it &lt;em&gt;should&lt;/em&gt; be to deploy code
into production.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Say hello to the nice people of the world, children :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">the_story_so_far_a_fairy_tale</guid><link>http://uglybugger.org/software/post/the_story_so_far_a_fairy_tale</link><author>andrewh@uglybugger.org</author><title>The story so far: a fairy tale.</title><description>&lt;p&gt;I've just pushed the latest to the &lt;a href="http://readify.net/our-events?event-id=45EDF1AF-782E-4089-85A0-9E89F50D4865"&gt;Making Legacy Apps Awesome&lt;/a&gt; workshop's &lt;a href="https://github.com/Readify/MakingLegacyApplicationsAwesome"&gt;Git repo&lt;/a&gt;.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 11 Apr 2013 21:23:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/the_story_so_far_a_fairy_tale" /><a10:updated>2013-04-11T21:23:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I've just pushed the latest to the &lt;a href="http://readify.net/our-events?event-id=45EDF1AF-782E-4089-85A0-9E89F50D4865"&gt;Making Legacy Apps Awesome&lt;/a&gt; workshop's &lt;a href="https://github.com/Readify/MakingLegacyApplicationsAwesome"&gt;Git repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You'll note that the app is actually quite small. You could say that that's because &lt;a href="http://kozmic.net/"&gt;Krzysztof&lt;/a&gt; and I felt dirty writing it
(which we did) but in reality it's small because we're going to cover a large number of topics in two days and we don't want people
getting bogged down in doing the same repetitive refactorings time after time.&lt;/p&gt;

&lt;p&gt;The code's probably going to undergo a few tweaks before the workshop but it's worth cloning now for links, download
instructions and other odds and ends.&lt;/p&gt;

&lt;p&gt;Oh, and there's a story.&lt;/p&gt;

&lt;h1&gt;The story so far...&lt;/h1&gt;

&lt;p&gt;Once upon a time in land far, far away, there was a little town called Derp Town.&lt;/p&gt;

&lt;p&gt;The citizens of Derp Town were a proud bunch, and one day they decided that they would create
their own university for the betterment of all human-kind (and, of course, to show those snobby
villagers over in Herp Town that they were not to be outdone).&lt;/p&gt;

&lt;p&gt;The villagers were a poor but sincere lot and they were determined to build their university the
Right Way&amp;#8482;. They formed a Board of Directors (this was Modern Times, after all, and the
old, fuddy-duddy Academic Council could leave their robes at home, &lt;em&gt;thankyouverymuch&lt;/em&gt;) and resolved
that their university would do the best of everything. It would be the most grand university in all
the land. (Being more grand than the nearby Herp College, of course, was a thought that occurred to
&lt;em&gt;nobody at all&lt;/em&gt; and the citizens would not have &lt;em&gt;dreamed&lt;/em&gt; of slighting their neighbours.)&lt;/p&gt;

&lt;p&gt;The university had no technology budget or staff to speak of yet, but that was not to stop them
from becoming the market leader in technological engagement with their students, who would travel
over all the lands and across all the seas to study at such a prestigious institution and gaze
with awe upon the wonder that was Derp University's... &lt;strong&gt;Enrolment Portal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Undeterred by their lack of suitably qualified engineers, and being a resourceful lot, they asked the
teenage child of the Dean of the Rainbows and Unicorns faculty to write their grand portal using the
latest and greatest technologies of the time. It would, they claimed, be a sight to behold.&lt;/p&gt;

&lt;p&gt;The portal was unveiled, and all gasped with wonder, for it was great. The villagers rejoiced and
praised the Board of Directors for their foresight and wisdom.&lt;/p&gt;

&lt;p&gt;Of course, there were a few hitches along the way; a few things that went mysteriously wrong and a
couple of enrolments that got eaten by the Terrible Greedy Fossifoo who snuck into the system one
night, but by and large the villagers were pleased.&lt;/p&gt;

&lt;p&gt;One fine day, the Dean's teenage offspring decided to embark upon an adventure. The child packed
some belongings, said some good-byes and set off to find the Ivory Tower of the Architect. The
villagers rejoiced, for the Architect would surely praise their Enrolment Portal and speak of them
in tones of wonder. (And not at all smug, of course, that Herp College had never seen or spoken to
the Architect or been so praised.)&lt;/p&gt;

&lt;p&gt;During the time in which the Dean's teenage child and creator of the Enrolment Portal was adventuring,
it came time for the villagers to extend the portal. While it had been quite good for the first
semester of Derp University's existence, a few (very minor, of course) shortcomings had come to
light. Although the portal's author had been the only one to know all the ins and outs of the system,
the villagers were confident that these shortcomings could surely be quickly addressed by the villagers
themselves if they merely put their minds to it.&lt;/p&gt;

&lt;p&gt;Weeks came and went; mid-term examinations happened; students caroused; the leaves began to brown and
the seasons to turn. The villagers were no closer to making the required changes to their vaunted
portal, and time was running out.&lt;/p&gt;

&lt;p&gt;The villagers knew fear.&lt;/p&gt;

&lt;p&gt;The villagers worked, and patched, and cobbled, and hacked, and eventually they came to
accept that their vaunted Enrolment Portal was unknowable by any but its author, and its author was
nowhere to be found.&lt;/p&gt;

&lt;p&gt;The villagers knew despair.&lt;/p&gt;

&lt;p&gt;In their misery, the villagers came to accept that what they had created for their university had not
been Done Right This Time&amp;#8482;, but instead was a Brand New Legacy Application&amp;#8482;.&lt;/p&gt;

&lt;p&gt;A young traveller from far away chose this moment to enter the village, seeking food and shelter. The
traveller carried in their luggage a USB stick, upon which the villagers discovered wondrous tomes
of knowledge and tools of refactoring. In desperation, the villagers begged the traveller to renew their
hopes and restore their grand Enrolment Portal to its former glory.&lt;/p&gt;

&lt;p&gt;Despite being young and inexperienced, the traveller took pity upon the villagers and agreed to aid them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To be continued...&lt;/em&gt;&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">almost_sold_out_only_5_tickets_left_to_making_legacy_apps_awesome</guid><link>http://uglybugger.org/software/post/almost_sold_out_only_5_tickets_left_to_making_legacy_apps_awesome</link><author>andrewh@uglybugger.org</author><title>Almost sold out: only 5 tickets left to Making Legacy Apps Awesome.</title><description>&lt;p&gt;We're almost sold out for the &lt;a href="http://readify.net/our-events?event-id=45EDF1AF-782E-4089-85A0-9E89F50D4865"&gt;Making Legacy Apps Awesome&lt;/a&gt; workshop - there
are only five tickets left.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 11 Apr 2013 14:23:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/almost_sold_out_only_5_tickets_left_to_making_legacy_apps_awesome" /><a10:updated>2013-04-11T14:23:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;We're almost sold out for the &lt;a href="http://readify.net/our-events?event-id=45EDF1AF-782E-4089-85A0-9E89F50D4865"&gt;Making Legacy Apps Awesome&lt;/a&gt; workshop - there
are only five tickets left.&lt;/p&gt;

&lt;p&gt;I'll be pushing some code to the &lt;a href="https://github.com/Readify/MakingLegacyApplicationsAwesome"&gt;GitHub repository&lt;/a&gt; soon. &lt;a href="http://kozmic.net/"&gt;Krzysztof&lt;/a&gt; and
I almost cried when we wrote this code for you all, so stay tuned for our hand-crafted disaster :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">two_day_workshop_making_legacy_applications_awesome</guid><link>http://uglybugger.org/software/post/two_day_workshop_making_legacy_applications_awesome</link><author>andrewh@uglybugger.org</author><title>Two-day workshop: Making Legacy Applications Awesome</title><description>&lt;p&gt;I'm running a &lt;a href="http://readify.net/our-events?event-id=45EDF1AF-782E-4089-85A0-9E89F50D4865"&gt;two-day Readify workshop&lt;/a&gt; with
&lt;a href="http://kozmic.net/"&gt;Krzysztof Kozmic&lt;/a&gt; in Brisbane in April.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 12 Mar 2013 20:53:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/two_day_workshop_making_legacy_applications_awesome" /><a10:updated>2013-03-12T20:53:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I'm running a &lt;a href="http://readify.net/our-events?event-id=45EDF1AF-782E-4089-85A0-9E89F50D4865"&gt;two-day Readify workshop&lt;/a&gt; with
&lt;a href="http://kozmic.net/"&gt;Krzysztof Kozmic&lt;/a&gt; in Brisbane in April.&lt;/p&gt;

&lt;p&gt;If you've ever had the privilege of maintaining a legacy application once it's been in production for a while, you'll
likely appreciate some of the lessons on offer.&lt;/p&gt;

&lt;p&gt;Once in a blue moon software engineers have the privilege of embarking on a new project: to do away with the old; to
start over; to Do It Right This Time™. More often, software developers are saddled with existing legacy applications
with poor code quality, no regression tests to speak of and frustrated, angry customers and stakeholders to boot. This
downward spiral is all too common in the software industry and it would appear that there’s no way out – or is there?&lt;/p&gt;

&lt;p&gt;What makes a legacy application? Every big ball of mud had its origins in a green-fields project. Where do we draw the
distinction? And why does it matter? Isn’t every application a legacy after it’s released? How do we maintain our software
so that "legacy" isn’t a bad word any more – and how can we improve our existing software to that standard?&lt;/p&gt;

&lt;p&gt;This two-day workshop will start with the exploration of an utter disaster of a codebase. We’ll investigate how it got into
that state in the first place, decide on an end goal, devise a rough strategy to get there and then fire up the compiler.
We’ll finish the workshop with a well-factored, usable, maintainable application and a whole lot of appreciation for the
tools available to us.&lt;/p&gt;

&lt;p&gt;At each stage of the journey you’ll be given the opportunity to have a go at refactoring the application to the next point,
after which you’ll be able to pull that completed exercise from GitHub. You will be writing code and you won’t be left
behind.&lt;/p&gt;

&lt;p&gt;You will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laptop (WiFi key will be shared on the day)&lt;/li&gt;
&lt;li&gt;Visual Studio 2012&lt;/li&gt;
&lt;li&gt;SQL Server 2012 Express Edition&lt;/li&gt;
&lt;li&gt;Git (download TortoiseGit if you’re unfamiliar with Git)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ReSharper (trial versions are available from jetbrains.com)&lt;/li&gt;
&lt;li&gt;Visual Studio 2012&lt;/li&gt;
&lt;li&gt;A pair-programming partner. Partners will be arranged on the day if necessary but you’ll probably prefer to bring a colleague. If you want to go it alone, that’s fine, too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In advance:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git://github.com/Readify/MakingLegacyApplicationsAwesome.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Further instructions for the workshop will be made available within this repository so make sure you do this before the day!&lt;/p&gt;

&lt;p&gt;Tickets are available via the &lt;a href="http://readify.net/our-events?event-id=45EDF1AF-782E-4089-85A0-9E89F50D4865"&gt;Readify event page&lt;/a&gt;.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">we_tried_agile_and_it_didnt_work</guid><link>http://uglybugger.org/software/post/we_tried_agile_and_it_didnt_work</link><author>andrewh@uglybugger.org</author><title>"We tried agile and it didn't work."</title><description>&lt;p&gt;So, you tried agile and it didn't work?&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sun, 10 Mar 2013 16:43:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/we_tried_agile_and_it_didnt_work" /><a10:updated>2013-03-10T16:43:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;So, you tried agile and it didn't work?&lt;/p&gt;

&lt;p&gt;Let's first look at this via an analogy: You fall into a lake. You try swimming but you're not very good at it. Should you stop?&lt;/p&gt;

&lt;p&gt;So why are agile methods supposed to work in the first place? Forget the hype about agile. Forget Scrum, Kanban,
Lean and all those other buzzwords and instead, consider this very simple question. Why &lt;em&gt;does&lt;/em&gt; agile work? Or,
at least, why should we try it again when we tried it once or twice and all we encountered was failure?&lt;/p&gt;

&lt;p&gt;When you say "We tried agile and it didn't work," what you're really saying is "We tried agile and we kept running
into failure. Releasing so frequently was hard; our testing cycle was too long to fit into a sprint; our developers
couldn't keep up."&lt;/p&gt;

&lt;p&gt;In other words, &lt;strong&gt;your agile methodology was doing &lt;em&gt;exactly&lt;/em&gt; what it was supposed to do: highlight failures early.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I hear "We tried agile and it didn't work," I hear "We tried agile and it worked too well but we didn't like
the message so we stopped listening."&lt;/p&gt;

&lt;p&gt;I hate to break it to you, but highlighting failures is actually the entire reason for existence of an agile process.
Everything else is window dressing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every feedback point is an opportunity to identify failings, both large and small.&lt;/li&gt;
&lt;li&gt;Every missed user story is a message that the team can't yet estimate well enough.&lt;/li&gt;
&lt;li&gt;Every bug discovered by end users rather than automated tests tells the story of human error.&lt;/li&gt;
&lt;li&gt;Every pain point is a warning to fix it before it gets worse.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Teams that "go agile" usually experience pain because previously they just deferred the pain that &lt;em&gt;already awaits them&lt;/em&gt;
by only trying to release their software at the end of a multi-year project. It's not that there's less pain in
single-release projects; just that all the pain is felt at once. That kind of pain is often enough to cause individual
nervous breakdowns and company bankruptcies.&lt;/p&gt;

&lt;p&gt;When you feel the pain from going agile, don't view it as failure. View it as the process's helpfully surfacing problems
early so that you can deal with them while there's still time.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">video_from_my_dddbrisbane_talk_yesterday_is_now_online</guid><link>http://uglybugger.org/software/post/video_from_my_dddbrisbane_talk_yesterday_is_now_online</link><author>andrewh@uglybugger.org</author><title>Video from my #dddbrisbane talk yesterday is now online</title><description>&lt;p&gt;&lt;a href="http://dddbrisbane.com/"&gt;DDD Brisbane 2012&lt;/a&gt; yesterday was great fun. If you weren't there, you really missed out.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sun, 02 Dec 2012 16:41:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/video_from_my_dddbrisbane_talk_yesterday_is_now_online" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3567.PNG/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3566.PNG/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3565.PNG/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3568.PNG/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3569.PNG/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3570.PNG/" /><a10:updated>2012-12-02T16:41:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;&lt;a href="http://dddbrisbane.com/"&gt;DDD Brisbane 2012&lt;/a&gt; yesterday was great fun. If you weren't there, you really missed out.&lt;/p&gt;

&lt;p&gt;Massive thanks to Damian Brady, Bronwen Zande, John O'Brien, Brendan and Lin Kowitz and David Cook for putting on a great event.&lt;/p&gt;

&lt;p&gt;The video from my talk (abstract &lt;a href="http://www.codingforfunandprofit.com/blog/vote_for_my_dddbrisbane_talk_inversion_of_control_from_first_principles_top_gear_style"&gt;here&lt;/a&gt;) is
now online:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;iframe width="480" height="360" src="http://www.youtube.com/embed/5lIeky2V4dc" frameborder="0" allowfullscreen="true"&gt;&lt;/iframe&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some of my favourite tweets from the talk:&lt;/p&gt;

&lt;p&gt;&lt;style type="text/css"&gt;
    .thisPost img {
        display: inline-block;
        width: 280px;
        margin: 5px;
    }
&lt;/style&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="thisPost"&gt;
&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3567.PNG/" alt=""/&gt;
&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3566.PNG/" alt=""/&gt;
&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3565.PNG/" alt=""/&gt;
&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3568.PNG/" alt=""/&gt;
&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3569.PNG/" alt=""/&gt;
&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._12._02._1641._1000.IMG_3570.PNG/" alt=""/&gt;
&lt;/span&gt;&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">vote_for_my_dddbrisbane_talk_inversion_of_control_from_first_principles_top_gear_style</guid><link>http://uglybugger.org/software/post/vote_for_my_dddbrisbane_talk_inversion_of_control_from_first_principles_top_gear_style</link><author>andrewh@uglybugger.org</author><title>Vote for my @dddbrisbane talk: Inversion of Control from First Principles: Top Gear Style</title><description>&lt;p&gt;So I'm throwing my hat into the ring again to present at &lt;a href="http://dddbrisbane.com/"&gt;DDD Brisbane&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DDD Brisbane 2012 is on the 1st of December (a Saturday) and sessions are peer-voted so you get to see what
&lt;em&gt;you&lt;/em&gt; want to see.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h2&gt;Inversion of Control from First Principles: Top Gear Style&lt;/h2&gt;
  
  &lt;p&gt;Tonight: James May writes "Hello, World!", Richard Hammond cleans up the mess and Clarkson does some shouting.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;When most people first try to apply good OO design the wheels fall off as soon as their app starts to get complex.
  TDD, Mock&amp;lt;T&amp;gt;, IoC, WTF? What are these TLAs, why should you care and where's that owner's manual when you need it,
  anyway?&lt;br /&gt;&lt;br /&gt;  &lt;/p&gt;
  
  &lt;p&gt;Most people are afraid of trying TDD and IoC because they don't really know what they're doing. In true Top Gear
  spirit we're not going to let ignorance prevent us from having a go, so sit back and watch us point a compiler in
  the general direction of France and open the throttle.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;In this talk we're going to introduce inversion of control from first principles so that it's not just an abstract
  concept but a real, "I finally get it" tool in your toolbox. We'll start with "Hello, world!" and finish by writing
  a functioning IoC container - live, in real-time and without a seat-belt - and you can take the code home afterwards
  and test-drive it yourself.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;In the right hands, IoC is a very sharp tool. Just don't let Clarkson drop it on his foot...&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;*Actual Top Gear presenters may not be present. But it will be awesome anyway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://dddbrisbane.com/submit2012"&gt;You should submit something, too&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;a href="http://dddbrisbane.com/"&gt;vote&lt;/a&gt; for me :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sat, 03 Nov 2012 09:24:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/vote_for_my_dddbrisbane_talk_inversion_of_control_from_first_principles_top_gear_style" /><a10:updated>2012-11-03T09:24:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;So I'm throwing my hat into the ring again to present at &lt;a href="http://dddbrisbane.com/"&gt;DDD Brisbane&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DDD Brisbane 2012 is on the 1st of December (a Saturday) and sessions are peer-voted so you get to see what
&lt;em&gt;you&lt;/em&gt; want to see.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h2&gt;Inversion of Control from First Principles: Top Gear Style&lt;/h2&gt;
  
  &lt;p&gt;Tonight: James May writes "Hello, World!", Richard Hammond cleans up the mess and Clarkson does some shouting.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;When most people first try to apply good OO design the wheels fall off as soon as their app starts to get complex.
  TDD, Mock&amp;lt;T&amp;gt;, IoC, WTF? What are these TLAs, why should you care and where's that owner's manual when you need it,
  anyway?&lt;br /&gt;&lt;br /&gt;  &lt;/p&gt;
  
  &lt;p&gt;Most people are afraid of trying TDD and IoC because they don't really know what they're doing. In true Top Gear
  spirit we're not going to let ignorance prevent us from having a go, so sit back and watch us point a compiler in
  the general direction of France and open the throttle.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;In this talk we're going to introduce inversion of control from first principles so that it's not just an abstract
  concept but a real, "I finally get it" tool in your toolbox. We'll start with "Hello, world!" and finish by writing
  a functioning IoC container - live, in real-time and without a seat-belt - and you can take the code home afterwards
  and test-drive it yourself.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;In the right hands, IoC is a very sharp tool. Just don't let Clarkson drop it on his foot...&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
  
  &lt;p&gt;*Actual Top Gear presenters may not be present. But it will be awesome anyway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://dddbrisbane.com/submit2012"&gt;You should submit something, too&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;a href="http://dddbrisbane.com/"&gt;vote&lt;/a&gt; for me :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">in_software_the_iron_triangle_is_a_lie</guid><link>http://uglybugger.org/software/post/in_software_the_iron_triangle_is_a_lie</link><author>andrewh@uglybugger.org</author><title>In software, the iron triangle is a lie</title><description>&lt;p&gt;Everyone's heard the old adage, "Fast, good, cheap: pick two." It's called the Iron Triangle or &lt;a href="http://en.wikipedia.org/wiki/Project_triangle"&gt;Project Triangle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._08._31._1158._1000.200px-Project-triangle.svg.png/" alt="Fast, good, cheap"/&gt;&lt;/p&gt;

&lt;p&gt;I'm not going to make this argument about the world in general but in software this just doesn't work.&lt;/p&gt;

&lt;p&gt;Why? Because software quality is paramount and poor-quality software is a complete showstopper as far as "fast"
is concerned. You can't build any decent-sized piece of software on a poor foundation. If the code is good it
will be easy and quick to change. If the code is poor it will be slow and painful to change.&lt;/p&gt;

&lt;p&gt;Cheap will start out cheap and nasty by design but will morph into "expensive and nasty" very, very quickly, and
then you'll be stuck with your expensive-yet-cheap-and-nasty legacy application and a team of developers
quickly heading for the door before the midden hits the windmill.&lt;/p&gt;

&lt;p&gt;In software your best options are "fast and good" (if you can find a crack team) or "slow and good" but neither
of those is cheap.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Fri, 31 Aug 2012 11:58:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/in_software_the_iron_triangle_is_a_lie" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2012._2012._08._31._1158._1000.200px-Project-triangle.svg.png/" /><a10:updated>2012-08-31T11:58:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Everyone's heard the old adage, "Fast, good, cheap: pick two." It's called the Iron Triangle or &lt;a href="http://en.wikipedia.org/wiki/Project_triangle"&gt;Project Triangle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2012._2012._08._31._1158._1000.200px-Project-triangle.svg.png/" alt="Fast, good, cheap"/&gt;&lt;/p&gt;

&lt;p&gt;I'm not going to make this argument about the world in general but in software this just doesn't work.&lt;/p&gt;

&lt;p&gt;Why? Because software quality is paramount and poor-quality software is a complete showstopper as far as "fast"
is concerned. You can't build any decent-sized piece of software on a poor foundation. If the code is good it
will be easy and quick to change. If the code is poor it will be slow and painful to change.&lt;/p&gt;

&lt;p&gt;Cheap will start out cheap and nasty by design but will morph into "expensive and nasty" very, very quickly, and
then you'll be stuck with your expensive-yet-cheap-and-nasty legacy application and a team of developers
quickly heading for the door before the midden hits the windmill.&lt;/p&gt;

&lt;p&gt;In software your best options are "fast and good" (if you can find a crack team) or "slow and good" but neither
of those is cheap.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">what_risks_are_you_taking_with_your_business</guid><link>http://uglybugger.org/software/post/what_risks_are_you_taking_with_your_business</link><author>andrewh@uglybugger.org</author><title>What risks are you taking with your business?</title><description>&lt;p&gt;I had a potential client contact us a while ago. We hadn't dealt with them before and they didn't end up retaining us - largely,
I think, because the message about how much trouble they were in might have been a bit too unpalatable to heed.&lt;/p&gt;

&lt;p&gt;They're in a world of pain through a combination of bad luck and poor planning although, to be fair, it's more of the latter.&lt;/p&gt;

&lt;p&gt;I can't help you with bad luck but I &lt;em&gt;can&lt;/em&gt; prompt you to plan for it.&lt;/p&gt;

&lt;p&gt;If you ship software, please ask yourself these questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you had to ship a build tomorrow, could you?&lt;/li&gt;
&lt;li&gt;How long would it take? Be honest - a day? A week? A month?&lt;/li&gt;
&lt;li&gt;What dependencies do you have that could cause you to need to ship one?
&lt;ul&gt;
&lt;li&gt;Third-party web services?&lt;/li&gt;
&lt;li&gt;iOS provisioning profiles?&lt;/li&gt;
&lt;li&gt;Expired x.509 certificates?&lt;/li&gt;
&lt;li&gt;Changes to certificate revocation lists?&lt;/li&gt;
&lt;li&gt;A critical security flaw?&lt;/li&gt;
&lt;li&gt;A leap-year bug?&lt;/li&gt;
&lt;li&gt;A leap-second bug?&lt;/li&gt;
&lt;li&gt;An operating system patch?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;What monitoring do you have in place so that you're the first to know about any of these problems?&lt;/li&gt;
&lt;li&gt;How much will it hurt if any of these fails?&lt;/li&gt;
&lt;li&gt;How quickly do you need to be back up and running?&lt;/li&gt;
&lt;li&gt;How many people are going to sue you if your software/platform/application falls down? And for how much?&lt;/li&gt;
&lt;li&gt;&lt;em&gt;How much do you stand to lose?&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Back to that potential client: I honestly don't think their business is going to survive this particular flavour of disaster. In other
words, I think &lt;em&gt;the entire company is going to fold&lt;/em&gt; - and all because someone else moved their cheese and they didn't have a contingency
plan. I wish them the best but I can't help them now - not at this late stage :(&lt;/p&gt;

&lt;p&gt;I can't help them but I &lt;em&gt;can&lt;/em&gt; remind &lt;em&gt;you&lt;/em&gt; that the unexpected does happen, and will to you at some point. If your answers to any of the
questions above frighten you... better me than fate :)&lt;/p&gt;

&lt;p&gt;UPDATE: It brings me no happiness to report that they indeed did go bankrupt. Please don't let that happen to you for such a preventable reason.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Tue, 21 Aug 2012 15:43:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/what_risks_are_you_taking_with_your_business" /><a10:updated>2012-08-21T15:43:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I had a potential client contact us a while ago. We hadn't dealt with them before and they didn't end up retaining us - largely,
I think, because the message about how much trouble they were in might have been a bit too unpalatable to heed.&lt;/p&gt;

&lt;p&gt;They're in a world of pain through a combination of bad luck and poor planning although, to be fair, it's more of the latter.&lt;/p&gt;

&lt;p&gt;I can't help you with bad luck but I &lt;em&gt;can&lt;/em&gt; prompt you to plan for it.&lt;/p&gt;

&lt;p&gt;If you ship software, please ask yourself these questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you had to ship a build tomorrow, could you?&lt;/li&gt;
&lt;li&gt;How long would it take? Be honest - a day? A week? A month?&lt;/li&gt;
&lt;li&gt;What dependencies do you have that could cause you to need to ship one?
&lt;ul&gt;
&lt;li&gt;Third-party web services?&lt;/li&gt;
&lt;li&gt;iOS provisioning profiles?&lt;/li&gt;
&lt;li&gt;Expired x.509 certificates?&lt;/li&gt;
&lt;li&gt;Changes to certificate revocation lists?&lt;/li&gt;
&lt;li&gt;A critical security flaw?&lt;/li&gt;
&lt;li&gt;A leap-year bug?&lt;/li&gt;
&lt;li&gt;A leap-second bug?&lt;/li&gt;
&lt;li&gt;An operating system patch?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;What monitoring do you have in place so that you're the first to know about any of these problems?&lt;/li&gt;
&lt;li&gt;How much will it hurt if any of these fails?&lt;/li&gt;
&lt;li&gt;How quickly do you need to be back up and running?&lt;/li&gt;
&lt;li&gt;How many people are going to sue you if your software/platform/application falls down? And for how much?&lt;/li&gt;
&lt;li&gt;&lt;em&gt;How much do you stand to lose?&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Back to that potential client: I honestly don't think their business is going to survive this particular flavour of disaster. In other
words, I think &lt;em&gt;the entire company is going to fold&lt;/em&gt; - and all because someone else moved their cheese and they didn't have a contingency
plan. I wish them the best but I can't help them now - not at this late stage :(&lt;/p&gt;

&lt;p&gt;I can't help them but I &lt;em&gt;can&lt;/em&gt; remind &lt;em&gt;you&lt;/em&gt; that the unexpected does happen, and will to you at some point. If your answers to any of the
questions above frighten you... better me than fate :)&lt;/p&gt;

&lt;p&gt;UPDATE: It brings me no happiness to report that they indeed did go bankrupt. Please don't let that happen to you for such a preventable reason.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">introducing_yaclp_yet_another_command_line_parser</guid><link>http://uglybugger.org/software/post/introducing_yaclp_yet_another_command_line_parser</link><author>andrewh@uglybugger.org</author><title>Introducing YACLP: Yet Another Command-Line Parser</title><description>&lt;p&gt;It's on NuGet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package YACLP
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why another one?&lt;/p&gt;

&lt;p&gt;Because there were a bunch out there but all of them focused more on the parsing than on being quick and easy to call.&lt;/p&gt;

&lt;p&gt;I want my command-line parser to not only parse arguments (which it does, but isn't very flexible about) but to automatically generate a usage message so that I don't have to.&lt;/p&gt;

&lt;h2&gt;Simple Usage&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;var options = DefaultParser.ParseOrExitWithUsageMessage&amp;lt;MyCommandLineParameters&amp;gt;(args);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Recommendations&lt;/h2&gt;

&lt;p&gt;I'd recommend using an IConfiguration or similar interface so that anything that depends on it doesn't need to know about command-line parameters.&lt;/p&gt;

&lt;p&gt;Our main program would look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Program
{
    private static void Main(string[] args)
    {
        var configuration = DefaultParser.ParseOrExitWithUsageMessage&amp;lt;CommandLineParameters&amp;gt;(args);

        new Greeter(configuration).SayHello();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... and our Greeter like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Greeter
{
    private readonly IConfiguration _configuration;

    public Greeter(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public void SayHello()
    {
        var message = string.IsNullOrEmpty(_configuration.Surname)
                          ? string.Format("Hi, {0}!", _configuration.FirstName)
                          : string.Format("Hello, Mr/Ms {0}", _configuration.Surname);

        Console.WriteLine(message);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that our Greeter takes a dependency on an IConfiguration, which looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface IConfiguration
{
    string FirstName { get; set; }
    string Surname { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... and that IConfiguration interface is implemented by our CommandLineParameters class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class CommandLineParameters : IConfiguration
{
    [ParameterDescription("The first name of the person using the program.")]
    public string FirstName { get; set; }

    [ParameterIsOptional]
    [ParameterDefault("Smith")]
    [ParameterDescription("The last name of the person using the program.")]
    public string Surname { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The key point here is that our Greeter knows absolutely nothing about command-line parameters as everything is segregated using the IConfiguration interface.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 28 Jun 2012 17:47:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/introducing_yaclp_yet_another_command_line_parser" /><a10:updated>2012-06-28T17:47:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;It's on NuGet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Install-Package YACLP
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why another one?&lt;/p&gt;

&lt;p&gt;Because there were a bunch out there but all of them focused more on the parsing than on being quick and easy to call.&lt;/p&gt;

&lt;p&gt;I want my command-line parser to not only parse arguments (which it does, but isn't very flexible about) but to automatically generate a usage message so that I don't have to.&lt;/p&gt;

&lt;h2&gt;Simple Usage&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;var options = DefaultParser.ParseOrExitWithUsageMessage&amp;lt;MyCommandLineParameters&amp;gt;(args);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Recommendations&lt;/h2&gt;

&lt;p&gt;I'd recommend using an IConfiguration or similar interface so that anything that depends on it doesn't need to know about command-line parameters.&lt;/p&gt;

&lt;p&gt;Our main program would look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Program
{
    private static void Main(string[] args)
    {
        var configuration = DefaultParser.ParseOrExitWithUsageMessage&amp;lt;CommandLineParameters&amp;gt;(args);

        new Greeter(configuration).SayHello();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... and our Greeter like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class Greeter
{
    private readonly IConfiguration _configuration;

    public Greeter(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public void SayHello()
    {
        var message = string.IsNullOrEmpty(_configuration.Surname)
                          ? string.Format("Hi, {0}!", _configuration.FirstName)
                          : string.Format("Hello, Mr/Ms {0}", _configuration.Surname);

        Console.WriteLine(message);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that our Greeter takes a dependency on an IConfiguration, which looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface IConfiguration
{
    string FirstName { get; set; }
    string Surname { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;... and that IConfiguration interface is implemented by our CommandLineParameters class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class CommandLineParameters : IConfiguration
{
    [ParameterDescription("The first name of the person using the program.")]
    public string FirstName { get; set; }

    [ParameterIsOptional]
    [ParameterDefault("Smith")]
    [ParameterDescription("The last name of the person using the program.")]
    public string Surname { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The key point here is that our Greeter knows absolutely nothing about command-line parameters as everything is segregated using the IConfiguration interface.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">the_principle_of_least_privilege_and_other_fallacies</guid><link>http://uglybugger.org/software/post/the_principle_of_least_privilege_and_other_fallacies</link><author>andrewh@uglybugger.org</author><title>The Principle of Least Privilege and other fallacies</title><description>&lt;p&gt;The Principle of Least Privilege states that a user (or service) should be given the absolute bare minimum
privileges required in order to fulfil its function.&lt;/p&gt;

&lt;p&gt;On the surface, how could this possibly be bad? If I have everything I need in order to do my job then by definition
I have everything I need. Likewise, if my app has all the privileges it needs in order to function correctly then,
again, by definition it can function correctly. Right?&lt;/p&gt;

&lt;p&gt;For the purpose of this post I'm going to focus on application security. The parallels between that and user-level
permissions are obvious, so I'll leave you to draw your own conclusions.&lt;/p&gt;

&lt;p&gt;Where this all falls down is in defining &amp;quot;least privilege&amp;quot; in a sensible manner. How do we normally decide
what privileges an application will require? When we decide on what the application will do, of course. And how do we
decide what an application will do? We gather our requirements, of course. And when do we do this? We (of course, of
course) gather all our requirements up-front, because that's how we roll.&lt;/p&gt;

&lt;p&gt;To rephrase that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We gather our requirements up-front.&lt;/li&gt;
&lt;li&gt;We know these requirements to be inaccurate, incomplete or just plain wrong.&lt;/li&gt;
&lt;li&gt;We set our security policies according to these requirements.&lt;/li&gt;
&lt;li&gt;We have our policies &amp;quot;signed off&amp;quot; by some governance group or other.&lt;/li&gt;
&lt;li&gt;We send our security requirements off to our sysadmins to implement in the form of AD security groups etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We send our known-broken security requirements, based on our known-broken application requirements, off to be set in
stone before we ever even ship our application.&lt;/strong&gt; &lt;em&gt;Now&lt;/em&gt; try telling me that it makes sense. Of course,
we can change security policies after they've been written - and constitutional reform is theoretically possible, too,
but how long did it take for women to get the vote?&lt;/p&gt;

&lt;p&gt;If you're going to set strict security policies for your app then your development team should be responsible - and
&lt;em&gt;held accountable&lt;/em&gt; - for setting sensible policies and updating them quickly according to changing requirements. If
you're going to wrap security policies in endless red tape then don't be surprised when 1) people ask for more
privileges than they need just to avoid administrative pain; and 2) your project ends up with a sub-optimal result
because of a bunch of stupid security work-arounds that decrease your overall security anyway.&lt;/p&gt;

&lt;p&gt;TL;DR: Hire smart people. Trust them. Get out of their road. &lt;em&gt;Hold them accountable&lt;/em&gt;.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 07 Jun 2012 08:32:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/the_principle_of_least_privilege_and_other_fallacies" /><a10:updated>2012-06-07T08:32:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;The Principle of Least Privilege states that a user (or service) should be given the absolute bare minimum
privileges required in order to fulfil its function.&lt;/p&gt;

&lt;p&gt;On the surface, how could this possibly be bad? If I have everything I need in order to do my job then by definition
I have everything I need. Likewise, if my app has all the privileges it needs in order to function correctly then,
again, by definition it can function correctly. Right?&lt;/p&gt;

&lt;p&gt;For the purpose of this post I'm going to focus on application security. The parallels between that and user-level
permissions are obvious, so I'll leave you to draw your own conclusions.&lt;/p&gt;

&lt;p&gt;Where this all falls down is in defining &amp;quot;least privilege&amp;quot; in a sensible manner. How do we normally decide
what privileges an application will require? When we decide on what the application will do, of course. And how do we
decide what an application will do? We gather our requirements, of course. And when do we do this? We (of course, of
course) gather all our requirements up-front, because that's how we roll.&lt;/p&gt;

&lt;p&gt;To rephrase that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We gather our requirements up-front.&lt;/li&gt;
&lt;li&gt;We know these requirements to be inaccurate, incomplete or just plain wrong.&lt;/li&gt;
&lt;li&gt;We set our security policies according to these requirements.&lt;/li&gt;
&lt;li&gt;We have our policies &amp;quot;signed off&amp;quot; by some governance group or other.&lt;/li&gt;
&lt;li&gt;We send our security requirements off to our sysadmins to implement in the form of AD security groups etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We send our known-broken security requirements, based on our known-broken application requirements, off to be set in
stone before we ever even ship our application.&lt;/strong&gt; &lt;em&gt;Now&lt;/em&gt; try telling me that it makes sense. Of course,
we can change security policies after they've been written - and constitutional reform is theoretically possible, too,
but how long did it take for women to get the vote?&lt;/p&gt;

&lt;p&gt;If you're going to set strict security policies for your app then your development team should be responsible - and
&lt;em&gt;held accountable&lt;/em&gt; - for setting sensible policies and updating them quickly according to changing requirements. If
you're going to wrap security policies in endless red tape then don't be surprised when 1) people ask for more
privileges than they need just to avoid administrative pain; and 2) your project ends up with a sub-optimal result
because of a bunch of stupid security work-arounds that decrease your overall security anyway.&lt;/p&gt;

&lt;p&gt;TL;DR: Hire smart people. Trust them. Get out of their road. &lt;em&gt;Hold them accountable&lt;/em&gt;.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">if_your_dba_makes_your_schema_changes_youre_doing_it_wrong</guid><link>http://uglybugger.org/software/post/if_your_dba_makes_your_schema_changes_youre_doing_it_wrong</link><author>andrewh@uglybugger.org</author><title>If your DBA makes your schema changes, you're doing it wrong</title><description>&lt;p&gt;Does your DBA make schema changes for you? Here's a simple question: why?&lt;/p&gt;

&lt;p&gt;One of the fundamental principles of an agile team is that of cross-functionality. Everyone should have at least a passing familiarity with
everyone else's role, and there should be no one bottleneck within the team. There should also be minimal external dependencies that could
prevent the team from delivering its stated sprint goal. If you have an external dependency then you're betting your own team's success
on something that you don't control. Tell me how that makes sense, someone?&lt;/p&gt;

&lt;p&gt;If you have a crack DBA within your team then that's one thing. I still don't think it's wise, but at least they're operating within your
team. Even so, they're a bottleneck: if more than one person needs to make a schema change then all but the first person can hurry up
and wait for the DBA to be available.&lt;/p&gt;

&lt;p&gt;Is your DBA a developer? Does s/he have commit rights and responsibilities just like any other member of your team? Will s/he fix the build
if it breaks? Does s/he decide on your class names? Or on your project/solution structure? Then why have them act as a gatekeeper for
same? Your database is just a persistent record of your domain model, and should change accordingly. The schema should be updated by your
own scripts, kept in your own source repository, and applied automatically by your application. It &lt;em&gt;is part&lt;/em&gt; of your application.&lt;/p&gt;

&lt;p&gt;Have infrastructure people do infrastructure and software developers write software. Database &lt;em&gt;servers&lt;/em&gt; are infrastructure. Databases
themselves are &lt;em&gt;software components&lt;/em&gt;, not infrastructure.&lt;/p&gt;

&lt;p&gt;This might sound like I'm against DBAs in principle. Not entirely, but I am against the kind who feel the need to insert themselves into
application design decisions after the fact. To be fair, I'm also against developers who treat databases as an abstraction that they don't
have to understand. My position is that both attitudes are irresponsible.&lt;/p&gt;

&lt;p&gt;As a developer using a database you're responsible for knowing your tools and using them well, and that includes SQL. Likewise, as a
DBA responsible for any component of a software development project you're responsible for knowing &lt;em&gt;your&lt;/em&gt; tools, and that includes being
able to code to the extent that you can write migrations if that's what your team needs.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Wed, 06 Jun 2012 17:11:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/if_your_dba_makes_your_schema_changes_youre_doing_it_wrong" /><a10:updated>2012-06-06T17:11:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Does your DBA make schema changes for you? Here's a simple question: why?&lt;/p&gt;

&lt;p&gt;One of the fundamental principles of an agile team is that of cross-functionality. Everyone should have at least a passing familiarity with
everyone else's role, and there should be no one bottleneck within the team. There should also be minimal external dependencies that could
prevent the team from delivering its stated sprint goal. If you have an external dependency then you're betting your own team's success
on something that you don't control. Tell me how that makes sense, someone?&lt;/p&gt;

&lt;p&gt;If you have a crack DBA within your team then that's one thing. I still don't think it's wise, but at least they're operating within your
team. Even so, they're a bottleneck: if more than one person needs to make a schema change then all but the first person can hurry up
and wait for the DBA to be available.&lt;/p&gt;

&lt;p&gt;Is your DBA a developer? Does s/he have commit rights and responsibilities just like any other member of your team? Will s/he fix the build
if it breaks? Does s/he decide on your class names? Or on your project/solution structure? Then why have them act as a gatekeeper for
same? Your database is just a persistent record of your domain model, and should change accordingly. The schema should be updated by your
own scripts, kept in your own source repository, and applied automatically by your application. It &lt;em&gt;is part&lt;/em&gt; of your application.&lt;/p&gt;

&lt;p&gt;Have infrastructure people do infrastructure and software developers write software. Database &lt;em&gt;servers&lt;/em&gt; are infrastructure. Databases
themselves are &lt;em&gt;software components&lt;/em&gt;, not infrastructure.&lt;/p&gt;

&lt;p&gt;This might sound like I'm against DBAs in principle. Not entirely, but I am against the kind who feel the need to insert themselves into
application design decisions after the fact. To be fair, I'm also against developers who treat databases as an abstraction that they don't
have to understand. My position is that both attitudes are irresponsible.&lt;/p&gt;

&lt;p&gt;As a developer using a database you're responsible for knowing your tools and using them well, and that includes SQL. Likewise, as a
DBA responsible for any component of a software development project you're responsible for knowing &lt;em&gt;your&lt;/em&gt; tools, and that includes being
able to code to the extent that you can write migrations if that's what your team needs.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">dear_dbas</guid><link>http://uglybugger.org/software/post/dear_dbas</link><author>andrewh@uglybugger.org</author><title>Dear DBAs</title><description>&lt;p&gt;Applications need to own their own data.&lt;/p&gt;

&lt;p&gt;The job of a DBA is a relatively thankless one. To make things easier for all parties, there needs to be a better understanding
of where the responsibilities lie between DBAs and applications developers.&lt;/p&gt;

&lt;p&gt;Applications should be perfectly capable of maintaining their own schemas and data. A database is just a big variable
store, in the same way as are the stack and the heap. It's a clever store, yes, but still a variable store. The
structure of that variable store and the access to it should be governed by the application itself. The application should
be able to migrate its own schema up and down in the case of a rollout or rollback, and should need no human intervention
for any part of its release.&lt;/p&gt;

&lt;p&gt;Making changes to an app's database outside of the build pipeline (for instance, adding uniqueness constraints
that may end up crashing the app), is putting the application into an inconsistent state with what's in development
and what will be deployed when it next goes to production. This isn't going to help anybody.&lt;/p&gt;

&lt;p&gt;A good software engineer will keep mechanical sympathy in mind when doing database work, and will ask for help when out
of his/her depth. A good software engineer will know about nth normal forms, indices, sharding and will be as responsible
with the database(s) owned by his/her app to the same degree that he/she would be responsible with the stack and heap.&lt;/p&gt;

&lt;p&gt;A good DBA will ensure that each app sharing a database server behaves as a good citizen and doesn't unnecessarily or
unfairly utilise resources. A good DBA will be able to help identify and debug poorly-performing queries, and contribute
to changing them via the normal build/deployment pipeline.&lt;/p&gt;

&lt;p&gt;We can play nicely in the sandpit together. Let's do that :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sat, 02 Jun 2012 21:43:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/dear_dbas" /><a10:updated>2012-06-02T21:43:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Applications need to own their own data.&lt;/p&gt;

&lt;p&gt;The job of a DBA is a relatively thankless one. To make things easier for all parties, there needs to be a better understanding
of where the responsibilities lie between DBAs and applications developers.&lt;/p&gt;

&lt;p&gt;Applications should be perfectly capable of maintaining their own schemas and data. A database is just a big variable
store, in the same way as are the stack and the heap. It's a clever store, yes, but still a variable store. The
structure of that variable store and the access to it should be governed by the application itself. The application should
be able to migrate its own schema up and down in the case of a rollout or rollback, and should need no human intervention
for any part of its release.&lt;/p&gt;

&lt;p&gt;Making changes to an app's database outside of the build pipeline (for instance, adding uniqueness constraints
that may end up crashing the app), is putting the application into an inconsistent state with what's in development
and what will be deployed when it next goes to production. This isn't going to help anybody.&lt;/p&gt;

&lt;p&gt;A good software engineer will keep mechanical sympathy in mind when doing database work, and will ask for help when out
of his/her depth. A good software engineer will know about nth normal forms, indices, sharding and will be as responsible
with the database(s) owned by his/her app to the same degree that he/she would be responsible with the stack and heap.&lt;/p&gt;

&lt;p&gt;A good DBA will ensure that each app sharing a database server behaves as a good citizen and doesn't unnecessarily or
unfairly utilise resources. A good DBA will be able to help identify and debug poorly-performing queries, and contribute
to changing them via the normal build/deployment pipeline.&lt;/p&gt;

&lt;p&gt;We can play nicely in the sandpit together. Let's do that :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">this_weeks_version_control_workflow</guid><link>http://uglybugger.org/software/post/this_weeks_version_control_workflow</link><author>andrewh@uglybugger.org</author><title>This week's version control workflow</title><description>&lt;p&gt;So this is my current workflow in order to commit a single change from my development VM to the client's environment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push to github from My_VM&lt;/li&gt;
&lt;li&gt;Pull from github to My_Laptop.&lt;/li&gt;
&lt;li&gt;Push from My_Laptop to USB stick.&lt;/li&gt;
&lt;li&gt;Transfer USB stick to Client_Workstation.&lt;/li&gt;
&lt;li&gt;Pull from USB stick to Client_Workstation.&lt;/li&gt;
&lt;li&gt;Push from Client_Workstation to NTFS share.&lt;/li&gt;
&lt;li&gt;Pull from NTFS share to Client_VM&lt;/li&gt;
&lt;/ol&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Mon, 06 Feb 2012 16:36:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/this_weeks_version_control_workflow" /><a10:updated>2012-02-06T16:36:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;So this is my current workflow in order to commit a single change from my development VM to the client's environment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push to github from My_VM&lt;/li&gt;
&lt;li&gt;Pull from github to My_Laptop.&lt;/li&gt;
&lt;li&gt;Push from My_Laptop to USB stick.&lt;/li&gt;
&lt;li&gt;Transfer USB stick to Client_Workstation.&lt;/li&gt;
&lt;li&gt;Pull from USB stick to Client_Workstation.&lt;/li&gt;
&lt;li&gt;Push from Client_Workstation to NTFS share.&lt;/li&gt;
&lt;li&gt;Pull from NTFS share to Client_VM&lt;/li&gt;
&lt;/ol&gt;
</a10:content></item><item><guid isPermaLink="false">software_project_rescue_a_fairy_tale_qalmug_on_friday_the_3rd</guid><link>http://uglybugger.org/software/post/software_project_rescue_a_fairy_tale_qalmug_on_friday_the_3rd</link><author>andrewh@uglybugger.org</author><title>Software Project Rescue: A Fairy Tale (@QALMUG on Friday the 3rd)</title><description>&lt;p&gt;I'm presenting &lt;a href="http://qalmug.org/?p=95"&gt;this&lt;/a&gt; on Friday morning at the &lt;a href="http://www.qalmug.org/"&gt;QLD ALM User Group&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is a tale of a naïve protagonist, misguided advisors, princesses[1], dragons[2] and knights[3] in
  shining armour[4].&lt;br /&gt;
  &lt;br /&gt;
  Like most fairy tales, this story has an idyllic beginning, a middle, and a happy ending. Also like most
  fairy tales, the middle of this tale is a grim, dark, scary journey through the Woods of Requirements,
  blithely past the Ivory Tower of Architecture, into the Depths of Design Despair, under the Mountain of
  Technical Debt and finishing with an agile leap of faith over the Waterfall of Doom to reach the rainbow
  on the other side.[5]&lt;br /&gt;
  &lt;br /&gt;
  This talk starts with a post-mortem of a 3.5-year, $2m project that went horribly wrong. We’ll look at
  where the project failed: the architectural choices; the management strategies; the personalities
  involved and some sample code. We’ll also look at the changes that were made to bring the project back
  on track, get its wildly spiralling technical debt under control, re-release a functioning version and
  refactor it to something testable – and all in 3.5 weeks.&lt;br /&gt;
  &lt;br /&gt;
  Finally, we’ll discuss ways to identify the issues encountered in this project so that you can spot them
  before they bite, strategies for regaining control over a project that’s already in trouble, and
  effective methods for managing troublesome stakeholders.&lt;br /&gt;
  &lt;br /&gt;
  [1] There may or may not be actual princesses.&lt;br/&gt;
  [2] Or dragons.&lt;br/&gt;
  [3] Or knights.&lt;br/&gt;
  [4] Motorcycle helmets.&lt;br/&gt;
  [5] Bingo!  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I hope people think it's worth getting up early for :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Mon, 30 Jan 2012 08:12:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/software_project_rescue_a_fairy_tale_qalmug_on_friday_the_3rd" /><a10:updated>2012-01-30T08:12:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I'm presenting &lt;a href="http://qalmug.org/?p=95"&gt;this&lt;/a&gt; on Friday morning at the &lt;a href="http://www.qalmug.org/"&gt;QLD ALM User Group&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is a tale of a naïve protagonist, misguided advisors, princesses[1], dragons[2] and knights[3] in
  shining armour[4].&lt;br /&gt;
  &lt;br /&gt;
  Like most fairy tales, this story has an idyllic beginning, a middle, and a happy ending. Also like most
  fairy tales, the middle of this tale is a grim, dark, scary journey through the Woods of Requirements,
  blithely past the Ivory Tower of Architecture, into the Depths of Design Despair, under the Mountain of
  Technical Debt and finishing with an agile leap of faith over the Waterfall of Doom to reach the rainbow
  on the other side.[5]&lt;br /&gt;
  &lt;br /&gt;
  This talk starts with a post-mortem of a 3.5-year, $2m project that went horribly wrong. We’ll look at
  where the project failed: the architectural choices; the management strategies; the personalities
  involved and some sample code. We’ll also look at the changes that were made to bring the project back
  on track, get its wildly spiralling technical debt under control, re-release a functioning version and
  refactor it to something testable – and all in 3.5 weeks.&lt;br /&gt;
  &lt;br /&gt;
  Finally, we’ll discuss ways to identify the issues encountered in this project so that you can spot them
  before they bite, strategies for regaining control over a project that’s already in trouble, and
  effective methods for managing troublesome stakeholders.&lt;br /&gt;
  &lt;br /&gt;
  [1] There may or may not be actual princesses.&lt;br/&gt;
  [2] Or dragons.&lt;br/&gt;
  [3] Or knights.&lt;br/&gt;
  [4] Motorcycle helmets.&lt;br/&gt;
  [5] Bingo!  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I hope people think it's worth getting up early for :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">wow_disqus_rocks</guid><link>http://uglybugger.org/software/post/wow_disqus_rocks</link><author>andrewh@uglybugger.org</author><title>Wow. DISQUS rocks.</title><description>&lt;p&gt;Wow. I was introduced today by &lt;a href="http://aussiecoder.com/"&gt;Andrew Tobin&lt;/a&gt; (&lt;a href="https://twitter.com/#!/tobin"&gt;@tobin&lt;/a&gt;) to &lt;a href="http://disqus.com/"&gt;DISQUS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'd tweeted about my replacement blog engine, and mentioned in my previous post that I hadn't yet
implemented commenting. He suggested DISQUS, which is an online commenting service that I'd somehow
never heard of. How had I not heard of this?!&lt;/p&gt;

&lt;p&gt;From sign-up to comments working and tested, it's taken about half an hour of effort. If you need
a public commenting solution, I genuinely can't think why you'd write your own any more. Nice work :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Mon, 09 Jan 2012 21:27:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/wow_disqus_rocks" /><a10:updated>2012-01-09T21:27:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Wow. I was introduced today by &lt;a href="http://aussiecoder.com/"&gt;Andrew Tobin&lt;/a&gt; (&lt;a href="https://twitter.com/#!/tobin"&gt;@tobin&lt;/a&gt;) to &lt;a href="http://disqus.com/"&gt;DISQUS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'd tweeted about my replacement blog engine, and mentioned in my previous post that I hadn't yet
implemented commenting. He suggested DISQUS, which is an online commenting service that I'd somehow
never heard of. How had I not heard of this?!&lt;/p&gt;

&lt;p&gt;From sign-up to comments working and tested, it's taken about half an hour of effort. If you need
a public commenting solution, I genuinely can't think why you'd write your own any more. Nice work :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">new_blog_engine</guid><link>http://uglybugger.org/software/post/new_blog_engine</link><author>andrewh@uglybugger.org</author><title>New Blog Engine</title><description>&lt;p&gt;As per my &lt;a href="http://www.uglybugger.org/Home/Post/2011.12.30.2005"&gt;New Beginnings&lt;/a&gt; post, I've tried a
couple of times recently to move to &lt;a href="http://www.funnelweblog.com/"&gt;FunnelWeb&lt;/a&gt;. I've failed. The reasons
for my failure are simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wanted to host everything on &lt;a href="http://www.appharbor.com"&gt;AppHarbor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I wanted everything (including posts and comments) under source control.&lt;/li&gt;
&lt;li&gt;I wanted a custom look and feel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything that I wanted &lt;em&gt;could&lt;/em&gt; be done using FunnelWeb, but when I started doing it I realised that
I was re-working lots of code that I didn't actually expect to use in production and that, in a nutshell,
a blog is just a web site and making a database-driven web site only really makes sense when there are
frequently-changing data.&lt;/p&gt;

&lt;p&gt;In addition, I kept finding myself firing up Visual Studio in order to write code snippets, then doing
horrible things to them (I'm looking at you, Windows Live Writer) in order to make them appear. If I'd
used FunnelWeb then I could use markdown (good) but then I'd have had to use Visual Studio to write any
code snippets anyway.&lt;/p&gt;

&lt;p&gt;I thought about it some more, and decided that I &lt;em&gt;like&lt;/em&gt; writing code in Visual Studio, and can live with
using it as my main blog text editor. So... blog posts are all now written using VS.&lt;/p&gt;

&lt;p&gt;The other advantage of having a blog that's entirely under source control is that it's trivial to back up,
restore and redeploy - and I can deploy it anywhere.&lt;/p&gt;

&lt;p&gt;There's a bunch of stuff that doesn't work yet, but I can live with that. RSS isn't hooked up properly;
hence feeding to Twitter (TwitterFeed via RSS) doesn't work. Comments aren't ready for prime-time either,
but I expect they'll be done shortly. There's also no mobile browser detection, but that's in the pipeline.&lt;/p&gt;

&lt;p&gt;Why did I want to change in the first place? Because there have been lots of blog posts that I've
found myself wanting to write, but needing to include too many code snippets. Gists are fine but hurt to
include via script tags; pre-formatted code blocks are ick and screenshots are kind of pointless when
my goal is to allow people to easily copy/paste the code I'm posting. So... now that my roadblocks are mostly
out of the way, expect to see more useful stuff here. You can hold me to that :)&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sun, 08 Jan 2012 23:42:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/new_blog_engine" /><a10:updated>2012-01-08T23:42:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;As per my &lt;a href="http://www.uglybugger.org/Home/Post/2011.12.30.2005"&gt;New Beginnings&lt;/a&gt; post, I've tried a
couple of times recently to move to &lt;a href="http://www.funnelweblog.com/"&gt;FunnelWeb&lt;/a&gt;. I've failed. The reasons
for my failure are simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wanted to host everything on &lt;a href="http://www.appharbor.com"&gt;AppHarbor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I wanted everything (including posts and comments) under source control.&lt;/li&gt;
&lt;li&gt;I wanted a custom look and feel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything that I wanted &lt;em&gt;could&lt;/em&gt; be done using FunnelWeb, but when I started doing it I realised that
I was re-working lots of code that I didn't actually expect to use in production and that, in a nutshell,
a blog is just a web site and making a database-driven web site only really makes sense when there are
frequently-changing data.&lt;/p&gt;

&lt;p&gt;In addition, I kept finding myself firing up Visual Studio in order to write code snippets, then doing
horrible things to them (I'm looking at you, Windows Live Writer) in order to make them appear. If I'd
used FunnelWeb then I could use markdown (good) but then I'd have had to use Visual Studio to write any
code snippets anyway.&lt;/p&gt;

&lt;p&gt;I thought about it some more, and decided that I &lt;em&gt;like&lt;/em&gt; writing code in Visual Studio, and can live with
using it as my main blog text editor. So... blog posts are all now written using VS.&lt;/p&gt;

&lt;p&gt;The other advantage of having a blog that's entirely under source control is that it's trivial to back up,
restore and redeploy - and I can deploy it anywhere.&lt;/p&gt;

&lt;p&gt;There's a bunch of stuff that doesn't work yet, but I can live with that. RSS isn't hooked up properly;
hence feeding to Twitter (TwitterFeed via RSS) doesn't work. Comments aren't ready for prime-time either,
but I expect they'll be done shortly. There's also no mobile browser detection, but that's in the pipeline.&lt;/p&gt;

&lt;p&gt;Why did I want to change in the first place? Because there have been lots of blog posts that I've
found myself wanting to write, but needing to include too many code snippets. Gists are fine but hurt to
include via script tags; pre-formatted code blocks are ick and screenshots are kind of pointless when
my goal is to allow people to easily copy/paste the code I'm posting. So... now that my roadblocks are mostly
out of the way, expect to see more useful stuff here. You can hold me to that :)&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">the_book_of_process</guid><link>http://uglybugger.org/software/post/the_book_of_process</link><author>andrewh@uglybugger.org</author><title>The Book of Process</title><description>&lt;ol&gt;
&lt;li&gt;Once upon a time, a company's youthful founder lucked upon a successful method of performing a task.&lt;/li&gt;
&lt;li&gt;The task was profitable, and therefore it was good.&lt;/li&gt;
&lt;li&gt;The founder wrote down that method and bestowed it unto his/her minions.&lt;/li&gt;
&lt;li&gt;S/he said unto them, "This is The Process, and it is good."&lt;/li&gt;
&lt;li&gt;The minions performed The Process until the end of days.&lt;/li&gt;
&lt;li&gt;And they all lived happily ever after.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;The adage, "If it ain't broke, don't fix it" has a corollary best expressed by Tess Ferrandez: &lt;a href="http://blogs.msdn.com/b/tess/"&gt;If broken it is, fix it you should&lt;/a&gt;.
Or at least, "If broken it is, don't inflict it on everyone just because it's all too hard to bother changing it."&lt;/p&gt;

&lt;p&gt;I'm referring to internal corporate processes that serve no purpose other than demonstrating to some ISO 9000 certification
minion that a documented process exists.&lt;/p&gt;

&lt;p&gt;It seems as if every organisation, once it reaches a certain size, goes into the "create process and perish" stage. If it's
a private enterprise it'll die a long, slow, horrible death of three-thousand triplicate signatures, but if it's a government
enterprise then it's never going to die and we're all going to hate it.&lt;/p&gt;

&lt;p&gt;Is hate too strong a word? I don't think so. Show me a single person who's dealt with a government department and left happy,
and I'll show you someone who's on far too many psychedelics to be on the same planet as the rest of us. &lt;em&gt;We hate government
agencies because they're slow, bloated and inefficient.&lt;/em&gt; (We hate individual governments, too, but for different reasons.
That's just not the point of this post.)&lt;/p&gt;

&lt;p&gt;So, given the choice, why do organisations choose to have processes that make them slow, bloated and despised? Your guess is as
good as mine, but I think it's to do with some misguided idea that they should be able to have any human follow the process
and get the same result. Guess what, ladies and gentlemen: if you have a muppet-followable process then you'll end up hiring
muppets to implement it - which is at best embarrassing while the process makes sense, but an utter disaster once the process
becomes obsolete and everyone refuses to recognise it.&lt;/p&gt;

&lt;p&gt;The Book of Process above &lt;em&gt;should&lt;/em&gt; read something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once upon a time, a company's youthful founder lucked upon a successful method of performing a task.&lt;/li&gt;
&lt;li&gt;The task was profitable, and therefore it was good.&lt;/li&gt;
&lt;li&gt;The founder wrote down that method and bestowed it unto his/her minions.&lt;/li&gt;
&lt;li&gt;S/he said unto them, "This is The Process, and it is good."&lt;/li&gt;
&lt;li&gt;The minions performed The Process until the end of days.&lt;/li&gt;
&lt;li&gt;The end of days arrived with a pitchfork-waving, torch-brandishing mob of angry citizens who burned the company's offices down around the minions.&lt;/li&gt;
&lt;li&gt;The minions could not find &lt;strike&gt;their backsides with both hands&lt;/strike&gt; the "In Case of Fire" process document quickly enough to escape.&lt;/li&gt;
&lt;li&gt;And the citizens all rejoiced, and lived happily ever after.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Is process hurting your company? If so, it might be worth considering whether you actually &lt;em&gt;need&lt;/em&gt; all your documented processes, or
whether you can just set desired outcomes and performance metrics, and leave your smart people to figure things out for themselv...&lt;/p&gt;

&lt;p&gt;... oh. I get it. Smart people. They've already left. Never mind.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Fri, 14 Oct 2011 04:50:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/the_book_of_process" /><a10:updated>2011-10-14T04:50:00+10:00</a10:updated><a10:content type="text">&lt;ol&gt;
&lt;li&gt;Once upon a time, a company's youthful founder lucked upon a successful method of performing a task.&lt;/li&gt;
&lt;li&gt;The task was profitable, and therefore it was good.&lt;/li&gt;
&lt;li&gt;The founder wrote down that method and bestowed it unto his/her minions.&lt;/li&gt;
&lt;li&gt;S/he said unto them, "This is The Process, and it is good."&lt;/li&gt;
&lt;li&gt;The minions performed The Process until the end of days.&lt;/li&gt;
&lt;li&gt;And they all lived happily ever after.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;The adage, "If it ain't broke, don't fix it" has a corollary best expressed by Tess Ferrandez: &lt;a href="http://blogs.msdn.com/b/tess/"&gt;If broken it is, fix it you should&lt;/a&gt;.
Or at least, "If broken it is, don't inflict it on everyone just because it's all too hard to bother changing it."&lt;/p&gt;

&lt;p&gt;I'm referring to internal corporate processes that serve no purpose other than demonstrating to some ISO 9000 certification
minion that a documented process exists.&lt;/p&gt;

&lt;p&gt;It seems as if every organisation, once it reaches a certain size, goes into the "create process and perish" stage. If it's
a private enterprise it'll die a long, slow, horrible death of three-thousand triplicate signatures, but if it's a government
enterprise then it's never going to die and we're all going to hate it.&lt;/p&gt;

&lt;p&gt;Is hate too strong a word? I don't think so. Show me a single person who's dealt with a government department and left happy,
and I'll show you someone who's on far too many psychedelics to be on the same planet as the rest of us. &lt;em&gt;We hate government
agencies because they're slow, bloated and inefficient.&lt;/em&gt; (We hate individual governments, too, but for different reasons.
That's just not the point of this post.)&lt;/p&gt;

&lt;p&gt;So, given the choice, why do organisations choose to have processes that make them slow, bloated and despised? Your guess is as
good as mine, but I think it's to do with some misguided idea that they should be able to have any human follow the process
and get the same result. Guess what, ladies and gentlemen: if you have a muppet-followable process then you'll end up hiring
muppets to implement it - which is at best embarrassing while the process makes sense, but an utter disaster once the process
becomes obsolete and everyone refuses to recognise it.&lt;/p&gt;

&lt;p&gt;The Book of Process above &lt;em&gt;should&lt;/em&gt; read something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once upon a time, a company's youthful founder lucked upon a successful method of performing a task.&lt;/li&gt;
&lt;li&gt;The task was profitable, and therefore it was good.&lt;/li&gt;
&lt;li&gt;The founder wrote down that method and bestowed it unto his/her minions.&lt;/li&gt;
&lt;li&gt;S/he said unto them, "This is The Process, and it is good."&lt;/li&gt;
&lt;li&gt;The minions performed The Process until the end of days.&lt;/li&gt;
&lt;li&gt;The end of days arrived with a pitchfork-waving, torch-brandishing mob of angry citizens who burned the company's offices down around the minions.&lt;/li&gt;
&lt;li&gt;The minions could not find &lt;strike&gt;their backsides with both hands&lt;/strike&gt; the "In Case of Fire" process document quickly enough to escape.&lt;/li&gt;
&lt;li&gt;And the citizens all rejoiced, and lived happily ever after.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Is process hurting your company? If so, it might be worth considering whether you actually &lt;em&gt;need&lt;/em&gt; all your documented processes, or
whether you can just set desired outcomes and performance metrics, and leave your smart people to figure things out for themselv...&lt;/p&gt;

&lt;p&gt;... oh. I get it. Smart people. They've already left. Never mind.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">farewell_steve</guid><link>http://uglybugger.org/software/post/farewell_steve</link><author>andrewh@uglybugger.org</author><title>Farewell, Steve</title><description>&lt;p&gt;There's nothing I can say that hasn't been said before by someone else, about someone else, for similar reasons. Nonetheless: today the world has lost a giant and we are all the poorer for it.&lt;/p&gt;

&lt;p&gt;Steve Jobs changed the game so many times that people lost count. His visionary genius, his personal drive and his dedication to making absolute perfection commonplace have left an indelible legacy in which we all share.&lt;/p&gt;

&lt;p&gt;His arrogance, his of-course-my-way-is-better approach and his unwillingness to compromise cultivated dislike amongst many, but then, nobody else gave the world the iPhone or the MacBook. Steve's arrogance was justified and, well, his way generally &lt;em&gt;was&lt;/em&gt; better.&lt;/p&gt;

&lt;p&gt;Steve's example should prompt all of us - in all industries - to treat elegant, beautiful design as a first-class consideration when creating something. If you build something people love, they will love you for it.&lt;/p&gt;

&lt;p&gt;Farewell, Steve.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.apple.com/" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-sHIUBdzzW1U/To0IZOak0kI/AAAAAAAAAUw/Frefutp_DuY/image%25255B9%25255D.png?imgmax=800" width="595" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 06 Oct 2011 11:46:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/farewell_steve" /><a10:updated>2011-10-06T11:46:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;There's nothing I can say that hasn't been said before by someone else, about someone else, for similar reasons. Nonetheless: today the world has lost a giant and we are all the poorer for it.&lt;/p&gt;

&lt;p&gt;Steve Jobs changed the game so many times that people lost count. His visionary genius, his personal drive and his dedication to making absolute perfection commonplace have left an indelible legacy in which we all share.&lt;/p&gt;

&lt;p&gt;His arrogance, his of-course-my-way-is-better approach and his unwillingness to compromise cultivated dislike amongst many, but then, nobody else gave the world the iPhone or the MacBook. Steve's arrogance was justified and, well, his way generally &lt;em&gt;was&lt;/em&gt; better.&lt;/p&gt;

&lt;p&gt;Steve's example should prompt all of us - in all industries - to treat elegant, beautiful design as a first-class consideration when creating something. If you build something people love, they will love you for it.&lt;/p&gt;

&lt;p&gt;Farewell, Steve.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.apple.com/" target="_blank"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-sHIUBdzzW1U/To0IZOak0kI/AAAAAAAAAUw/Frefutp_DuY/image%25255B9%25255D.png?imgmax=800" width="595" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">the_forgotten_convention_based_test_harness</guid><link>http://uglybugger.org/software/post/the_forgotten_convention_based_test_harness</link><author>andrewh@uglybugger.org</author><title>The Forgotten Convention-Based Test Harness</title><description>&lt;p&gt;I'm writing another MVC3 app. I'm in the same world of pain with respect to magic strings and anonymous classes.
I don't like it here.&lt;/p&gt;

&lt;p&gt;I'm sorry, but who on earth thought that this was a good idea for a method signature?&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot1.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;I mean, seriously? Six strings and a Dictionary&amp;lt;string, object&amp;gt;? And that's a sensible collection of arguments? Why
not add in a RouteValueDictionary (another string/object dictionary) for good measure? Oh, never mind.&lt;/p&gt;

&lt;p&gt;But surely there are smarter overloads than that, right? Well, yes - and honestly, you just couldn't make this stuff up:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot2.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;Oh My Friendly Geranium, but who on earth thought of this - and why wasn't it knocked on the head by someone sensible?
MVC team: I'm really sorry, but IMO you've completely missed the point of a strongly-typed language. I know you've
taken a lot of flak for this over the past few years but, to be honest, it's kind-of deserved :(&lt;/p&gt;

&lt;p&gt;So, what on earth do we do about it?&lt;/p&gt;

&lt;p&gt;When we're in a world of magic-string pain, the first thing to do is generally start creating some conventions. The
second thing, of course, is that we test those conventions using unit tests. Hold on a second, though: we're using a
strongly-typed language and yet we're *writing unit tests *to test our conventions because we're using strings and
anonymous classes? Why don't we have a tool that does this for us?&lt;/p&gt;

&lt;p&gt;We want a convention-based test harness that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs on every build. &lt;/li&gt;
&lt;li&gt;Has a set of conventions that are clear and unambiguous. &lt;/li&gt;
&lt;li&gt;Doesn't make us manually write tests. &lt;/li&gt;
&lt;li&gt;Will auto-generate test cases for every new piece of code we write. &lt;/li&gt;
&lt;li&gt;Is refactoring-friendly. &lt;/li&gt;
&lt;li&gt;Is fast. &lt;/li&gt;
&lt;li&gt;Will fail the build if something's wrong. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think we've forgotten something important. Can anyone point to a tool that's all of the above, comes pre-installed
with every version of Visual Studio and requires zero integration work, no NuGet packages and &lt;em&gt;just works&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Anyone? Anyone? No? Here's one: csc.exe. Yep, that's right: use the compiler.&lt;/p&gt;

&lt;p&gt;Call me old-school, but a compiler is all of the above. Consider this method:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot3.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;Think about it: why don't I have to test that a and b are integers? Sure, I should be testing for edge cases here, but
I don't have to type-check or null-check my inputs. Why not? Because the compiler is enforcing the convention that
when I say "int", I mean a 32-bit integer and it simply won't let anyone pass in anything else.&lt;/p&gt;

&lt;p&gt;I don't have to write a single unit test to enforce these conventions. The compiler will provide me with fast and
reliable feedback - at compile time - if I've broken anything, which is far better than getting the feedback at
run-time using unit tests (or worse, at run-time when a user hits an issue).&lt;/p&gt;

&lt;p&gt;I think we as developers can afford to take a bit more time to write strongly-typed code, e.g. HtmlHelpers for
controller actions. Try this one:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot4.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;You can make your code infer the controller name, the action name, the area and all sorts of things without ever having
a magic string. You could even add strongly-typed parameters to it (built using a fluent interface) so that it's
effectively impossible to get it wrong without the compiler complaining.&lt;/p&gt;

&lt;p&gt;So why don't more people use such a great convention-based test tool? I have no idea.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Thu, 29 Sep 2011 09:31:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/the_forgotten_convention_based_test_harness" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot1.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot2.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot3.png/" /><a10:link rel="image" href="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot4.png/" /><a10:updated>2011-09-29T09:31:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I'm writing another MVC3 app. I'm in the same world of pain with respect to magic strings and anonymous classes.
I don't like it here.&lt;/p&gt;

&lt;p&gt;I'm sorry, but who on earth thought that this was a good idea for a method signature?&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot1.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;I mean, seriously? Six strings and a Dictionary&amp;lt;string, object&amp;gt;? And that's a sensible collection of arguments? Why
not add in a RouteValueDictionary (another string/object dictionary) for good measure? Oh, never mind.&lt;/p&gt;

&lt;p&gt;But surely there are smarter overloads than that, right? Well, yes - and honestly, you just couldn't make this stuff up:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot2.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;Oh My Friendly Geranium, but who on earth thought of this - and why wasn't it knocked on the head by someone sensible?
MVC team: I'm really sorry, but IMO you've completely missed the point of a strongly-typed language. I know you've
taken a lot of flak for this over the past few years but, to be honest, it's kind-of deserved :(&lt;/p&gt;

&lt;p&gt;So, what on earth do we do about it?&lt;/p&gt;

&lt;p&gt;When we're in a world of magic-string pain, the first thing to do is generally start creating some conventions. The
second thing, of course, is that we test those conventions using unit tests. Hold on a second, though: we're using a
strongly-typed language and yet we're *writing unit tests *to test our conventions because we're using strings and
anonymous classes? Why don't we have a tool that does this for us?&lt;/p&gt;

&lt;p&gt;We want a convention-based test harness that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs on every build. &lt;/li&gt;
&lt;li&gt;Has a set of conventions that are clear and unambiguous. &lt;/li&gt;
&lt;li&gt;Doesn't make us manually write tests. &lt;/li&gt;
&lt;li&gt;Will auto-generate test cases for every new piece of code we write. &lt;/li&gt;
&lt;li&gt;Is refactoring-friendly. &lt;/li&gt;
&lt;li&gt;Is fast. &lt;/li&gt;
&lt;li&gt;Will fail the build if something's wrong. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think we've forgotten something important. Can anyone point to a tool that's all of the above, comes pre-installed
with every version of Visual Studio and requires zero integration work, no NuGet packages and &lt;em&gt;just works&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Anyone? Anyone? No? Here's one: csc.exe. Yep, that's right: use the compiler.&lt;/p&gt;

&lt;p&gt;Call me old-school, but a compiler is all of the above. Consider this method:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot3.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;Think about it: why don't I have to test that a and b are integers? Sure, I should be testing for edge cases here, but
I don't have to type-check or null-check my inputs. Why not? Because the compiler is enforcing the convention that
when I say "int", I mean a 32-bit integer and it simply won't let anyone pass in anything else.&lt;/p&gt;

&lt;p&gt;I don't have to write a single unit test to enforce these conventions. The compiler will provide me with fast and
reliable feedback - at compile time - if I've broken anything, which is far better than getting the feedback at
run-time using unit tests (or worse, at run-time when a user hits an issue).&lt;/p&gt;

&lt;p&gt;I think we as developers can afford to take a bit more time to write strongly-typed code, e.g. HtmlHelpers for
controller actions. Try this one:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://uglybugger.org/software/image/Software._2011._2011._09._29._0931._1000.Screenshot4.png/" alt="Screenshot"/&gt;&lt;/p&gt;

&lt;p&gt;You can make your code infer the controller name, the action name, the area and all sorts of things without ever having
a magic string. You could even add strongly-typed parameters to it (built using a fluent interface) so that it's
effectively impossible to get it wrong without the compiler complaining.&lt;/p&gt;

&lt;p&gt;So why don't more people use such a great convention-based test tool? I have no idea.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">iphone_monotouch_unit_testing_with_team_foundation_server</guid><link>http://uglybugger.org/software/post/iphone_monotouch_unit_testing_with_team_foundation_server</link><author>andrewh@uglybugger.org</author><title>iPhone/MonoTouch Unit Testing with Team Foundation Server</title><description>&lt;p&gt;I know, I know: apples, oranges etc. It's not really, though - this is actually quite straight-forward. But first, some background.&lt;/p&gt;

&lt;p&gt;I was recently involved in building another iPhone application for an enterprise customer. We had previously dealt with that customer and had a good working relationship and level of trust with them, but a huge part of that trust was the visibility that we provided as to what was going on. It's mostly off-topic for this post, but the way we did it involved using Team Foundation Server, giving the client's people accounts and making sure that the client's product owner could log in at any time and see how the project was going.&lt;/p&gt;

&lt;p&gt;With the iPhone application, we wanted to do exactly the same. The problem was that we hadn't had that much experience using TFS to build iPhone apps. Most of our collective efforts had either been in Objective C using git (the stock-standard approach that Xcode pushes) or C#/MonoTouch using Mercurial (my experience). While both of those approaches are fine for personal and small projects, we really wanted all the other bonus points that TFS provides (continuous integration, work item tracking, reporting, web-based project portal etc.)&lt;/p&gt;

&lt;p&gt;So how'd we do it? Well, the first thing to note is that we're not actually building the application bundle using TFS - yet. That still requires a MacBook, MonoDevelop and a bunch of other stuff. We'll probably get there soon using custom build tasks, rsync, ssh and a few other things, but we're not quite there yet.&lt;/p&gt;

&lt;p&gt;What we &lt;em&gt;do&lt;/em&gt; have is a working continuous integration and nightly build, plus running tests using MSTest. The nice thing is that it actually wasn't that hard.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the project in Visual Studio (not MonoDevelop). You'll probably need something like Chris Small's &lt;a href="https://bitbucket.org/mrshrinkray/monotouch-samples/src/b1983c0a8d68/MonotouchProjectConverter/" target="_blank"&gt;MonoTouch Project Converter&lt;/a&gt; to make this work happily.&lt;/li&gt;
&lt;li&gt;Include monotouch.dll in your /lib directory and reference it from there rather than from the GAC. (It won't be in the GAC on your build server, and nor should it be.)&lt;/li&gt;
&lt;li&gt;If you have other dependencies (e.g. System.Data), copy those from your MacBook into /lib as well and reference those from there.&lt;/li&gt;
&lt;li&gt;Done :)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key point to note when you're building your app is that you're not going to be able to easily test your ViewController classes using MSTest, so make them dumb. If there's business logic in there, extract it out into your domain model. If there's data access logic in there... well... you're doing it wrong anyway and you should &lt;em&gt;definitely&lt;/em&gt; extract that out :)&lt;/p&gt;

&lt;p&gt;You'll end up with an app that has a dumb(ish) UI shell wrapped around a bunch of well-tested business logic classes. The added bonus of doing it this way is that you can then re-use a lot of that code when you write your WP7 or Android version.&lt;/p&gt;

&lt;p&gt;The outcome? The visibility we wanted from the reporting and work item tracking side of things, plus a CI build that didn't require witchcraft to configure, plus automated unit tests.&lt;/p&gt;

&lt;p&gt;The only real down-side of this approach is that the build we're unit-testing isn't the build we're shipping - we still have to build that manually on a MacBook somewhere. It does, however, give us a good indication of our overall code quality and a reliable safety net for refactoring.&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Mon, 26 Sep 2011 09:19:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/iphone_monotouch_unit_testing_with_team_foundation_server" /><a10:updated>2011-09-26T09:19:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I know, I know: apples, oranges etc. It's not really, though - this is actually quite straight-forward. But first, some background.&lt;/p&gt;

&lt;p&gt;I was recently involved in building another iPhone application for an enterprise customer. We had previously dealt with that customer and had a good working relationship and level of trust with them, but a huge part of that trust was the visibility that we provided as to what was going on. It's mostly off-topic for this post, but the way we did it involved using Team Foundation Server, giving the client's people accounts and making sure that the client's product owner could log in at any time and see how the project was going.&lt;/p&gt;

&lt;p&gt;With the iPhone application, we wanted to do exactly the same. The problem was that we hadn't had that much experience using TFS to build iPhone apps. Most of our collective efforts had either been in Objective C using git (the stock-standard approach that Xcode pushes) or C#/MonoTouch using Mercurial (my experience). While both of those approaches are fine for personal and small projects, we really wanted all the other bonus points that TFS provides (continuous integration, work item tracking, reporting, web-based project portal etc.)&lt;/p&gt;

&lt;p&gt;So how'd we do it? Well, the first thing to note is that we're not actually building the application bundle using TFS - yet. That still requires a MacBook, MonoDevelop and a bunch of other stuff. We'll probably get there soon using custom build tasks, rsync, ssh and a few other things, but we're not quite there yet.&lt;/p&gt;

&lt;p&gt;What we &lt;em&gt;do&lt;/em&gt; have is a working continuous integration and nightly build, plus running tests using MSTest. The nice thing is that it actually wasn't that hard.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the project in Visual Studio (not MonoDevelop). You'll probably need something like Chris Small's &lt;a href="https://bitbucket.org/mrshrinkray/monotouch-samples/src/b1983c0a8d68/MonotouchProjectConverter/" target="_blank"&gt;MonoTouch Project Converter&lt;/a&gt; to make this work happily.&lt;/li&gt;
&lt;li&gt;Include monotouch.dll in your /lib directory and reference it from there rather than from the GAC. (It won't be in the GAC on your build server, and nor should it be.)&lt;/li&gt;
&lt;li&gt;If you have other dependencies (e.g. System.Data), copy those from your MacBook into /lib as well and reference those from there.&lt;/li&gt;
&lt;li&gt;Done :)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key point to note when you're building your app is that you're not going to be able to easily test your ViewController classes using MSTest, so make them dumb. If there's business logic in there, extract it out into your domain model. If there's data access logic in there... well... you're doing it wrong anyway and you should &lt;em&gt;definitely&lt;/em&gt; extract that out :)&lt;/p&gt;

&lt;p&gt;You'll end up with an app that has a dumb(ish) UI shell wrapped around a bunch of well-tested business logic classes. The added bonus of doing it this way is that you can then re-use a lot of that code when you write your WP7 or Android version.&lt;/p&gt;

&lt;p&gt;The outcome? The visibility we wanted from the reporting and work item tracking side of things, plus a CI build that didn't require witchcraft to configure, plus automated unit tests.&lt;/p&gt;

&lt;p&gt;The only real down-side of this approach is that the build we're unit-testing isn't the build we're shipping - we still have to build that manually on a MacBook somewhere. It does, however, give us a good indication of our overall code quality and a reliable safety net for refactoring.&lt;/p&gt;
</a10:content></item><item><guid isPermaLink="false">an_iphone_eye_for_the_c_guy_at_dddbrisbane</guid><link>http://uglybugger.org/software/post/an_iphone_eye_for_the_c_guy_at_dddbrisbane</link><author>andrewh@uglybugger.org</author><title>An iPhone Eye for the C# Guy at @dddbrisbane</title><description>&lt;p&gt;I just submitted this abstract for &lt;a href="http://www.dddbrisbane.com/" target="_blank"&gt;DDD Brisbane 2011&lt;/a&gt;. Don't forget to vote for me!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;An iPhone Eye for the C# Guy&lt;/strong&gt;&lt;/p&gt;
  
  &lt;p&gt;&lt;em&gt;iPhone Development using MonoTouch&lt;/em&gt;&lt;/p&gt;
  
  &lt;p&gt;This session will cover the basics of developing an iPhone application using C#/MonoTouch, from how to create a "Hello, world!" app through to a look at a real-world, production codebase.&lt;/p&gt;
  
  &lt;p&gt;We'll cover the use of web services, threads, databases, generics (yes, you &lt;em&gt;can&lt;/em&gt; use generics), reflection, inversion of control (yes, you can use IoC, too!) and general application architecture, and finish with a look at some tools, tips and tricks to make life as an iPhone developer much less painful.&lt;/p&gt;
  
  &lt;p&gt;This session will assume prior knowledge of threading, reflection, generics, inversion of control and why you'd want to use all of these, but don't let that scare you :)&lt;/p&gt;
&lt;/blockquote&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Sat, 27 Aug 2011 10:28:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/an_iphone_eye_for_the_c_guy_at_dddbrisbane" /><a10:updated>2011-08-27T10:28:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;I just submitted this abstract for &lt;a href="http://www.dddbrisbane.com/" target="_blank"&gt;DDD Brisbane 2011&lt;/a&gt;. Don't forget to vote for me!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;An iPhone Eye for the C# Guy&lt;/strong&gt;&lt;/p&gt;
  
  &lt;p&gt;&lt;em&gt;iPhone Development using MonoTouch&lt;/em&gt;&lt;/p&gt;
  
  &lt;p&gt;This session will cover the basics of developing an iPhone application using C#/MonoTouch, from how to create a "Hello, world!" app through to a look at a real-world, production codebase.&lt;/p&gt;
  
  &lt;p&gt;We'll cover the use of web services, threads, databases, generics (yes, you &lt;em&gt;can&lt;/em&gt; use generics), reflection, inversion of control (yes, you can use IoC, too!) and general application architecture, and finish with a look at some tools, tips and tricks to make life as an iPhone developer much less painful.&lt;/p&gt;
  
  &lt;p&gt;This session will assume prior knowledge of threading, reflection, generics, inversion of control and why you'd want to use all of these, but don't let that scare you :)&lt;/p&gt;
&lt;/blockquote&gt;
</a10:content></item><item><guid isPermaLink="false">crash_logging_in_a_monotouch_app</guid><link>http://uglybugger.org/software/post/crash_logging_in_a_monotouch_app</link><author>andrewh@uglybugger.org</author><title>Crash Logging in a MonoTouch App</title><description>&lt;p&gt;Customer: Your app crashed again.&lt;br/&gt;
Developer: How? What were you doing when it crashed? What happened?&lt;br/&gt;
Customer: I don't know. I was playing with it and it crashed.&lt;br/&gt;
Developer: Do you remember which page you were on?&lt;br/&gt;
Customer: ?&lt;br/&gt;
Developer: &lt;em&gt;bangs head against wall&lt;/em&gt;&lt;br/&gt;
Sound familiar?&lt;br/&gt;
One of the first things I do when I start a project (or when I inherit one) is set up logging. You'd be amazed and depressed at how many projects just don't have any, or bolt it on as an after thought. Here's a hint: &lt;em&gt;it's much easier to debug your app while you're developing it if you know where it's breaking&lt;/em&gt;. Ground-breaking, I know &lt;img alt="Smile with tongue out" class="wlEmoticon wlEmoticon-smilewithtongueout" src="http://lh4.ggpht.com/-3fKyPNGZM5k/TlhCKOHjPgI/AAAAAAAAAUE/16CIyFW1aLg/wlEmoticon-smilewithtongueout2.png?imgmax=800" style="border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none;" /&gt;&lt;br/&gt;
There are a couple of things we want to do:&lt;br/&gt;
1.  Log when the app crashes. Do it quickly and reliably, and don't rely on any app infrastructure (e.g. injected loggers) as it's already been torn down at this point. 
2.  Send the log message the next time the app starts. This will allow us to use all our nice web services etc. and means we can use just the one logging mechanism rather than having several different ones.  MonoDevelop creates a fairly standard-looking Main.cs for us: &lt;/p&gt;

&lt;p&gt;Let's change that to add a simple try/catch block:  &lt;/p&gt;

&lt;p&gt;The key here is line 11 - it makes it simple and obvious as to what it's doing.&lt;br/&gt;
So... the CrashLog class itself is a static class and doesn't do very much at all. The idea is that it's simple to call and doesn't rely on having any of the app's components still available.  &lt;/p&gt;

&lt;p&gt;We're using the &lt;em&gt;My Documents&lt;/em&gt; special folder as that's where we're reliably allowed to write things to on the filesystem.&lt;br/&gt;
So now that we have our crash logger, let's hook things up so that we can log when the app starts again. In our AppDelegate class:  &lt;/p&gt;

&lt;p&gt;Yes, we're using our IoC container as a service locator. This isn't good, but we can't use constructor injection in our AppDelegate as it's the class responsible for creating our IoC container.&lt;br/&gt;
So how does the logger work? Well, that's up to you. You can choose to make a web-service call; you could spit it to another text file and periodically upload it; you could even send an email if you really wanted to.&lt;br/&gt;
My preference is using a web service as I tend to just hook it straight to the server-side logger (which usually uses log4net under the covers), but your mileage may vary.&lt;br/&gt;
The next time a customer tells you that your app crashed, though, you'll be able to respond with, "I know - and I've already fixed that bug."&lt;/p&gt;
</description><source>Coding for Fun and Profit</source><pubDate>Fri, 26 Aug 2011 10:58:00 +1000</pubDate><a10:link href="http://uglybugger.org/software/post/crash_logging_in_a_monotouch_app" /><a10:updated>2011-08-26T10:58:00+10:00</a10:updated><a10:content type="text">&lt;p&gt;Customer: Your app crashed again.&lt;br/&gt;
Developer: How? What were you doing when it crashed? What happened?&lt;br/&gt;
Customer: I don't know. I was playing with it and it crashed.&lt;br/&gt;
Developer: Do you remember which page you were on?&lt;br/&gt;
Customer: ?&lt;br/&gt;
Developer: &lt;em&gt;bangs head against wall&lt;/em&gt;&lt;br/&gt;
Sound familiar?&lt;br/&gt;
One of the first things I do when I start a project (or when I inherit one) is set up logging. You'd be amazed and depressed at how many projects just don't have any, or bolt it on as an after thought. Here's a hint: &lt;em&gt;it's much easier to debug your app while you're developing it if you know where it's breaking&lt;/em&gt;. Ground-breaking, I know &lt;img alt="Smile with tongue out" class="wlEmoticon wlEmoticon-smilewithtongueout" src="http://lh4.ggpht.com/-3fKyPNGZM5k/TlhCKOHjPgI/AAAAAAAAAUE/16CIyFW1aLg/wlEmoticon-smilewithtongueout2.png?imgmax=800" style="border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none;" /&gt;&lt;br/&gt;
There are a couple of things we want to do:&lt;br/&gt;
1.  Log when the app crashes. Do it quickly and reliably, and don't rely on any app infrastructure (e.g. injected loggers) as it's already been torn down at this point. 
2.  Send the log message the next time the app starts. This will allow us to use all our nice web services etc. and means we can use just the one logging mechanism rather than having several different ones.  MonoDevelop creates a fairly standard-looking Main.cs for us: &lt;/p&gt;

&lt;p&gt;Let's change that to add a simple try/catch block:  &lt;/p&gt;

&lt;p&gt;The key here is line 11 - it makes it simple and obvious as to what it's doing.&lt;br/&gt;
So... the CrashLog class itself is a static class and doesn't do very much at all. The idea is that it's simple to call and doesn't rely on having any of the app's components still available.  &lt;/p&gt;

&lt;p&gt;We're using the &lt;em&gt;My Documents&lt;/em&gt; special folder as that's where we're reliably allowed to write things to on the filesystem.&lt;br/&gt;
So now that we have our crash logger, let's hook things up so that we can log when the app starts again. In our AppDelegate class:  &lt;/p&gt;

&lt;p&gt;Yes, we're using our IoC container as a service locator. This isn't good, but we can't use constructor injection in our AppDelegate as it's the class responsible for creating our IoC container.&lt;br/&gt;
So how does the logger work? Well, that's up to you. You can choose to make a web-service call; you could spit it to another text file and periodically upload it; you could even send an email if you really wanted to.&lt;br/&gt;
My preference is using a web service as I tend to just hook it straight to the server-side logger (which usually uses log4net under the covers), but your mileage may vary.&lt;br/&gt;
The next time a customer tells you that your app crashed, though, you'll be able to respond with, "I know - and I've already fixed that bug."&lt;/p&gt;
</a10:content></item></channel></rss>