Excessive use of technology results in sub-optimal solutions


When designing a system there is always the temptation to use the latest and greatest technologies. This is based on the (generally true) premise that new technologies are superior to older technologies. The implicit reasoning from here is that using a more advanced technology will result in a better solution. In practice however this does not always hold.

As an example I recently purchased a second 24 inch monitor for my home system. I selected a Samsung 2493HM because it was the size and resolution I wanted and had decent reviews. One element of the reviews I do wish I'd paid more attention to was in reference to the monitor controls. My existing Dell 2407WFP uses (as do most monitors) a number of buttons on the front bezel to control the monitor. These buttons are simple and effective. The button isn't exactly cutting edge technology but they happen to work fairly well.

Samsung however have decided that buttons, being functional, have no place in the design of their monitor. They've replaced them with touch sensitive controls on the bezel in the same place where the Dell has buttons. They've decided that the more advanced touch sensitive technology is an improvement because it results in a cleaner design. Unfortunately they're completely wrong about this.

Physical buttons are more visible true, but it turns out in practice that this is a good thing. A physical button has a defined boundary that makes it obvious what is a control and what is not. The touch sensitive controls do not. Worse, Samsung have marked them using symbols that are extremely difficult to read in most lighting. As such actually finding the controls is annoying.

Touch controls are also inferior in their tactile response. A physical button gives feedback when pressed, the touch controls do not. You must also lift your finger entirely off a touch control to press it again or avoid it assuming another keypress. These factors combine such that the experience of actually using the touch controls is extremely frustrating. It's even more annoying when a side by side comparison of the look of the two monitors has me giving the styling win to the Dell, as they've foisted barely functional controls on me without actually achieving their goal.

The lesson from this is that what is on a technical level a more advanced technology can in context be an inferior solution overall. In this case the drawbacks of the new technology (ill-defined controls, lack of tactile response) were ignored over perceived benefits (lower design profile). However the selection of a new technology may also be invalid due to integration costs, general availability, differences in reliability and integration and consistency issues with existing technologies. Failure to adequately justify that the benefits of the new technology outweigh the true costs of adopting it is unfortunately common but no more appropriate for this.

You could also take away the lesson that selecting technology on appearance alone can have a significantly negative experience on the function (which is the entire point of a system in the first place) which is something I may expand on in a later post.

author: Colin David Scott | posted @ Friday, July 18, 2008 2:05 PM | Feedback (0)

Constant Consistency is Detrimental


Consistency is a desirable property in a codebase due to the benefits in understandability and maintainability it provides. Application architecture assists here by providing a common template to which the system is constructed. Therefore the design of the architecture should be done in such a way that consistency may be effectively achieved. This does not mean that the benefits of consistency should imply that consistency must be enforced universally and in all cases. There are a number of cases where managed inconsistency brings greater benefit to the system.

Some systems will have highly disparate elements where there is no single architecture that will optimally address all the requirements. Indeed it may be that the optimal architecture* for the majority of the system will not allow some of the requirements to be met. If absolute consistency is mandated then a solution that is less effective (in terms of maintainability, flexibility, performance and other relevant criteria) may need to be selected to meet all the requirements. Where the requirements driving this choice represent a relatively small subset of the overall requirements we get a situation where a relatively large cost is imposed on all requirements to meet the needs of a few. The costs of such overhead can easily exceed the costs of having an exception to the standard application architecture to handle the special cases.

What is desirable here is having a manageable (preferably low single digit) number of designs for the different elements. This allows elements of the system to be non-standard in a standardised fashion. Although a greater cognitive overhead than having a single universal design this does not represent a huge or unmanageable set of complexities and the benefits to the implementation of the system generally outweigh these costs.

The other primary instance where inconsistency may be beneficial is when an improvement to the architecture is identified. Generally it is not justifiable to apply such an improvement to the entire system at once as this will provide little immediate benefit and caries significant risks and costs. In these cases a staged rollout of the improvements is preferable. New code and that which is being modified can have the new design applied, whereas code that is relatively stable can be left alone.

I've experienced cases where an argument is made that improvements to the design should not be performed because it would make the system inconsistent (these arguments have prompted this post). This argument is not always invalid. There are certainly cases where the scope of a change makes it inappropriate, such as when stabilising a system in preparation for a release. In general development outside these cases I don't feel this to be a compelling argument. It is essentially arguing that the system may never be improved simply because the improvement would not be applied immediately across the entire system.

What is required when applying a design change in this fashion is some management of the changes. Failure to do so will lead to a case where the system is scattered with multiple "improved" designs across its components and the corresponding problems with maintenance this can cause. This may involve such activities as periodically applying design improvements to all or parts of the code that have not otherwise been upgraded in order to improve the system consistency.

