Over the past six months or so, there has been a fair amount of negative commentary about automated acceptance / integration / system testing. The thrust of this commentary is that testing at this level tends to be brittle, slow and have a high maintenance overhead. None of this needs to be true, but producing a robust suite of tests requires an uncommon adherence to good practice.
Archive for the ‘Software Process’ Category
Large Systems
Many times over the years we have encountered an attitude towards code cleanliness that is summed up in the assertion that as systems grow in size, code quality will necessarily degrade. Often the argument is backed by references to ‘programming in the large’ as opposed to ‘programming in the small’. We have consistently found these assertions to be unfounded and this article is an attempt to explain why.
Producing Systems that Do Not Rot
I was driven to write this article after reading Kirk Knoernschild’s blog about Rotting Design and felt I needed to say something.
There Is Only One Codebase
Software Quality – Pragmatics
This article continues my series on Software Quality. My thesis is that we judge quality using the same inbuilt sense of aesthetics as we would a work of art or an everyday object, albeit at quite a high level of abstraction.
The design industry has a lot to say about this kind of thing and no one more so than Massimo Vignelli, who summarised his core ideas in The Vignelli Canon. I am following each part of the Canon, this part being Pragmatics.
Whatever we do, if not understood, fails to communicate and is wasted effort. – Vignelli
No matter how cleverly we design something, if it is not understood then that design has failed. Software is complex and some decisions will need explanation, but if the design is still not understood then the effort in producing it is wasted.
Complicated, confused designs are very common in our industry. They are often the result of confusion in the minds of their developers, analysts and users. A confused mind will produce a confused product. These projects usually limp along before collapsing, mercifully, under their own weight, but not after many years of very expensive and wasted effort.
We should be careful not to confuse a complex solution with an accidentally complicated one. Some systems are unavoidably complex and what we expect to find there, as in all systems, is a set of core principles that underpin the whole edifice. Without clear, strong and forceful decisions that provide structure to systems, there will be no clarity and plenty of confusion. This is not to say that those decisions are carved in stone. Constantly changing environments and requirements are a fact of life in software and so those decisions will need to be revisited and reworked. However, it is much easier to move from one set of clear and strong design decisions to another, than it is to rework a confused system.
Having clear, strong and forceful decisions is the only pragmatic choice we can make. Allowing ambiguity and confusion is not pragmatic, it is simply sloppy and is the easy way out in the short term.
Vignelli sums it beautifully:
• We like Design to be forceful
• We do not like limpy Design
• We like Design to be intellectually elegant – that means elegance of the mind, not one of manners, elegance that is the opposite of vulgarity
• We like Design to be beyond fashionable modes and temporary fads
• We like Design to be as timeless as possible
• We despise the culture of obsolescence
• We feel the moral imperative of designing things that will last for a long time
This is pragmatism in any field, and no more so than in software.
TDD from a Control Theory Point of View
Before becoming a developer, I was an academic at University College London. We built the world’s first homodyne and heterodyne phase locked loop with semiconductor lasers for oscillators instead of electronic oscillators. Sounds easy, right? But the problem is that because lasers oscillate at high frequencies (it’s light after all), a delay of a few hundred picoseconds around the feedback loop is significant and results in the system becoming unstable.
Indeed, any system with feedback can become unstable if the delay around the loop is significant. There are things that one can do to prevent instability but the best thing to do is remove the delay if possible.
In software, there are many feedback loops. When you write code, often the first feedback you get is whether it compiles or not. Can you imagine the pain if that wasn’t the case? Waiting a few weeks to find out whether the code actually compiled would be ridiculous. Right?
Fortunately, most software developers have a go at making sure their software actually compiles. Some don’t, but thats a different article.
Testing is another feedback mechanism. So how is it sane to wait months before finding out that your code actually works? It isn’t, thats crazy talk. TDD helps in a number of ways: it helps you to think about what your code will do before you think about how it will do it; it provides a safety-net for all those refactorings you will need to do; and it tells you that the code you thought you wrote is what you actually wrote.
The instant feedback obtained by TDD is a stabilising mechanism to ensure that what is written is correct and that you haven’t broken anything else inadvertently because all that other code in the system is also tested.
But what is meant by stability in this context?
The main instability is the code – wait – test – fix – repeat cycle. During the wait and test phases, new code is being built on top of the broken code, and the fixes themselves often introduce new defects. This results in increasingly painful fix phases. What is worse is that there may be many overlapping loops like this which is utterly chaotic!
This chaotic process results in developers working in a panicked, crisis mode which leaves no time for refactoring, reflection about improving the codebase, or writing tests. It’s very demoralising as the deterioration in the codebase cannot be stopped.
The end result is a brittle, sprawling mess of a system that is now not in any state to be tested or repaired without heroic effort from the developers, and buy in from business stakeholders. And we know how that story ends…
Different Interpretations
As a retrospective facilitator I frequently see different parts of a team presenting different perceptions of the same event. In fact, this underlies a great many of the problems seen in teams.
Demand Quality: You Get What You Ask For
“In the long run, men hit only what they aim at. Therefore, though they should fail immediately, they had better aim at something high.” – Henry David Thoreau
This Business of Analysis – Domain Knowledge
Many people involved in software development understand their business domain – i.e. they have business or domain knowledge. This is, for the most part, a good thing, for it means that they can have reasonable confidence that they share syntax and semantics with other stakeholders.
However, there are two common issues related to domain knowledge that bear some discussion. The first is the assumption that if we have sufficient domain knowledge, then we understand the problem. The second is a failure to recognise that in almost every significant software development effort, there is more than one domain that needs to be understood.
(more…)
This Business of Analysis – The Problem
Analysis is usually a significant part of most software development efforts. As such, it would be reasonable to assume that analytical methods are well understood, even if analytical skills are not commonplace. However, there is often a great deal of tension between stakeholders that centers on the mechanisms and products of analysis, indicating that this assumption is not valid.
The reasons for this are many and varied, and I will explore them in this series of articles.