caines.ca/blog Shell-Shocked Ramblings from the Trenches of Software Development

14Jan/100

The Difficulty of Changing to a Focus on Quality

One thing that TDD's advocates and opponents can agree on is that the concept is hard to introduce to new people.  There are lot of pain points to unit-testing that lead to it being difficult to get buy-in for, in the minds of managers and developers alike.

How we got here

Product owners and stake holders have a fixed set of features that they need implemented, and so management then has the choice to put a focus on either quality or speed-of-delivery.  Historically that focus has overwhelmingly been on speed-of-delivery, and so the deadline dictates how much quality a team has time for.  Very few programmers have never worked within the confines of a deadline.

Deadlines have little to no regard for quality.  Quality is sacrificed at the altar of the deadline in order to deliver the necessary features at each stage as fast as possible.  Few people involved in the decision-making process are unaware of the sacrifice that they're making, but it's a trade-off that is often considered acceptable anyway.

In general, management that makes that choice for speed-of-delivery over and over again is unaware of the various studies of the effect of quality in the long run.  The basic principle they're missing is that software that has fewer defects is easier to maintain, so its continued development is much faster than software with more defects.  So quality leads to higher speed-of-delivery in the long run .  To choose speed-of-delivery over and over again instead of focusing on quality is like playing a chess match and considering only one move ahead.  But this is not a natural or intuitive concept to grasp!  Management and developers alike understandably question how we can possibly be faster over the long term by spending so much time on quality.

So that's the way it is in many software development shops, and that's the way it always has been.  Developers, being the clever bunch that they are, optimize their workflows and tools to deliver software as rapidly as possible.  The desire for faster speed-of-delivery at the expense of all else has been culturally ingrained in the brain of every developer I've ever met.

Understanding How Deep the Problem Is

It makes sense then that people are not ready to shift the focus to being quality-centric.  Not only is the justification non-intuitive, but they're simply not equipped in any way to meet quality requirements.  They lack the tools, the training, and the experience.  It's even been found that given a task with *no deadline*, developers will tend to invent their own deadline, just because that's how they're comfortable working.  It's simply not enough for management to direct the team to be quality-focused.  The change in focus to quality-centric goals should be expected to be just as difficult a transition as many developers had transitioning from procedural to object-oriented programming (if not more).  We're talking about undoing a lifetime of work habits and learning completely new ones.

The New Toolset / Mindset

The primary solution we've got for really being able to work with a quality mindset is TDD.  It comes with a bunch of standard tools (unit-testing frameworks, mocking libraries, code coverage analysis tools, inversion of control containers, etc.) and a bunch of clear cut rules on how to measure and achieve an acceptable level of quality.  And TDD has really proven itself to those that have made the transition:  IMVU and flickr, for instance, can deploy new code to their customers many times in a single day because they can rely on the quality brought to them by TDD.

But developers that are new to the concepts don't have that experience of success, and they don't know any of the tools, and they don't have a clear picture of how to achieve their quality goals.  These factors contribute to the steep learning curve of TDD and the quality mindset in general.

The Biggest Obstacle of All

The biggest obstacle of all is that there's a chicken/egg scenario where developers are naturally trying to learn about unit-testing by writing tests for their existing codebase, and it just so happens that existing code is the hardest kind of code to write tests for.  They're simply not ready for the work at that level of difficulty.

There are roughly a dozen stages that any new developer needs to go through in order to be able to work on a team that's doing TDD:

Stages of Unit-testing Consciousness:

  1. run existing tests
  2. maintain existing tests
  3. understand the importance of code coverage
  4. write new tests for code that is written by someone else who understands testability
  5. understand the problems of dependencies and what constitutes testability
  6. write code and tests for scenarios with no heavy dependencies
  7. understand the role of mocking / faking
  8. write code and tests for scenarios with heavy dependencies by mocking / faking
  9. understand the limitations of coverage analysis
  10. understand the value of writing tests before code
  11. refactor legacy code to be testable in ways that aren't necessarily safe
  12. refactor legacy code to be testable in ways that are safe

Each of these steps requires new skills, new tools, new concepts, and new psychological buy-in.  To expect a developer to be able to write tests for his existing codebase as a first step, is to expect a developer to skip all the way to stage 12.  It's simply not realistic.

Quality is REALLY Slow in the Short Term

Even if a developer knows the methodology and toolset inside-out, there's a shocking realization that in the short-term, quality really slows down the development process.  The SQLite project for instance boasts over 600 times the lines of code in their tests than in the product itself .  For a TDD-neophyte, this looks like an unrealistic and wasteful amount of work, but the SQLite developers know exactly how quickly and easily they will be able to make future changes and still maintain quality.  That's an understanding that can only come through experience though.

It's Faster to do a Manual Test than to Write an Automated Test

While absolutely true, this is another product of the short-term thinking mindset that developers have had hammered into their minds for decades.  Obviously if a manual test takes 1 minute to run and a similar automated test takes an hour to write, there's a specific number of iterations after which the the automated test is time well spent (60 iterations to be precise!).  In a normal development day it's common for me to run my automated tests 10 times per hour or more, so I recoup my upfront test-writing time very quickly.  Again, it's difficult to see this, or even see why I'd even want to run my tests so often unless you've had the experience.

The First Step is Admitting We Have a Problem

There's a deep cultural change that needs to happen in a person to make them understand, and it's not a quick or simple process by any means.  There are real impediments to switching our course towards quality that we need to first recognize so that we can overcome them.  A quality focus is such a huge shift in paradigm that we can't expect our teammates to simply buy right into the concepts that help us achieve quality, or even the rationale.  Once we've admitted that we have a problem, we can start to talk about ways to most effectively convince our teammates about the value of the focus on quality and the value of TDD in achieving the goals of that focus (I'll talk about those in the next post).