Ever wonder why good code is so hard to find? In his consistently brilliant xkcd.com, Randall Munroe explains the situation: Write fast and write junk. Write well and your software is obsolete before you’re done.
It’s Waterfall vs Agile, of course. And the debate, unsurprisingly, is more often tribal than rational — my team is better, which I can prove by pointing out the other team’s flaws.
And so, Waterfallers focus on the similarity between Agile’s touching faith in refactoring and UFOlogists’ certainty that civilizations capable of interstellar travel have no better way to communicate with us than to create a big circle in a corn field.
Meanwhile, Agilites concentrate on the number of web pages we’d have in production right now had the Web been produced through waterfall techniques (an estimated 6,427 total pages in total; IBM would be just about ready to put up its OS/2 support area).
Fun as it is, finding the sins of others does nothing to expiate our own, which brings us (more or less) to this week’s sermon — a response to subscriber Donna Bushard’s request that KJR talk a bit about Agile testing.
Here’s my first bit: I’m in favor of it.
In case you want more on the subject … in the old world of waterfall methodologies we recognized these levels of testing (or, better-because-it-sounds-a-lot-more-impressive, software quality assurance (SQA)):
- Software engineering (does my code adhere to the overall system architecture, is it properly structured, and does it adhere to coding style standards?)
- Unit (does my module do what it’s supposed to?)
- Integration (does my module interact properly with all the other modules the team is creating?)
- Regression (do our new modules break anything that’s already in production?)
- Stress (will the whole system perform well enough once everyone starts to bang on it?)
- User acceptance (are the new modules aesthetically pleasing? And, although it’s probably less important, do they do what the business needs them to do?)
The question: How does Agile change this? The answer: Agile doesn’t. There are, however, IT shops that think “Agile” means “Free-for-all,” and free-for-all development does change everyone’s thought process about SQA … namely, it eliminates the whole subject.
Agile is, as everyone ought to know by now, both a family of methodologies with two shared critical elements — iteration, and high levels of informal end-user involvement — and a religion, complete with sects, offshoots, and wars between adherents of the competing theologies.
The religious wars notwithstanding, one of Agile’s best features is that its high levels of informal end-user involvement make user acceptance testing something close to a non-event. When it happens, there will be nothing in the application end-users are seeing for the first time.
Iteration is where Agile gets into the most trouble from a software engineering perspective. The temptation to take structural shortcuts just this once can be overwhelming. That’s why code reviews are, if anything, more important with Agile than with waterfall projects. Except for eXtreme, of course, where code review happens while code is being written.
And in case the point isn’t clear, Agile projects require an overall architecture plan, just as waterfall projects do. Like most things Agile, the architecture plan should itself be iterative, with the high-level view developed up front and the rest happening as developers recognize when they are making design decisions that have architectural impact. For the other SQA steps:
Agile unit testing is little different from waterfall. Either way, developers can’t be relied on to unit test their own modules, because when developers have blind spots that result in defects, they bring those same blind spots into their unit tests.
What is a bit different is that as developers iterate they must keep track of how each iteration adds new test cases. Figuring them out later is a whole lot harder than jotting them down as they’re happening.
How you handle integration, regression, and stress testing depend on whether IT has invested the time, effort and infrastructure to develop an automated test suite. If so, take advantage of it and run it frequently … perhaps even nightly.
If not, make integration, regression, and stress testing waterfall tasks that take place at the end of each release cycle. And whatever you do, make them incompressible.
You might as well, because when it comes to testing there’s exactly one certainty: You always test, and you always test thoroughly. You don’t have a choice.
The choice you do have is whether you test before you put the software into production or after.
Before is better for your image.
One of the techniques for testing in Agile (by developers) is that you do “TDD” or Test Driven Design. (sometimes, test-driven-development). The point is that the whole code-test cycle is inverted, the test is written before the code, run the test, test fails, write the code to fulfill the test, run the test, test passes. Then write more tests, run the tests, write the code until the tests pass … rinse and repeat. The cycle is meant to be tight and *short* (on the order of a handful of minutes).
The tests thus built up therefore operate as the *specification* of the unit’s behaviour. It also forces the developer to concentrate on the outcome of the code (i.e. from the user’s – or using code’s – perspective) and not on the details of how it’s done until after what is to be done is specified. It always produces better code designs.
You can also do this for functional (acceptance) tests, e.g. the test team can develop automated, functional, test cases which specify the system behaviour *before* the development team writes the code for the particular story at hand. That’s part of the point of writing the acceptance criteria on the back of a user story. The acceptance criteria should briefly outline the major features of “acceptance”, i.e. completeness.
It strikes me that these two approaches are not mutually exclusive. I use both whenever I start a new project and advise any programmers I am supervising to do the same.
That is, before starting to code, do a deep analysis of what you are trying to accomplish. If you are under someone else’s direction as to the final product, treat there instructions as guidelines, hewing faithfully only to what the final product MUST do.
While coding, do it as rapidly as possible, depending on the API to root out most trivial errors (like typos). Though coding rapidly, try to adhere to good coding practices at all times. This should be a HABIT after only a couple years of experience.
The bottom line is that today’s computers are so fast, that compilers take only seconds to finish and leave detailed comments on errors. Iterations can be completed in minutes rather than hours, so you can depend heavily on iteration without losing any overall time. (Remember, I have been in this game since one had to program in MACHINE language, before there were any assemblers, compilers or interpreters. Guess which approach you had to use then.)
Finally, your comment that testing should NEVER be left completely to the programmers is spot on and essential to good code.
One non-quite-related comment. Big internet companies like Google or Facebook fiercely resist outside commentary. Being a good Samaritan, whenever I come across obvious flaws in coding, I try to get in touch with the company programmers to advise them what is wrong and how to quickly fix it. This turns out to be mostly futile. I get back “sniffy” letters stating…in “lawyerese”…various excuses for why they can not pay attention to “outsiders”. This is truly stupid, especially when the advice is given without request for any compensation ! ! !
One non-quite-related comment. Big internet companies like Google or Facebook fiercely resist outside commentary. Being a good Samaritan, whenever I come across obvious flaws in coding, I try to get in touch with the company programmers to advise them what is wrong and how to quickly fix it. This turns out to be mostly futile. I get back “sniffy” letters stating…in “lawyerese”…various excuses for why they can not pay attention to “outsiders”. This is truly stupid, especially when the advice is given without request for any compensation ! ! !
+1