Fowler’s Technical Debt Quadrant – Giving the co-ordinates where Agile is contraindicated.

Martin Fowler’s bliki has a very good post on what he calls the ‘technical debt quadrant‘. This post succinctly sums up the difference between those who produce poor designs in ways that are contrary to their best interests, and those who do so knowingly and reluctantly.

In the past I’ve noted that many of those who profess to being agile are really just defaulters in the bank of technical debt. They confuse incurring inadvertent reckless technical debt with being Agile. The YAGNI (You Ain’t Gonna Need It) maxim is an example of something that, when used prudently and knowingly, is a sensible (temporary) acceptance of short term technical debt. In the hands of those who recklessly and inadvertently incur technical debt, it becomes a waiver for all sorts of abuses of good software development practice. It’s not uncommon in small cash-strapped start-ups to hear people invoke the YAGNI maxim as they contemplate key architectural issues, confusing cost-cutting with architectural parsimony. I think it’s safe to say that those who live in the dark waters of the bottom left of the quadrant need the formality of a more ‘regulated’  process to support them as they grope their way into the light.

Does formality have to mean expensive? I don’t think so. I think in most cases it’s a matter of perception – people assume that ‘formality’ implies back-breaking bureaucracy. It needn’t, it just means creating a framework that helps people to stop, take a breath and look around them. Without that, people often lose their way and drive headlong into crippling technical debt. I’ve seen large companies that consciously avoided using up-front design subsequently paying the cost of that debt for years afterwards in maintenance. One notable example would regularly burn through its OpEx budget within the first 6 months of each year – they had a product that was so badly designed, inconsistent and hard to maintain that they lost all forward momentum, threw away their monopoly and effectively lost their place in the market. All through lack of up-front design and architecture.

For all companies where stakeholders are either so stressed or so inexperienced that they opt for the lower left of Fowler’s quadrant, Agile is contraindicated.

Eeebuntu

Perhaps the day has finally arrived when GNU/Linux seems like a viable option. Every six months or so I try out the latest GNU/Linux distros to see how they’re progressing. I look at them from the usual jaundiced perspective of the professional programmer. Not from the naive perspective of teenage rebellion. Normally I end up wandering off in disgust at the unfinished feel of the whole ensemble.

