In this article we shall discuss some of the core tenets when creating UI frameworks/libraries and how these principles guides us in the development of Gaia. Gaia is an Ajax library for the ASP.NET platform. It takes a philosophically radical different approach than it's platform counterparts, including Microsoft's own ASP.NET Ajax framework.
Many of the assertions here applies just as much to general software development as it does to framework development. It is however necessary with a stronger emphasis on a number of principles since you are now in the sphere of building software for other programmers and not general purpose end user applications. This leads us to one of the first postulates. The developer is the customer.
# The Developer Is The Customer
This gives us a little edge, because we are ourselves in fact developers. We know perfectly well how we want the product to be like. Unfortunately this statement does not always hold true. If it did, then all software libraries would be perfect which they are not. Another pitfall is not keeping your hands dirty, gradually moving away from day to day development work into abstract philosophical reflections in your ivory tower. Suddenly your product doesn't solve the developers itches anymore and it cannot survive.
The derived conclusion is to keep a close customer feedback loop with a focus on customer driven development. Including transparent tracking facilities, daily build system with unit tests and early/often releases. You must listen to the [voice of the customer].
This first postulate is mostly connected with the art of quality, but is deemed so important that leaving it out would make this work look poorer. Quality in your craft extends beyond the product itself and into the whole organization. The product is often just a manifestation of the quality.
Now that we know who the customer is, what can we do for him? This gives us the second postulate.
# The Pain And The Cure Is In The API
Your customers will work mostly with the API, so that's where the pain and cure is. The API is the cornerstone of UI architecture and we will need to lay out some of the fundamentals of success here. The API should be clean, consistent, intuitive and should be carefully designed using best practice design patterns, GRASP principles. Gaia Ajax is composed using many of these patterns and principles, but for sake of brevity I am only going to cover a few GRASP principles here. We will discuss public API, loose coupling and high cohesion.In later blog posts we'll go deeper into design patterns.
Clean
The API is the facade of your product. It's the entrance to your realms. What I mean by clean is that the components do what they should do and nothing more (single responsibility). All the properties of the object serve important and distinct missions, the public API offers a nice grammar and is well documented.
Here's a few coding horror examples
/* C# Source code*/
// what does this property mean?
Widget1.Force = true;
// Dependency order == low cohesion
Widget1.SetThisValueFirst = 50;
Widget1.NowItsSafeToCallMe();
// doesn't work. Either throws NotSupportedException()
// or does nothing. Often introduced through
// inheritance and is no longer needed on the derivate.
Widget1.Items.Add(object);
// Multiple responsibilities in single method call.
// Maybe applicable in end user applications,
// but not in the core API.
Widget1.RollDownWindowAndThenBlink();
// Which one of these works as intended?
Widget1.Items.Add(object);
Widget1.Controls.Add(object);

And here's how you should do it.
/* C# Source code*/
// this one was easy :-)
Widget1.Text = "Hello World";
// hard to guess?
Widget1.OnDoubleClick += evt;
// Keep it simple
Widget1.Enabled = false;
Too simple? That's right. It's because it was well designed.
Consistent
Consistency applies mostly to your expectations across the component array. It's about keeping up with the developers expectations about how things work. Many of the rules outlined above applies here as well. Consistency is about conformity. Choose a convention and stick to it through the entire library. This applies to naming, composition, documentation and usage.

