MLevel

Please, keep the abstractions to a minimum.

I’m lucky enough to be one of the developers at SuperConnect working on a greenfield software project.  For me brand new projects are one of the most challenging and rewarding experiences a software developer can endure. New projects always introduce a pressure to “get something working.” With this pressure it is very easy to introduce decisions that can haunt a project for the rest of its lifetime.  Over time these rushed decisions can introduce technical debt which will grow and eventually make a project impossible to maintain and simply painful for new developers to join.  Technical debt inevitably adds time and cost to every future change and addition.  These “bad decisions” will also ripple throughout future decisions if not realized and fixed. The SOLID principles provide “guidelines” for combating bad design; the hard part is not understanding these principles but actually applying them to real world projects and ever-changing requirements.

Good software designs let software evolve naturally; the open/closed principal states “software should be open to extension but closed to modification.”  This means that if the software product team comes up with a new feature idea, then a good design should find it easy to incorporate by writing new code.  If product comes up with a change to existing functionally, then a good design should find it easy to incorporate with new code but will require existing code to change, maybe a lot. It’s important to understand that when requirements change, it’s OK to rewrite code. Having to rewrite code doesn’t mean your design has failed, it simply means your design has changed.  Technical debt often incurs when building atop of your project when you actually need to reorganize and rewrite existing code.

Often developers combat the open/closed problem by introducing  software abstractions. Even Wikipedia says that software abstractions can help keep your application stay open to extension. Being open is great because it means developers can implement whatever the product team wants, and for a low cost without sweeping impacts. What is not often discussed is the downside of premature abstractions.  When working on new projects it can be very tempting to over-engineer in order to “be ready” for what may come next.  The important part of that statement is what may come next…if you don’t know it’s not necessary. Early abstractions simply introduce complexity. Complexity is a software developer’s worst nightmare, it makes it harder to understand how changes to one part of your system affect other parts. Complexity adds cost to change and new projects change more frequently, therefore that cost is incurred more often.

Let us recap the requirements of the new project design laid out.  It should be easy to add new features and change the way existing features work. A common technique for providing a flexible software project is to introduce abstractions to limit the impact of change across the system. On the other hand abstractions introduce complexity which make projects harder to design and build. Catch-22, anyone?

Luckily greenfield development has another huge advantage, it means the developer gets to choose what frameworks they develop their project atop.  The abstractions necessary to build robust and well designed software already live in the frameworks, so all the developers have to do is understand how to use the framework and try their best to not reinvent the wheel.  I’ll say it again because it’s so important and is the goal of this post:

… look to the framework with which you are building your application for the necessary abstractions during the early stages of development.

Some may be hesitant to depend so heavily upon single framework or a suite of frameworks, but the truth is that these framework were designed to solve a majority of the problems for new projects. When a project grows big enough to require additional abstractions, you’ll also have a better idea of how to implement it since you’ll understand the existing frameworks limitations and existing extension points.

Being a Microsoft shop we get to use the newest and most powerful web technologies available. That includes windows azure with asp.net, mvc w/ razor, jquery, and entity framework.  All of these frameworks provide structure and abstractions to design more than 80% of any ideas product can come up with.  A developer’s time is better spent understanding these frameworks and using them to their advantage as opposed to building complexity atop of a plenty flexible system. All too often I have written code only to find out that the framework exposes better solutions to the problem I need to solve.

A few tips for starting new “enterprise” projects. First and foremost, don’t abstract away the power of the framework. Provide abstractions where you need testable code or have confidence in a product design decision. Appreciate, understand, and most importantly use the existing abstraction and extension points provided in the framework you’re using.  Have confidence in your team and provide training if people are exploiting the framework; don’t waste time trying to write abstractions to simplify other developers’ jobs.

I’ve included an example of creating a twitter bootstrap suite of HtmlHelpers to greatly simplify the markup required for creating CRUD webpages. The cool part is that by taking advantage of Microsoft’s existing abstractions including HtmlHelper and WebViewPage, we can write a pretty tiny bit of code which doesn’t introduce additional abstractions. Also this code doesn’t require drastic changes to our existing code base to make the switch. We don’t have to go back and change a bunch of stuff to make it work with our new design.

The twitter bootstrap example is hosted on github https://github.com/SuperConnect/TwitterBootstrapHtmlHelper

 

Share this post

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on pinterest
Share on print
Share on email

2 thoughts on “Please, keep the abstractions to a minimum.”

  1. Avatar

    Fantastic! As developers, we often talk about premature optimization, feature creep, etc. – but rarely talk about abstraction in this manner.

    Note: I would love to see a follow-up article that details the criteria (a checklist?) you might use to answer the “should I use an abstraction?” question.

  2. Avatar

    Hey Michael: Yeah I agree, sometimes as engineers we forget to discuss the downside of patterns because we’re so excited to play with new and shiny tools. Especially on new projects when there is no demand from existing infrastructure and system limitations. Ayenda is currently writing a brainstorm on design patterns test of time. His earlier articles in regards to the repository pattern originally got me thinking about “Am I abstracting away the power of my framework?” I think there is a lot of good reading on the subject from Matt Hidinger, blog.AppHarbor, and more Ayenda.

Leave a Comment