(Riddle: “What is voiceless, yet cries and toothless, yet bites..” Read to the end to see the answer..)
Defintions:
- Agile – Software that adapts well to change (is well-designed and has comprehensive test coverage)
- Flat-Footed – Software that is NOT agile.
As I start work on my eighth Agile project, I felt it was time to take a breather and recap everything that I have learnt about Agile (the fact that this post just has 2 points to touch upon doesn’t speak wonders for my learning ability…however, living by the maxim that quality trumps quantity, I shall proceed…)
The whole idea behind Agile is based on the assumption that all customers are ‘fickle’ (for lack of a better word). This means that all requirements are subject to change (even the ones that are ‘locked down’). Not only can a customer change their mind (about anything) later, but the software must be tweaked/revamped as needed to accommodate the changed requirements. I remember a poster from college about ‘Rules that Women would like to share with men’…
The Rules
- The Woman always makes the Rules.
- The Rules are subject to change at any time without prior notification.
- No Man can possibly know all the Rules.
- If the Woman suspects the Man knows all the Rules, she must immediately change some or all of the Rules.
- The Woman is never wrong.
- The Woman can change her mind at any given point in time.
- The Man must never change his mind without express written consent from the Woman.
- The Woman has every right to be angry or upset at any time.
- The Man must remain calm at all times, unless the Woman wants him to be angry or upset.
Substituting ‘Customer’ for ‘Woman’ and ‘Developer’ for ‘Man’, here are the rules as applied to software development.
The Rules as applied to Software Development
- The Customer always makes the Rules.
- The Rules are subject to change at any time without prior notification.
- No Developer can possibly know all the Rules.
- If the Customer suspects the Developer knows all the Rules, he/she must immediately change some or all of the Rules.
- The Customer is never wrong.
- The Customer can change their mind at any given point in time.
- The Developer must never change his mind without express written consent from the Customer.
- The Customer has every right to be angry or upset at any time.
- The Developer must remain calm at all times, unless the Customer wants him to be angry or upset.
Ok – so the point of that little diversion was simply that the customer is always at liberty to change their mind (even for those projects where requirements are seemingly ‘locked down’ – such as fixed-bid type of projects). Agile’s whole purpose in life is to handle any and every curve ball that the customer can throw at the development team. In the pursuit of Agile, I find two areas where development teams get the intent of Agile all wrong.
The two agile tenets that I find most commonly misunderstood/abused are:
-
Agile Tenet 1: Only program the system to meet the current requirements
-
Agile Tenet 2: Write comprehensive Unit tests
Misinterpreted (flat-footed version of) Agile Tenet 1 – Only program the system to meet the current requirements.
Flat-Footed interpretation of Agile Tenet 1 : We can start coding anytime – even if some of the more critical requirements are not currently available.
Agile does not say that you should begin coding without requirements. Agile does not say that you should use the ‘start with current requirements’ as an excuse for not flushing out the important missing pieces up front. Agile’s intent here is simply to let you know that your system must be designed in a way to accommodate change. It is not saying that your system must be designed using an incomplete or inaccurate blueprint.
The simple example below may help illustrate this.
An Example: Building a simple contact form (web form):
Say you are tasked with building a simple contact form – just your everyday firstname, lastname, address fields, email etc. On the address fields, the customer is unsure about:
a) Whether they will allow a single ‘address’ for the customer or multiple addresses (e.g. Amazon.com)
b) Whether they allow a single contact per address (e.g. a typical consumer shopper) or multiple contacts per address (e.g. a business office location)
“Flat-footed approach” : Let us build they system assuming a single address only – and a single contact per address. If it changes down the road, we can accommodate that change.
Correct Interpretation of Agile Tenet 1
Answers to the specific requirements above (single address versus multiple addresses, single contact versus multiple contacts per address) can dictate the entire nature of the code. The UI layer, business layer as well as the data layer all depend on this simple decision.
In effect, the question is about whether the Contact—Address relationship is a 1 to 1 relationship (the simplest scenario) versus a 1 to many versus a many to many (the most complex scenario).
At the database level, intuitively, we understand that this is a big deal. It should come as no surprise then, that the domain (business entity) layer, which is an OO representation of the database schema, will be hugely impacted by this decision. The UI layer, of course, is the most damned by this decision since it not only has a dependency on the business objects layer but also has to worry about different types of controls to accommodate ‘multiple relationships’ as opposed to single 1-1 relationships.
Extrapolate that single contact form to multiple forms, tied to a large business layer tied to a data access layer tied to an entity layer which finally ties to the database, the change is no longer simple. It could (and usually does) mean days and days of rework and code changes.
The real question should be: ‘Why do we not have these important requirements upfront?’ Is ‘Agile’ being used as an excuse for ‘we’ll worry about it later?’
Summarizing Agile Tenet 1
- Start with as complete a set of requirements as you can get – especially when it comes to core features. Push the customer to provide these if they are not easily forthcoming.
- Agile (or any software development process for that matter) relies heavily on having as much information up front as possible. The only thing Agile does better than others is handle changes when they do happen (via the second Agile tenet – comprehensive unit tests).
Consequences of misinterpreting Agile Tenet 1
- This common misinterpretation of ‘Start with whatever you have right now’ typically leads to inflexible software design which is not well suited for changes down the road.
- This simple misinterpretation can add weeks (and thousands of dollars) to any development budget.
- It typically involves an entire revamp of one or more layers of the application every single time the customer changes her mind. Instead of being an Agile sprint, the process has turned into an expensive, flat-footed marathon.
Misinterpreted (flat-footed version of) Agile Tenet 2 – Comprehensive Unit Testing
This one is not so much ‘misinterpreted’ as it is ‘not practiced’! If I had a dollar for every time I heard..
“Oh yes – we do agile – but we just don’t have unit tests in there yet. We make it optional for developers and some of them haven’t gotten around to the unit tests. “
This is the exact anti-thesis of agile development! Holding daily scrums, doing pair programming and all of the rest can not make your software agile. Only unit tests can! When major feature changes are proposed, a non-unit testable codebase will need to be inspected for every conceivable breaking point manually. This is as nightmarish as software development can become. The larger the project, the scarier the nightmare.
Just having unit tests in place can avoid all these issues. How, you ask?
“In Agile, Unit Tests are the superhero that catches all the bad guys.”
Unit tests are what identify breaking points for you whenever you decide to change some code to accommodate feature changes. Unit tests are what let you handle a real curve ball requirement that could potentially wreak havoc on your codebase. Unit tests do not do this alone – but if combined with the following, they will greatly reduce chances of bugs making it beyond the developer’s box (i.e. bugs will be caught during development as opposed to QA or worse (the dreaded ‘Production Issue’). What distinguishes well-designed software from poorly designed software:
- A well designed object model
- A normalized, relational database model.
- A flexible business layer that allows for easy modification of underlying object types (using patterns such as Abstract Factory and Interface based design) and
- A comprehensive set of unit tests.
The last item (comprehensive unit tests) are also what distinguishes Agile software from ‘flat-footed’ software. If you were to leave out the first three and only have the last item (comprehensive test coverage), you would still have agile software. You may argue that what is the value of having ‘agile’ software that is not ‘well-designed’.
This leads us to the second redeeming quality of unit tests – they force you to refactor your code – so it becomes better designed.
Unit tests, by their very nature, force you to look at your code with a fine tooth comb. For example, if you approach writing a unit test for a ‘GetCustomerInfo’ method, you may realize that the method is trying to do too many thing (connect to a data source, fetch the data, assign the data to a business object etc.). Instead of doing all of that, you reason that it would be better to break that method into a few smaller methods – each of which does one specific thing. Already, you have refactored your code and made it better before you even wrote your first test!
Repeating this process leads to highly refactored code which can be read and understood easily by a new developer on the team. More importantly, during troubleshooting, it helps to quickly pin-point a problem down to a single, small ‘culprit’ method as opposed to a gigantic block of code.
Summarizing Agile Tenet 2 –Comprehensive Unit Tests
A comprehensive set of unit tests is the best insurance that code can buy. Agile teams start writing tests alongside code. Some managers argue that they have a team of testers ready to catch all bugs prior to launching the application into production. To them, my response would be:
An agile system catches various ‘breaking points’ for you. In lieu of unit tests, some of these ‘’breaking points’ may even make it to the production system, since it is often impossible for QA teams working under already stressful timelines to catch all of these.
Consequences of misinterpreting Agile Tenet 2
- Makes your code incapable of accommodating changes – making it a huge liability rather than an asset.
“A comprehensive set of unit tests is the best insurance that code can buy….”
Summarizing Agile Tenet 2 – Unit Tests
- I would rank unit testing advances as the single most important development in the software development industry in recent years (and I am including web services, cloud computing etc.).
- True – that in the 70s and 80s, people would write ‘drivers’ for their C code – which were essentially ‘tests’ – i.e. software testing software'. However, the sheer proliferation in languages, tools and libraries to facilitate unit testing in recent years takes unit testing to a new level.
- In addition, today’s OO software is far more layered requiring test suites at each layer (some of you might argue that the UI layer cannot be unit tested well. While that may have been true a few years back, in recent days, it is entirely possible to unit test UI layers (I blogged some time back about some nifty ways to unit test the UI layer.)
Summary
Imagine a home-owner who decides to remodel a room (say combine two rooms into a single room by breaking down the dividing wall).
A ‘flat-footed’ architect would say – ‘Sure - all I need to do is take the entire house down - and rebuild the entire house from scratch – where we should be able to easily build the new room.
In contrast, our ‘Agile’ architect would say – sure – all we need to do is to figure out what the effect of breaking down the dividing wall will be – then we address those issues while taking down the wall – so there are no unexpected consequences.
In my experience, these two flat-footed practices (starting coding with incomplete requirements and not writing tests for alongside code), are not only rampant, but are often found in pairs.
- Agile is here to stay. The real question is - “How is your team interpreting ‘Agile’?”. Just holding daily scrums and sprint planning meetings do not make a team Agile (see my related upcoming post on Scrummy Development versus Crummy Development)‘. The ultimate test of whether you have implemented Agile correctly is how long it takes you to make changes that are potentially ‘breaking changes?’.
- If you are going to do Agile, do it right. Simply holding daily scrums, doing pair programming etc. does not make a project agile. Making sure your code can easily and quickly handle the toughest requirement change thrown at it, is what distinguishes Agile software from flat-footed code.
Answer to the riddle posted as a teaser to this blog post - “What is voiceless, yet cries and toothless, yet bites..” – The Wind.