Coding horror examples
/* C# Source Code */
// two different widgets, with two properties
// named and implemented differently.
Button1.ForeColor = Color.Black;
Label1.ForeGroundColor = "black";
// camel casing a method call that obviously
// should have been a property instead.
Window1.setOpacity(50);
// two ways to do the same thing. Not good,
// but unfortunately an inheritance from ASP.NET :-(
Button1.Width = new Unit(250);
Button1.Style["width"] = "250px";
Intuitive
Things are always easier when it's intuitive. A logical structure where things are composed/stacked nicely leaves a smaller footprint and lessens the learning curve. After using a couple of components you should have gotten a headstart on every new component you start using. This is as much about knowledge reuse as code reuse. This is what lead to our fundamental design decision to inherit from the existing ASP.NET controls instead of building them from scratch. It dramatically reduces learning curve and increases compatibility and code reuse. Unfortunately there was a small price to pay there in terms of inheriting bad stuff too. This concept also extends the previous ones and is important in building the foundation of a UI library.
An important
OOP concept from Computer Science. It means that each building block relies less or not at all on other components. We try to make as many building blocks as possible with singular responsibility that can be used in larger composition of complex architecture. If you take a closer look at the Gaia architecture you will see that it's modular structure allows you to make a huge amount of combinations to create derived works. This unleashes creativity (which is a cornerstone in programming practices) and is one of the areas where Gaia excels the most. To illustrate this better let me tell you a short story.
Short story
A potential customer called me up and asked if we had a cropper tool feature. He had looked into a competing vendor which had such a tool, but unfortunately it was tightly integrated into the RadEditor they offered. My answer to him was no, we don't have such a component, but with Gaia it's extremly simple to create one. And then I gave him the recipe on how he could do it with reusing our building blocks to create the cropper tool as s reusable widget.
And we have a plethora of similar stories. The only challenge posed is that many developers are now accustomed to the property morbidity and feature fatness from existing component vendors (without naming any of them) that our thinking framework needs a little brain tweaking to be fully leveraged. Remember this postulate ->
# The best features are the ones you don't have
Highly cohesive
High cohesion correlates with low coupling and is about the responsibility focus of a module. To accomplish the first goals of clean, consistent and logical building blocks you must have high cohesion. To explain low cohesion with a little code example, consider the following.

Coding horror
'Visual Basic.NET
Dim webSvc as new WebService
Dim clientID as Integer = 5
Dim order as Order = webSvc.CreateOrder(clientID)
Dim product as Product = webSvc.GetProduct("Soda")
order.AddProduct(product)
Dim success as Boolean = webSvc.SaveOrder(order)
If success Then
'do something
End If

A more cohesive solution would look something like this
'Visual Basic.NET
Dim webSvc as new WebService
Dim clientID as Integer = 5
Dim success as Boolean
success = webSvc.AddOrder(clientID, Product1, Product2)
if success Then
'do something
End If
As you can see everything is done in a single execution of the AddOrder method. In the horror example you can envision what happens if you get an exception on line 5 :-)
Another coding horror example demonstrating low cohesion
// C# 3.0
var writer = new HtmlTextWriter();
writer.WriteStartElement(DIV);
writer.WriteStartElement(SPAN);
writer.Write("Some content here");
writer.WriteEndElement();
writer.WriteStartElement(IMG);
writer.WriteAttribute("src", "url");
writer.WriteAttribute("alt", "text");
writer.WriteEndElement();
writer.WriteEndElement();
Can you see the related method calls here? What do you think is the probability of getting one of these wrong and thereby rendering falsy output. Since you need to keep track of the method calls yourself you are rendered with a poor API that leaves more responsibility on you and increases the error surface significant.

