Software dev, tech, mind hacks and the occasional personal bit

Category: Design / Architecture

The Fallacy “Best of Breed” in Layered Solutions

Imagine you are designing a layered solution where data enters in a GUI, and passes through several layers for transformation and processing before being written to a database. Everyone knows that layering is a good way to do decomposition, right? It means you can work on each layer separately, without affecting any other layer? It means we can even hand off each layer to a separate person/group/company and different hardware to handle? This is all looking so good, now we can choose a “best of breed” solution for each layer. If each layer chooses the technology and implementation group that is the very best for that sort of work, it must lead to the very best solution overall, right?

Well, data needs to flow through all of the layers in this sort of design. Lets take an imaginary example. Say one layer in the middle has a data field length limit of 255 characters. This means that every layer is then limited to this data length, otherwise the data will be truncated or rejected on the way to/from storage. Instead of getting the advantages of each layer’s solution, you end up being limited to the lowest common denominator of all the layers.

A further problem is staffing and team structure. If each layer has chosen a very different “best of breed” technology, it will be difficult to find one team/company/group that can handle all of the layers (eg, Java front end, BizTalk middleware, Mainframe backend) and do vertical slices of functionality. Of course, you need the “best of breed” for the staffing! Hence, implementation is often split between different teams/companies (horizontal slicing of teams), each of which is known for skills in a particular layer. Although each team may be “best of breed”, we end up with the lowest common denominator again. Methodologies are likely to differ between teams (eg, waterfall vs agile) so the communication and planning is limited to the area of overlap between methodologies. The same applies for project goals. For example, one team may focus on user experience and another may focus on building an enterprise wide data model. It is only where/when these goals intersect that the project can progress efficiently.

What can we do to defuse this sort of architectural design in its infancy? Questions to ask:

  • How many times is the same data transformed, and does each transformation add value?
  • Can multiple layers be hosted in the same process rather than split between different machines/processes?
  • Integration is always time consuming. Do the “best of breed” advantages of a solution for a particular layer outweigh the cost of cross process or cross technology integration?
  • Can one co-located, multi-disciplinary team be formed to build the solution?
  • By comparison, how many people would be required, and how long would it take to build the application with the simplest architecture that could possibly work?

 

XML: When to attribute and when to element?

When defining an XML document, when are attributes most appropriate, and when are elements best? This is something that I’ve generally decided based more on intuition than a good set of rules.

Recently, at work, the need has arisen to define quite a few XML message payloads. I’ve also had the good fortune to work with Erik Doernenburg and we had a chat about attributes vs. elements. Largely thanks to Erik, here are some guidelines that could come in handy when making such a decision.

An attribute is best used to represent:

  • an id
  • metadata (eg, like rel and class in HTML)
  • a value from a small, closed set of values which interpreting programs rely on (eg, values that end up as application constants)

If none of the above apply, an element would likely be the best choice.

Green & Red Local Builds (adding colour to the local build process)

build.JPGWell, who doesn’t write tests and do continuous integration (CI) these days? Whether you use one of the many Cruise Control variants, or Team City or some other tool, you most likely get a handy colour coding of builds as either green or red (ie, good, or bad). But, you can take this a step further!

redbuild.JPGOften on .NET projects, we have a little batch file that we run before checking in (often with a pause at the end so it can be run from a shortcut), to confirm that no tests are broken locally. Well, it’s not much fun peering at the ugly Nant output (or whatever build system you use). Instead, it is quite easy to add a couple of lines to your batch file and change the colour of the console to bright Red or bright Green depending on the success of the local build. It is great for telling what the result was at a glance. I can’t claim credit the idea – it was something we used at EDI for our custom build system, but here’s some batch file code I whipped up which I can claim is all mine, every last GOTO of it! Enjoy 🙂

The following code uses NAnt, but you can replace it with MsBuild or any other build tool that returns a status code.

@echo off

color 07

tools\\nant\\NAnt.exe -buildfile:mybuild.build %*

IF ERRORLEVEL 1 goto RedBuild
IF ERRORLEVEL 0 goto GreenBuild