All I want is an environment that doesn’t fight back when I use it. I only care if it is possible to run all the usual tools with a minimum of fuss and bother. And, believe it or not, that’s fairly true of Eeebuntu. (With the sole exception of the fact that monodevelop is still a very long way behind VS 2010 or even sharpdevelop, but you can still do real C# development, and that’s so very cool).

I guess I’m lucky because I chose a distro specifically designed for my brand of machine, so everything is tuned and provided and properly configured. But it still amazes me that I am up and running in minutes (including dev tools) where previously on GNU/Linux that would have taken weeks of frustration.

I love the package management systems – they are (so far) flawless, as was the OS installer. Google Chrome, MonoDevelop, Mono, XSP2 and even ASP.NET MVC 1.0 are all available directly from the synaptic package manager and all install and run completely without hitches.

MonoDevelop even has settings allowing it to default to using VS 2010 project file formats! I’m impressed. Really. No piss taking at all. Well done, all involved.

PostSharp Laos – Beautiful AOP.

I’ve recently been using PostSharp 1.5 (Laos) to implement various features such as logging, tracing, API performance counter recording, and repeatability on the softphone app I’ve been developing. Previously, we’d been either using hand-rolled code generation systems to augment the APIs with IDisposable-style wrappers, or hand coded the wrappers within the implementation code. The problem was that by the time we’d added all of the above, there were hundreds of lines of code to maintain around the few lines of code that actually provided a business benefit.

Several years ago, when I worked for Avanade, I worked on a very large scale project that used the Avanade Connected Architecture (ACA.NET) – a proprietary competitor for PostSharp. We found Aspect Oriented Programming (AOP) to be a great way to focus on the job at hand and reliably dot all the ‘i’s and cross all the ‘t’s in a single step at a later date.

ACA.NET, at that time, used a precursor of the P&P Configuration Application Block and performed a form of post build step to create external wrappers that instantiated the aspect call chain prior to invoking your service method. That was a very neat step that could allow configurable specifications of applicable aspects. It allowed us to develop the code in a very naive in-proc way, and then augment the code with top level exception handlers, transactionality etc at the same time that we changed the physical deployment architecture. Since that time, I’ve missed the lack of such a tool, so it was a pleasure to finally acquaint myself  with PostSharp.

I’d always been intending to introduce PostSharp here, but I’d just never had time to do it. Well, I finally found the time in recent weeks and was able to do that most gratifying thing – remove and simplify code, improve performance and code quality, reduced maintenance costs and increased the ease with I introduce new code policies all in a single step. And all without even scratching the surface of what PostSharp is capable of.

Here’s a little example of the power of AOP using PostSharp, inspired by Elevate’s memoize extension method. We try to distinguish as many of our APIs as possible into Pure and Impure. Those that are impure get database locks, retry handlers etc. Those that are pure in a functional sense can be cached, or memoized. Those that are not pure in a functional sense are those that while not saving any data still are not one-to-one between arguments and result, sadly that’s most of mine (it’s a distributed event driven app).

[Serializable]
public class PureAttribute : OnMethodInvocationAspect
{
    Dictionary<int, object> PreviousResults = new Dictionary<int, object>();

    public override void OnInvocation(MethodInvocationEventArgs eventArgs)
    {
        int hashcode = GetArgumentArrayHashcode(eventArgs.Method, eventArgs.GetArgumentArray());
        if (PreviousResults.ContainsKey(hashcode))
            eventArgs.ReturnValue = PreviousResults[hashcode];
        else
        {
            eventArgs.Proceed();
            PreviousResults[hashcode] = eventArgs.ReturnValue;
        }
    }

    public int GetArgumentArrayHashcode(MethodInfo method, params object[] args)
    {
        StringBuilder result = new StringBuilder(method.GetHashCode().ToString());

        foreach (object item in args)
            result.Append(item);
        return result.ToString().GetHashCode();
    }
}

I love what I achieved here, not least for the fact that it took me no more than about 20 lines of code to do it. But that’s not the real killer feature, for me. It’s the fact that PostSharp Laos has MulticastAttributes, that allow me to apply the advice to numerous methods in a single instruction, or even numerous classes or even every method of every class of an assembly. I can specify what to attach the aspects to by using regular expressions, or wildcards. Here’s an example that applies an aspect to all public methods in class MyServiceClass.

[assembly: Pure(
    AspectPriority = 2,
    AttributeTargetAssemblies = "MyAssembly",
    AttributeTargetTypes = "UiFacade.MyServiceClass",
    AttributeTargetMemberAttributes = MulticastAttributes.Public,
    AttributeTargetMembers = "*")]

Here’s an example that uses a wildcard to NOT apply the aspect to those methods that end in “Impl”.

[assembly: Pure(
    AspectPriority = 2,
    AttributeTargetAssemblies = "MyAssembly",
    AttributeTargetTypes = "UiFacade.MyServiceClass",
    AttributeTargetMemberAttributes = MulticastAttributes.Public,
    AttributeExclude = true,
    AttributeTargetMembers = "*Impl")]

Do you use AOP? What aspects do you use, other than the usual suspects above?

Does this seem nice to you?

After years of recoiling at the sight of code like this, am I supposed now to embrace it in a spirit of reconciliation?

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic blah = GetTheBlah();
            Console.WriteLine(blah);
        }

        private static dynamic GetTheBlah()
        {
            if (DateTime.Now.Millisecond % 3 == 0)
                return 0;
            else
                return "hello world!";
        }
    }
}

need to wash my hands.

Quote of the Day – Chris Sells on Cocktail Parties

I can relate to this:

I’ll take a lake of fire any day over more than three strangers in a room with which I share no common task and with whom I’m expected to socialize

How to express this to my wife without her thinking that I am suffering from a combination of acrophobia and Downs Syndrome…?

BTW: I was surfing Chris’ blog because I’ve finally made the time to explore MGrammar and the “OSLO” SDK.

Expect to see a resurgance of blogging on this site, as I introduce you to my new open source project.

Expect to hear a bit about MGrammar, PEX, F#, Powershell, and declarative architecture specifications…

… I’m excited. New toys to play with and some amazing new productivity enhancements to play with…

Australian Port – a new WMD?

IMG_0048

Proving that Cockroaches are not indestructible, Kerry neatly (if inadvertently) demonstrated that Australian port is capable of killing things that heat, cold and lethal levels of ionizing radiation cannot.

Of course Kerry was gagging for days just at the thought that the thing had been in her glass all along – it probably hadn’t – but I forgot to mention that anything that can kill a cockroach can surely kill the bacteria that the cockroach carries…