Let's have a look at the Gaia Ajax implementation of the XhtmlTagFactory which is implemented using the
Factory Design Pattern.
// C# XhtmlTagFactory in Gaia Ajax
using (create.Div())
{
using (create.Div())
{
using (create.Span()) {}
}
}
High cohesion is a fundamental design principle that you should adhere to. Gaia is a prime example of a collection of small and versatile building blocks that when put togheter in a simple way offer new possibilities never before thought of. We created our own XhtmlTextWriter to ensure deterministic destruction by encapsulating the writer in the Using pattern.
# Without a Philosophy it will be a Catastrophe!
Extensible
We have to acknowledge that no matter how many features we put into the library, there will always be a request for more and they will grow in specificity. The developers answer to a feature request is: Yeah, I can do that. And feature by feature the library gets bloated with code that must be maintained, bugfixed, supported, taught and documented. The library increases in size and the learning curve hits the roof exponentially. A developers good intentions leads to a product catastrophe. Because you cannot ensure that all possible feature requests goes into the product, you need to make the product so extensible that it's a breeze for the customer to add their own stuff. We've touched on this previously by talking about coupling and cohesion, but it's of similar importance.
We need to make the product highly extensible with a high variety of options for extending it. It could be done via inheritance, composition, different hooks, templating, etc. So far the extensibility story is quite good in Gaia. We offer many of the beforementioned techniques of extending the library.
-
Inheritance - Inheriting from existing controls is a nice way to extend functionality. It follows a is-a relationship and if wisely thought out allows customers to subclass the controls into their own subset and introduce desired functionality. Currently there's some work left to do here in Gaia. All of the advanced widgets inherit from the base controls ie ( Panel-> HybridPanel -> Window ) and ( Calendar -> CalendarWithTime ), etc.
-
Composition - Composition is the concept of mixing different blocks together to form new functionality. It can be combined with inheritance to introduce the desired features. For example the Window is composed of labels, buttons, images and aspects. Aspects are powerful constructs to add behaviour to controls. The composition of controls allows us to write many of the advanced controls purely in .NET managed code on the server, let it be C#, VB.NET or any other language for that matter.
-
Hooks - With hooks I mean a simpler way of utilizing the framework fully. In Gaia we have hooks to serialize values client/server-wise, sending method calls, raising events on the server from the client, etc. Other hooks include overriden base methods to include script files, utilities for rendering, etc. Hooks easens the extensibility story and allows customers to create exactly what they want, more easily than without the facilities of the framework.
Now let's have a look at how the Gaia Window was created using these built-in facilities.
#Hide it, Please!
In modern development there's many hurdles you need to address to write software. Someone said that programming is the most complex affair the human mind is bothered with. Others say it's even more complex than that. In Web application development there's the nitty gritty details of different browser implementations, javascript, security flaws, etc. All these details should be abstracted away from the developer so he/she can concentrate on their domain specific problems. That was the whole idea behind .NET in the first place. To consolidate development into a unified language for web, windows, pocket pc and console applications. Where the user could select language of choice for their implementation/project. That was also the whole idea behind LINQ (Language Integrated Query) to be able to write the same code across XML, SQL and Objects. LINQ was implemented using Monads, but that doesn't really matter for the consumer of
LINQ.
Monads taken from functional programming is one of the keys to manage complexity.
Information hiding is also a key concept in
OOP practices. It also aids in managing software complexity. When you start using Gaia in your projects you know there will be a single source of errors related to browsers. If the window modality doesn't work as expected in IE7, that's not relevant to your business logic, but it's a problem that can be found in the UI library. It's the UI library's topmost concern to deal with the lower level stuff.
The Gaia Window is a wonderful example of hiding complexity and it's modular structure. The following code adds a Modal Window to the Page with all the functionality of a modern DOM Window.
'Visual Basic.NET Code
Dim win as new Window
win.ID = "window"
win.Width = new Unit(400)
win.Height = new Unit(400)
win.Closeable = true
win.Resizable = true
win.Aspects.Add(new AspectModal())
Form.Controls.Add(win)
Can't be easier than that, right?
Also because everything is managed code, you can even abstract away the UI builders in separate projects. For example
' Visual Basic.NET Code
Form.Controls.Add(ControlFactory.CreateWindow(_
"window", 400, 400, true, true, true))
And you've effectivly reduced lines of code by a factor of 7/8. This reminds of a famous quote from the classical piece, The Mythical Man Month by Fred Brooks. Here freely paraphrased:
"Writing the code is only a fraction of the job. Approx 1/6. Raw thinking accounts for most of it."
#Follow the standards, Luke
If you submit to the standards you will do well. It took us quite some time to get here, but step by step we are starting to enjoy the benefits of software standards. If you decide to build your foundation on the trust of proprietary code (ie. ActiveX technology for web) you will quickly find yourself at the mercy of others. We've written extensively about this topic before here [Ajax is Dead] and the importance of adhering to open innovation. Here's a few examples
-
When Google Chrome came out, we knew Gaia would automatically work with it. Because of standards.
-
If your email client is built using open standards, you can use any computer in the world wired to open it.
-
Open standards live in the Public Domain and offers guidelines for software vendors. Imagine integration with a Web Service without the WSDL?
List of examples could continue ...
Gaia is built all the way using open standards. All output is 100% xhtml compatible. It runs on Mono and with a Linux installation you can have a server environment with access to source code all the way down to the sillicon. For clients, all they need is a browser. Either IE, FF, Safari, Chrome or Opera will do. Now, that's fantastic!
Conclusion
The list of principles and patterns presented here is by no means exhaustive and we will touch more principles in other blog posts about this highly interessting domain in the future. We will also drill deeper in the Gaia Ajax architecture itself for gems of importance and their relation to design patterns and GRASP principles. Writing software libraries is not easy and without a set of guidelines and tenets to follow it gets even harder. We believe Gaia Ajax is a manifestation of many of the ideas we've presented here and we hope you will download the bits and start playing around with it. Once you start to appreciate the conceptual framework, we believe you will never again reduce yourself and your position to a dull presence as a property setter on huge component libraries. Instead reclaim your job as a professional OO programmer and welcome the new brave world.