UI Manifesto

Staying D.R.Y.

I am a devout believer in the Don't Repeat Yourself (DRY) or Duplication is Evil (DIE) principle. This principle is easy to adhere to when building the middle-tier, or business layer, in a website architecture. A standard object-oriented business layer is usually just a collection of classes, properties, and methods, which inherently embraces abstraction and the DRY principle. The act of organizing business logic into objects almost forces a programmer to not duplicate business rules, but not all code fits into an object... or does it?

UI Abstraction?

The User Interface (UI), a.k.a. front end, is not as straight forward as the business layer when it comes to staying DRY, or at least so I thought. As I contemplated on this, it became clear that the vast majority of websites, and the various pages in each website, share a lot of the same front-end features (e.g. modal window, forms, autocomplete, etc.). So that begged the question, why should I make the same thing over and over again?! The answer was obvious and my new UI Manifesto was born, which is to build a library of common front-end features, the DRY way.

The Benefits

Apart from the extreme boredom found in doing the same tedious UI features day after day, here are some of the other benefits I have identified in building a DRY-based UI library:

  • Easier to Maintain.

    If there is only one code source for a given feature, then there is only one place to fix it.
  • Easier to Upgrade.

    The same logic applies here as to the maintenance, you upgrade the one code source and voilĂ !
  • Functional & Design Consistency.

    Using the same extracted control will always produce the same look and feature(s). This benefit can really be felt when a development team uses the same UI library, but very much still applies to a solo developer.
  • Faster Development.

    Once a feature is built in the library, all that needs to be done is implement it.

The Build Plans

This will be my third go at building the "ultimate" UI library in my career, and yes, this may not be my last attempt. However, this time might be different. I have learned a few lessons over the years. I believe that my biggest flaw in past attempts has been in making my solutions tightly coupled to the latest and greatest technologies of the moment. Those technologies often end up coming short, and always end up becoming obsolete over time. So keeping the markup loosely coupled from any supporting code is one of the primary build guidelines that I wish to follow. Here are all my build guidelines:

Loose Coupling between the Markup & Supporting Code

Don't get me wrong, I am again planning on using the latest and greatest technologies of the moment (HTML5, CSS3, and jQuery to name a few), but this time I hope to build my new UI library to stand the test of time by strategically deciding where the coupling of these technologies takes place. Any markup outputted by a control in the UI library, must be simple, raw markup. Markup should be a descriptive markup and not a presentational or functionality markup. No in-line styles or scripts. Just tags with attributes, and when I say attributes I really just mean the class attribute and custom data (data-*) attributes. The attributes will be what ties the technologies together. All coupling will be made through these attribute types only, which I believe is a basic and safe technology that is not going anywhere...right!?

The class attribute will obviously couple the markup to how the feature should be styled (CSS), but also to any functionality-supporting JavaScript needed. That part seems pretty much standard. So what is the need of the custom data (data-*) attributes? That is how needed flexibility is accomplished.

Functional Flexibility

Not all implementations of a UI control would/should be completely identical. Let's take a data table (Grid) for example. There are many features that you may want one data table to do, but not another, like sorting, paging, etc. This dilemma is solved through the use of the custom data (data-*) attribute, which is introduced with HTML5 and "intended to store custom data private to the page or application". Sounds like a good fit to me. By use of the custom data attributes (e.g. data-allowsorting="true" or data-allowpaging="false"), optional implementation for each control may be defined and allow any needed customization.

I think it is easiest to think of the class attribute as a method call, and to think of the custom data-* attributes as the optional parameters of that method call.

Future Proof

Not being future proof is where I have failed in my past attempts at building the "perfect" DRY UI library, and that is why I am once again re-building it. The coupling in my UI libraries in the past has been too tight, so when one of the technologies supporting the library has died the entire library has died with it. I am not going to do that again, or at least that is my goal. The class attribute and the custom data (data-*) attributes are the only portion of the UI library that must remain the same moving forward to keep it all compatible. If the markup becomes obsolete, it alone can change and the rest will not be trashed. Same with the other technologies, because you know <sarcasm>jQuery is just a fad and won't stick around for long.</sarcasm>

Future Compatibility

There are many new features in HTML5 that some browsers now support, and the other browsers will follow shortly. With this mixed support, the UI controls can't rely on the native support from the browsers and they can't always get their feature support with the help of some JavaScript that will conflict with the possible native support. There must be levels of graceful degradation or progressive enhancement. In other words, I need to code the markup to trigger the native browser support of a feature, but then test to see if it is actually supported natively. If it is not natively supported, then I must enable the feature in a similar manner using JavaScript, or other techniques.

Simple Implementation

Simple implementation can be interpreted in many ways, but what this really means to me is that I have intelliSense in Visual Studio for the controls as I am implementing them. I don't want to try and remember the 5 to 30 optional custom data attributes for a given control, and each attributes valid values every time I go to implement a control. I can easily solve this problem by creating custom ASP.NET MVC HTML Helpers with class properties and associated enum values. The custom Helpers will then output the appropriate markup and attributes for a feature, and I don't have to remember how to do it each time I go to use it. If I find myself working in a non-Microsoft environment, I can just build similar server-side support and still use the same client-side framework.