:RedBuild
color 4F
goto TheEnd

:GreenBuild
color 2F

:TheEnd
pause

AntiPattern: BusinessObjects in the driving seat

When you have a rich domain model with a business object centric design, and a Windows forms GUI, it can be very tempting to start putting significant process logic in the business objects. After continuing along this path a little further, you may realise that the process needs some sort of user input, and you use events or some sort of notifier pattern to gain user input required by the process, while still maintaining layering in terms of referencing. Then additionally you may need to access some sort of external service.

Here is an example:

class Order : BusinessObject
{
  public void SendOrder(INotifier notifier)
  {
    if (ReadyForDelivery ||
        notifier.Confirm("Are you sure you want to send order lines? They are not ready for delivery."))
    {
      OrderLine[] orders = GetLinesToSend();
      foreach(OrderLine line in Lines)
      {
        SendLine(line); // send line using a web service?
      }

      Notify("Lines sent successfully.");
    }
  }
}

interface INotifier
{
  void Notify(string msg);
  bool Confirm(string msg);
  OrderLine[] GetLinesToSend();
}

I would like to suggest that this is an anti-pattern and a trap. Although there is no direct reference from the Business Layer to the GUI layer (INotifier is implemented in GUI and passed down), the Business Layer now requires the ability to stay instantiated, pause while waiting for responses from the notifier, and then continue execution. This will work for rich client applications, but not in a stateless web environment. The ideal of being able to swap in/out the GUI layers on top of the Business layer is now compromised.

Instead, it would be possible to drive form the GUI layer, and call a service to send the Order Lines. In pseudo code below:

void SendMenu_Click(...)
{
  if (Order.ReadyForDelivery ||
      MessageBox.Show(...) == DialogResult.Yes)
  {
    using (ChooseLineForm chooseLineForm = new ChooseLineForm(Order))
    {
      chooseLineForm.ShowDialog()
    }
    SendingSevice.SendLines(chooseLineForm.selectedLines);
    ...
  }
}

If the logic in the GUI layer became much more complex, it may be a good idea to pull it out into its own class (eg, LineSender). This class would be a type of GUI level controller, responsible for orchestrating the send process.

Using this approach, there are a number of benefits:

  • BusinessObjects have no reliance on GUI implementation, so can be used for Rich Client and Web Client indiscriminately.
  • Web developers are free to implement the user input process in stateless way more appropriate to their platform.
  • Functionality for sending Order lines (some sort of integration with a web service?) is pulled out into a service class which can be reused elsewhere (potentially sending other types of objects?) and unclutters the Order business object and removes its dependency on an external service.
  • Code is simpler and easier to follow.

In Defense of Simplicity AND Complexity

Simplicity and complexity seem to have become hot topics for some of my favourite technical bloggers of late. These fine people have taken the view that things should be either simple or complex. Right, seems logical, these are opposites. However, I would like to suggest that in a well designed appliance which addresses a complex process, it should have both a simple AND a complex interface.

A couple of years ago, I bought a LG “Fuzzy Logic” washing machine. It has lots of buttons and settings on the front and one big button that says something like “Start”. 97% of the time, I throw in my washing, some detergent and press the big start button, and the washing machine works out all the settings, displays them and then starts. In the 3% of the time when I want to do something different (eg, just a rinse), I use the more complex part of the interface to change the ‘cycle’ settings.

Recently, I bought an IXUS 65. It’s a lovely digital camera, and it provides both a complex and a simple interface. As soon as I put in the battery, I was able to take pretty nice pictures by just clicking the big button on the top. No problem, I was very happy. Over the next few days, I glanced through the manual and fiddled with more complex settings for ISO, colour etc. However, in 95% of shots, I simply want to click the one big button that takes a nice auto-everything picture. It’s only occasionally that I want to change the settings to achieve a particular effect or to override a mistake in the auto settings.

To conclude, I think that my talented fellow bloggers are all right. People like complex interfaces and simple interfaces, just at different times, for different tasks. The best gadgets and appliances offer both.

Page 2 of 2

Powered by WordPress & Theme by Anders Norén