Thursday, August 19, 2010

Complex code isn't always better

As a developer, I feel that we often have an aversion to code that feels or looks overly simple. If we don't inject a minimum level of complexity into the end result, somehow we are not justifying our worth. I know that deciding what is too complex is rather subjective, but it's a discussion worth having. On the team I work with, I always emphasize that the best code is the ones that require minimum amount of effort to understand. Don't turn something into a multi-class factory monstrosity if a hardcoded list is more than enough to get the job done. Keep It Simple! The principal is very basic, but often overlooked in practice. Take for example the following pseudo validation code,

public void CheckLimitsWithinRange()
{
    CheckInRange(AbsoluteMinimum, SuggestedMinimum, "absolute minimum", "suggested minimum");
    CheckInRange(SuggestedMinimum, SuggestedMaximum, "suggested minimum", "suggested maximum");
    CheckInRange(SuggestedMaximum, AbsoluteMaximum, "suggested maximum", "absolute maximum");
    CheckInRange(AbsoluteMaximum, 9999, "absolute maximum", "9999");
}

private void CheckInRange(decimal first, decimal second, string property1, string property2)
{
    if ((first < 0) || first > second)
        Errors.Add(String.Format("{0} cannot be less than 0 or greater than {1}", property1, property2));
}

and compare that with

public void CheckLimitsWithinRange()
{
    if ((AbsoluteMinimum < 0) || (AbsoluteMinimum > SuggestedMinimum))
        Errors.Add("absolute minimum cannot be less than 0 or greater than suggested minimum");
    if ((SuggestedMinimum < 0) || (SuggestedMinimum > SuggestedMaximum))
        Errors.Add("suggested minimum cannot be less than 0 or greater than suggested maximum");
    if ((SuggestedMaximum < 0) || (SuggestedMaximum > AbsoluteMaximum))
        Errors.Add("suggested maximum cannot be less than 0 or greater than absolute maximum");
    if ((AbsoluteMaximum < 0) || (AbsoluteMaximum > 9999))
        Errors.Add("absolute maximum cannot be less than 0 or greater than 9999");
}

The two blocks do roughly the same validation, but in my opinion, the latter is far more readable and self-documenting than the former. Yet, I've seen many developers shy away from the easier but plainer code, because the developer instinct often compels them to. The beginner looking block of code is also more maintainable. Imagine part of the rule changes to "suggested minimum" has to be less than 75% of the "suggested maximum". The first example will require a new programmer to retrace the exact thought process of the original writer when that code was first conceived, which is more costly in terms of the time spent.

The example I gave seems pretty silly, but the underlying symptom is very common. When applied on a larger scale, the maintenance overhead is no longer measured in seconds or minutes but rather hours lost in project resources. I guess the point of this rant is that there's a fine balance between well-engineered code and over-engineered code. Not every block of code needs to match the consulting fee your client is paying. It's OK for code to look cheap sometimes.

Thursday, August 12, 2010

You know what? I could really use a package manager!

So last night, I had a real itch to start experimenting with some new technologies coming out in the .NET space. After some going back and forth thinking how I should approach it, I decided that rather than trying to write yet another fake application that I wouldn't finish, I will just fork one of my favorite sample project instead. That way, starting with a well designed application in place and I can replace the relevant layers with the new technologies I am interested in. I get to skip wasting time on code I already know while still learning from something more complex than a "Hello World" demo.

But first thing's first, I want to upgrade the solution to VS 2010 and .NET 4.0. Simple enough right? WRONG! The Microsoft stack is pretty painless to update. A few clicks through a conversion wizard and all the projects are saved in the new format. And then things quickly spiraled out of control from there.

This shouldn't really be a surprise to anybody who use a lot of open source libraries in their projects. Once every few months, we open source addicts will go through a cycle of DLL upgrade hell. Generally triggered by the burning desire to grab the latest release of tool X for a shiny new feature that we just couldn't live without, and it quickly descends into chaos.

Here's how it went down. I first discovered something is not quite clicking when I couldn't start the web application. Broken app = signs of trouble, couldn't be any more obvious. I quickly realized that .NET 4.0 comes with ASP.NET MVC 2, which means I need to upgrade to the newer MvcContrib project.