In summary:

  • Consistency is generally a good thing, but it is not the only thing
  • Inconsistency may be supported and beneficial where it is properly justified and managed
  • The alternatives to allowing inconsistency are often stagnation or a poorly fit design both of which can be very costly over the life of the system

* Optimal here being what the architect(s) consider to be the best architecture they may develop with their available resources rather than a measure against some mythical arbitrary scale of ideal architectures.

author: Colin David Scott | posted @ Wednesday, July 16, 2008 12:10 PM | Feedback (0)

Today in Technical Difficulties


My blog is currently experiencing some technical difficulties. This may be a combination of code, configuration or hosting. I'll be looking at it this weekend. Until then all 3 of my readers will just need to bear with me.

In further failure news Telstra have managed to deliver the replacement handset to the wrong address, so I won't have it until tomorrow. This is after I specifically gave them the correct address. Brilliant. The delivery company (who just deliver where they're told) are the only consistently competent people I've dealt with so far. So kudos to Startrack Express and various bad words directed to Telstra.

author: Colin David Scott | posted @ Thursday, June 26, 2008 9:53 AM | Feedback (0)

New Adventures in Telecommunications


I recently got an i-mate Ultimate 9502 which I'm on the whole reasonably happy with. Its got a large form factor but that works for me. The screen is excellent, although the video performance isn't brilliant. It doesn't have the same one handed usability my SP5 did but that's to be expected given the additional capabilities and the compromises to phone functionality that entails.

Unfortunately its developed a problem. I used the included headset and now it won't work without it. It'll still ring but no other sounds will come from the inbuilt speakers. Kind of a problem. I've tried hard and soft reboots and leaving it with the battery out. No joy. So tomorrow I'm going to have to call Telstra to try to get this resolved.

I wouldn't be so reluctant to do so if my experience in getting the phone delivered and set up hadn't been so painful. I never did get a confirmation email from the Telstra online store. I rang the number listed on their website but the people there were unable to help. They were very nice, just useless. I tried them again when I got the phone and wanted to set it up to use. Same people, still nice, still useless. They alleged to have contacted the people who could make it all work, but nothing came of that. I finally came across a different number listed elsewhere on their website and those people were able to help fairly quickly. Why Telstra feels the need to have a department of nice but useless people answering phones I'm not quite sure. Surely allowing them to actually do things would be more cost effective.

author: Colin David Scott | posted @ Sunday, June 22, 2008 6:18 PM | Feedback (2)

When Anti-Patterns Collaborate


In my previous discussion of patterns I touched on one of the most frequent anti-patterns; overuse of Singletons. Today I'm going to elaborate with an example of what happens when you use multiple anti-patterns together. As always details not relevant to the example have been changed to protect the guilty.

The application in question was an existing code base which I was brought in to assist with. The system suffered badly from Singletonitis. Many of the items configured as Singletons had no state and had no business being Singletons at all. In particular the data access layer was invoked via a Singleton which was also set up as a Facade.

The Gang of Four describe the intent of Facade as to "Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use." That was not the case here. This particular Facade exposed every method on every database repository class. As such it possessed hundreds of methods, many of which had names starting with common term like "Get". It therefore actually increased the complexity of the data access interface by exposing a large number of low level data access methods on a single interface with low cohesion.

In addition the Facade class performed a variety of support logic required by the repository classes, including managing transactions and database connections. This was done using cut and paste, resulting in the same code being duplicated a few hundred times within a single class. This of course had slight variances in places as changes were made in specific instances but not propagated to all instances.

The way this class was used and implemented indicates that it's an anti-pattern. It did provide a unified interface to the subsystem, but what it failed to do was make that subsystem easier to use. Additionally the massively duplicate code certainly didn't help when errors in it were discovered.

I can only speculate as to the cause of this design, but I have what I believe to be a reasonable hypothesis as to the cause. This includes:

  • An incorrect belief that the data access code must be accessed via a Singleton. Objects without state are very cheap to instantiate in .NET. Even if they weren't better mechanisms (such as Dependency Injection) exist to support this requirement.
  • As it was believed that a Singleton was needed, an unnecessary incentive to consolidate all the data access methods onto a single interface. Use of the more fine grained repository interfaces would have been a substantial improvement in this case due to improved cohesion and simpler interfaces.
  • The Facade (or pseudo-Facade) implementation contained enormous duplication. I can only presume that the developers didn't consider this a significant problem or know how to fix it if they did.

