Saturday, December 1, 2012

Software Architecture and Ease of Implementation

A complicated software system can be designed in many different ways. Even though there may be many design choices that will lead to the same system feature set, the same user interface, and even the same quality, these designs may require very different amounts of development effort. In other words, the cost of implementing these designs in terms of time and money can vary quite substantially.

This claim itself is not very hard to understand. The million dollar question is: how do you design a system so that it can be implemented quickly, easily, reliably, and completely?

Again, at the top level, this is not a very hard question. Some answers would come to mind right away: the KISS principle, canonical forms that can be reused, advanced algorithms that cut down complexity, utilization of existing solutions, etc.

There may not be an exhaustive list of answers to this question. Here, I would like to start with one of the most important: designing the system with your development team in mind. If the design cannot be carried out by your development team quickly and reliably, it is not a practical design, and it is not a good design. Ease of implementation of a design does not mean it is easy for your architect to carry out the design work or how easy it would be if your architect were to write the code; it is supposed to be easy for your development team.

What is taking so long?

Let us start with a basic "CRUD system" that performs the basic operations of "create(C)", "retrieve(R)", "update(U)", and "delete(D)" on a data object with a dozen various attributes from a database:

Figure 1 Basic 3-Tier System
If you ask a programmer on your development team to implement such a basic system with Microsoft MVC .NET or ASP .NET using EDM from scratch, he should be able to complete it in no more than 10 minutes. If you ask the star programmer on your development team, it would be even quicker. Even if you demand detailed data validations on all attributes with localization, it would still take no more than half an hour.

Of course, in practice, a system is never this simple. For security and scalability, additional tiers are needed:

Figure 2 Distributed Multi-tier System
Here, the part of the system that is responsible for binding the view to the data object, namely the website or the presentation tier, is separated from the rest of the system by a remote access connection to the service tier. This separation provides mainly the following benefits:
  1. A compromised website will not expose the data tier directly to the intruder.
  2. Multiple websites and multiple service servers can be load balanced.
The connection between the service tier and the data tier is abstracted so that it can be either local or remote, depending on the data source. This separation provides mainly the following benefits:
  1. Data format complexity is hidden from the service tier. Complete different data sources can be used the same way.
  2. Multiple database shards can be used for load distribution.
After this seemingly simple change, if you ask a programmer on your development team to implement the same "CRUD" operation again, the time it takes will increase from half an hour to two weeks or even longer!

Unfortunately, this separation of responsibilities is not the end of real world design escalation. In many cases, more complicated delegates instead of functions are needed to further increase system flexibility. The system described in Figure 2 will change like a chameleon depending on the object that is being operated on. Now if you ask a programmer on your development team to implement the same "CRUD" operation again, the time it takes will increase to half a year or more, or perhaps never!

Can we keep it simple?

It is the architect's responsibility to stay with design patterns that a programmer on your team can understand. In Figure 1, binding an EDM entity to an HTML control is something that every programmer can easily do with Visual Studio scaffolding. Can we handle the data binding in Figure 2 the same way, and get it done with the same speed?

The answer is yes, of course. A good example is Microsoft RIA service. It hides the complexities of remote object handling in WCF, and exposes a programming interface to the object in question that can be treated exactly like it is local. If the architect can design the system this way for each implementation task, your implementation speed will increase tremendously.

A service like Microsoft RIA not just takes programmers back to a familiar pattern. It provides many other benefits:
  1. A canonical form requires virtually no programmer training.
  2. It is much less error prone.
  3. It provides data validation and presentation localization features that could otherwise be challenging to your programmers.
The list can go on further. But we can sum it up by saying that a pattern that is familiar to your programmers will allow them to get their jobs done quickly, easily, reliably, and completely.

Some may argue that Microsoft RIA service is only one example. There must be other cases where this example does not apply, right?

It is a devil's staircase

With a devil's staircase, if you put a small section of it under a microscope, you will find that it looks just like section that you were looking at earlier without the microscope. With the stretched version of the "CRUD" system in Figure 2, if you zoom into a small section of it, you will still find patterns like the one in Figure 1:

Figure 3 3-Tier Input/Output Pattern
These simple patterns can easily be implemented by programmers on your team. If we design with these simple patterns to build bigger simple patterns at the next level, the entire system will be implemented quickly, easily, and reliably.

Over design/Under design

Microsoft RIA is a great service. It should serve as an example for architects who are trying to implement systems depicted in Figure 2. However, it does not solve the problem of over design or under design. Because software architecture is a devil's staircase, its complexity can grow exponentially. By following the simple 3-tier input/output pattern, one can easily see this exponential growth in action. An over designed system will become impossible to complete mathematically. At that point, a copy-paste solution that spread linearly might seem wasteful, but it will be the only sensible thing to do: your programmers cannot even count 4 billion patterns before your deadline if your patterns are 32 levels deep. A number 32 may seem small until you put in the exponent!

Microsoft RIA would have been a perfect service if it were implemented for a single class of software applications. However, using it without EDM is extremely difficult. So it is under designed as a general purpose service. In the past I have developed a system that allows you to access data RIA service even if the data is not from an EDM data source. It is used in the Online Business Pro software system that I developed.


No comments:

Post a Comment