Some googling, a bit of reading and 15 minutes later, I downloaded and copied over the new MvcContrib assemblies. Compiled and off we go ... not so fast. The compiler was not happy, complaining that Castle.Windsor is outdated. Sigh!

Some more googling, and a couple clicks later, I landed on Castle project's homepage. OK, Downloading the latest now ... but hold on, that version is a bit too new! After some more digging and reading, the right version is copied over. The compiler must be happy now ... Not quite. Rhino.Commons is feeling left out of the party and wants a tune up too. Needless to say, frustration built up quickly. After over an hour of searching and downloading, I decided to throw in the towel and live to upgrade another day.

While walking away, I thought to myself, "you know what? I could really use a package manager!" Then the sky will be blue, the grass will be green and there will be world peace. If only we had something like RubyGems for .NET.

Today, with that lingering thought my my head, I googled for ".NET package manager". I kept my expectations low because surely if there was one, the world would've known. First few pages of the search results confirmed my fear - lots of blog discussions and a few dead projects that never got off the ground. I wasn't ready to gave up just yet however. How about "RubyGems for .NET", I know, sounds crazy, right? And what do you know, looks like there is a NU kid on the block. The project is not even a month old. Someone has done the unthinkable!

Much excitement ensues. Let's see if it will play well with IronRuby, which I already have installed.


I don't know what "thor" is, but that seemed to have gone well. Now let's try to bring down a real package.


Not as smooth. Somewhat ironic that I'm running into an outdated dependency error, but that was easily resolved by a quick self-upgrade. After that, we are really jamming! Gems ... get it? So clever!


A peek in windows explorer, you will see all the necessary dependencies downloaded and copied to the project folder with just a few simple commands.


Compare this to the hours I spent hunting down assemblies by hand, call me impressed. RubyGems + NU definitely fills a void in my arsenal. Couple that with a symbol server, developing with open source tools just became that much easier. I hope the community will embrace it. It definitely has my support.

Friday, August 6, 2010

.NET data serializers face off

For my current project, we have a few fairly sizable object graphs that need to be transported from the middleware server to the rich clients. BinaryFormatter has been the serializer of choice because our payload is not shared with other applications, therefore there is no interoperability needs. But because of the large amount of data, we decided to write a test with Google Protocol Buffers to see how much more efficient it would be to use that as an alternative.

We picked protobuf-net over protobuf# because the former is more aligned with other .NET serialization technologies and requires less effort to migrate. And just for comparison, we also decided to add DataContract and Json.NET serializers into the mix.

The test data consists of roughly 5000 objects in the graph. Each test is repeated 100 times and the results are averaged. The serialization pass uses Stream.Null as the destination buffer. The deserialization pass uses a MemoryStream as the source. A warmup pass is performed to force the JIT compilation, and GC.Collect is called before each test begins.


As expected, both Xml and Json serialization result in larger payloads. Protocol Buffers shows a significant (nearly 60%) saving over BinaryFormatter.



Speed test is where protobuf-net implementation truly shined. It is 5x faster than BinaryFormatter for both serializing and deserializing the object graph. Needless to say, we are probably looking to migrate in the near future.

Wednesday, August 4, 2010

Why can't the beginners and the elites co-exist?

A little post on Microsoft.Data kicked off quite the storm in the blogging community these past couple days. Plenty has been said on both sides of the argument, which I will not regurgitate. But one thing that strikes me is that Microsoft is perpetually trying to cater to this group of non professional developers, understandably a strategy that cemented their position in the industry. From Excel to Access, to FrontPage, and now WebMatrix, they continuously focusing on empowering those whom they describe as "not interested in becoming professional developers", and turning them into, like it or not, the next generation of professional developers. How long will it take before we start seeing these WebMatrix based applications unleashed into the corporate wilderness?

If RoR taught the industry anything, is that it's possible to create a technology that can be both beginner-friendly and architecturally sound. Microsoft should invest their efforts into building the next great .NET platform that unites the community rather than segregates.

It's disheartening to see Microsoft, ignoring the OSS community and the broader industry, releases products that are behind the times and lack innovation, because in many organizations, the implicit seal of approval by being a Microsoft product still drives the management decisions. Those of us who have progressed beyond will be forever fighting an uphill battle, re-culturing tomorrow's senior developers who are spoon-fed by the hobbyist technology stack.