This hypothesis, if correct, shows a cascading problem where the incorrect usage of Singletons incentivises further poor design decisions. Failing to consider the trade-offs of the patterns under consideration has imposed costs on all code that must relate to them. Combined these problems had a number of negative impacts on the code base:

  • Use of Singletons destroyed testability as testing units in isolation was difficult to impossible.
  • Working with the large repository Facade was difficult due to the sheer number of data access methods.
  • The duplicate behaviour in the Facade required significant effort to maintain when issues with it were discovered.

None of these things are blockers than will prevent the software being developed. Yet they impact on the overall quality and maintainability of the system. Over time these are essential factors in ensuring the success of a software system. Professional developers have a responsibility to be concerned with long term consequences, hopefully for reasons other than concern they'll be stuck with the consequences. They therefore have a responsibility to apply patterns correctly and with a full and proper understanding of the trade-offs involved.

author: Colin David Scott | posted @ Sunday, June 22, 2008 5:14 PM | Feedback (0)

How to organise a DDOS on yourself


Step 1: Produce a new version of Firefox

Step 2: Try and break a world record for number of downloads in 24 hours

Congratulations to Mozilla who appear to have organised to have themselves nuked off the Interblag by millions of geeks wanting the latest shiny thing. I'd mock, but I'm one of them. Mmmm.... Shiny....

author: Colin David Scott | posted @ Wednesday, June 18, 2008 1:10 AM | Feedback (0)

Intermittent unit tests are worse than no unit tests at all


I'm a big proponent of unit tests and Test Driven Design (TDD). Unfortunately something I see relatively often is developers who don't understand that the quality of the unit tests themselves is important. In this post I'm focusing on a particular area of concern: unit tests that will intermittently fail for reasons not due to errors in the code under test.

Failures of this kind are generally due to two causes. Firstly an external resource that the test depends on is unavailable or not in the expected state. This can be dealt with but the effort required to do so can be excessive and make testing difficult and expensive. The external resource may be another unit test, where the order the tests are run in can adversely affect the success of the test run. This causes test fragility and is to be avoided.

Secondly unit tests may fail due to timing issues. This can occur when operations are time sensitive. Such a test is subject to timing conditions beyond its control such as when the operating system schedules its thread to run. I've seen tests with Sleep() statements intended to ensure the timing of the test is valid. This is a fragile and unreliable hack that does not address the underlying problems that cause test failure. This kind of attempt to play with the timing of operations is a sign that the design of your code is inadequate, properly factored code should allow the time sensitive elements to be appropriately controlled or mock to allow reliable testing.

The net outcome of unreliable tests is that they provide negative value. When the test fails you have two choices. Investigate to see if there is an actual bug or ignore the failure. Investigation, even if it's running the test again, is time consuming, especially if the test happens to fail multiple times. Ignoring the test means that it might as well not be there. Indeed this would be preferable as its presence suggests that there is testing where in practice there is not. This false confidence runs the risk of introducing errors that may not be detected.

I've been burnt by test runs that required complex setup and specific ordering to be effective. Doing this damages the value of testing and tends to lead to team members ignoring the unit tests. This is not TDD. Accept no substitutes, demand unit tests that pass consistently and independently.

author: Colin David Scott | posted @ Monday, June 16, 2008 12:18 PM | Feedback (0)

Switched to SubText


After getting some reports of issues with dasBlog I've moved across to SubText which so far seems nifty. The binary version didn't work for me so I built it from source but had an otherwise trouble free install. This tool exported all the content from dasBlog except the images (which I solved by just leaving the images where they were). I also found this post from Ayende helpful in getting the post ordering sorted.

In theory I've tweaked things so that the URLs should be the same for older posts. The RSS link has changed but Feedburner should mean that's not an issue for most people.

author: Colin David Scott | posted @ Sunday, June 15, 2008 5:29 PM | Feedback (0)

Signs that Visual Studio 2008 underwent more testing than 2005


A few random items that indicate that Visual Studio 2008 had a release checklist more vigorous than "It Builds! Ship It!":

  • Docked windows actually auto hide correctly.
  • Code coverage excludes code that Visual Studio itself has generated.
  • I'm yet to scream abuse at it for a solid 5 minutes.
  • I'm no longer contemplating a shift to Java.

author: Colin David Scott | posted @ Tuesday, June 10, 2008 4:33 PM | Feedback (0)

Every developer should have a whiteboard


I got myself a whiteboard over the weekend. Due to a lack of available wallspace it's now "installed" by resting it on a wooden frame I happened to have lying about and using Scotch tape to fix it to a cabinet. I'm not good with physical objects...

Nevertheless there are some design problems that are best solved by scribbling transient crap on a whiteboard. They exist as a tribute to all the weird and improbably ideas you can have while searching for a solution that works. Recommended.

Just get one with a stand if you can...

author:  | posted @ Tuesday, June 10, 2008 2:31 PM | Feedback (0)