ABCs of Story Estimation


Estimation, predicting the future, is an art at best. Backing estimation techniques with extensive mathematics and statistics may make upper management happy--it's always great if you can provide supporting data for something and distill it to a single number! (42, of course.) But such diligence only serves to bestow way too much legitimacy on a bunch of HAGs (remember WAGs and SWAGs? Well, the "H" is for "Hairy").

Agile teams use dozens of various techniques for deriving story estimates. As my doctor once told me, so many "solutions" means that none of them is very good.


Predicting the future with estimates is immediately setting ourselves up for failure. When we estimate, we are always wrong. Always. It's just a matter of degree. But that's ok--we can get better over time, and the business always finds value in estimates. Repetition and increasing familiarity with things can dramatically improve the amount of error.

Best advice: Start simply! These five guidelines should help get you on your way.


  • All contributors estimate - not just a representative developer or team lead, and most certainly not anyone from the customer team simply asking for the story (how bizarre!). Those who do the work get to have some say in how large the story is. It doesn't make sense any other way.

  • Break story down into tasks to verify scope - This exercise can help verify whether or not this is the right story, and often brings out discussions around things that will impact the estimate. Sometimes a quick task breakdown gets the team to concede that this is a much larger story than thought.

  • Come to Consensus using planning poker - James Grenning's wideband delphi-based technique is a fun, engaging, and expeditious way of deriving a lot of estimates from a good-sized team. Show the cards, and if all are in agreement, or close to it, pick the size and move on. If there's disagreement, debate for a few minutes, try again. If there's still disagreement, come back later and move on to the next story for now.

  • Decrease estimation granularity as story size increases - It's silly to think that we can estimate anything precisely. As the story gets larger, beyond a couple days, even a day variance on an estimate is too fine. "Is this 6 days or 7 days?" Gee, let's do it and find out. The Fibonacci sequence is a classic choice for agile teams. A story that the team thinks is a 6 is most certainly not going to be done in 5 days, so it gets bumped up to 8.

  • Estimate using relative sizes, not calendar days - There will be no end of debate on this, but sizes do not degrade over time, and they do not vary depending on developer capability and availability. Calendar days do. Mike Cohn's book Agile Estimating and Planning provides many good additional insights on the differences between the two.

TDD Process Smells


This list of "process smells" focuses on execution of the practice of test-driven development (TDD)--not on what the individual tests look like. There are no doubt dozens of similar smells; following the rule of 7 (+/- 2), I've chosen the smells I see most frequently.
  • Using code coverage as a goal. If you practice test-driven development, you should be getting close to 100% coverage on new code without even looking at a coverage tool. Existing code, that's another story. How do we shape up a system with low coverage? Insisting solely on a coverage number can lead to a worse situation: Coverage comes up quickly by virtue of lots of poorly-factored tests; changes to the system break lots of tests simultaneously; some tests remain broken, destroying most of the real value in having an automated test suite.
  • No green bar in the last ~10 minutes. One of the more common mis-interpretations of TDD is around test size. The goal is to take the shortest step that will generate actionable feedback. Average cycle times of ten minutes or more suggest that you're not learning what it takes to incrementally grow a solution. If you do hit ten minutes, learn to stop, revert to the last green bar, and start over, taking smaller steps.
  • Not failing first. Observing negative feedback affirms that any assumptions you've made are correct. One of the best ways to waste time is skip getting red bars with each TDD cycle. I've encountered numerous cases where developers ran tests under a continual green bar, yet meanwhile their code was absolutely broken. Sometimes it's as dumb as running tests against the wrong thing in Eclipse.
  • Not spending comparable amounts of time on refactoring step. If you spend five minutes on writing production code, you should spend several minutes refactoring. Even if your changes are "perfect," take the opportunity to look at the periphery and clean up a couple other things.
  • Skipping something too easy (or too hard) to test. "That's just a simple getter, never mind." Or, "that's an extremely difficult algorithm, I have no idea how to test it, I'll just give up." Simple things often mask problems; maybe that's not just a "simple getter" but a flawed attempt at lazy initialization. And difficult code is often where most of the problems really are; what value is there in only testing the things that are easy to test? Changes are most costly in complex areas; we look for tests to clamp down on the system and help keep its maintenance costs reasonable.
  • Organizing tests around methods, not behavior. This is a rampant problem with developers first practicing TDD. They'll write a single testForSomeMethod, provide a bit of context, and assert something. Later they'll add to that same test code that represents calling someMethod with different data. Of course a comment will explain the new circumstance. This introduces risk of unintentional dependencies between the cases; it also makes things harder to understand and maintain.
  • Not writing the tests first! By definition, that's not TDD, yet novice practitioners easily revert to the old habit of writing production code without a failing test. So what if they do? Take a look at Why TAD Sucks for some reasons why you want to write tests first.

Card, Conversation, Confirmation



Source: Ron JeffriesJoshua Kerievsky, Essential XP: Card, Confirmation, Conversation

Too often, the story card is the thing that agile teams elevate. Some teams insist on strict verbiage for what gets written on the card, or on writing the stories very neatly (sometimes even printing them), or on strictly arranging cards on a peg board and adding rules about who can touch the cards and move them. Some teams even go as far as to spend hundreds of thousands of dollars on a tool to track the cards.


But they're only cards! The card is perhaps one of the least important things in agile software development. Wow, that seems like an odd statement for me to make--this whole Agile in a Flash project is about the power of index cards. I carry cards with me at all times. I often depend on their power and flexibility to help expedite various meetings (planning, estimating, brainstorming, etc.). The cards are a very useful tool, but they aren't what's important. The cards ain't the thing!


  • Card - Index cards are little physical things on which you can jot only a few things. A card does not capture all details about what should be built. It is instead a reminder, a promise for subsequent communication that must take place. Ron refers to the card as a "token," a word choice that I like a lot: The card isn't the thing--it's a placeholder for the real thing.

  • Conversation - So what is the real thing? Collaborating to build and deliver software that meets the customer's needs! To succeed, we must converse continually. We must continue to negotiate supporting specifics for a story until all parties are in agreement and the software is delivered.

  • Confirmation - The specifics of what we're building must ultimately be clear to the customer and the team who will deliver. The customer captures this criteria in acceptance tests, designed to exercise the system in enough ways to demonstrate that the feature really works. When this set of acceptance tests for a given card all pass, it confirms to the customer that the story is truly done--the software does what they asked.


I think you could run a very successful agile project without using a single index card. But that's not what I'm recommending. The key thing is to understand what the cards represent.

Arrange-Act-Assert



Source: William C. Wake


In a unit test, three things typically need to happen: you must first create a context, then execute the thing that you're trying to verify, and finally verify that what was executed actually behaved as expected. So if, for example, I need to verify that the system properly applies a fine to a library patron for returning a delinquent book, I:


  • arrange the context by creating a new patron object and setting its fine balance to $0

  • act by executing the applyFine method with an argument of $0.10

  • assert that the patron's balance is $0.10, thus verifying that the fine was applied correctly to the patron


The most direct result of thinking about tests in this manner is its impact on the code's visual layout:

@Test public void applyFine() {
Patron patron = new Patron();
patron.setBalance(0);

patron.applyFine(10);

assertEquals(10, patron.fineBalance());
}

Note the blank lines separating the three act, arrange, and assert sections in the test applyFine. I've even seen some test code with guiding comments to make the section names explicit:

// arrange
...
// act
...
// assert
...

Honestly, it's idiomatic--once this organization is explained, the intent is obvious, and thus it's only a waste of time and space to include such low-value comments.


Emphasizing AAA (Arrange-Act-Assert) played a significant factor in the evolution of the Rhino Mocks framework for NUnit. Ayende Rahien introduced a new interface for Rhino Mocks 3.5, one that dispenses with the need to call a "verify mock" method after assertions are complete. This allows for cleaner, AAA-compliant tests. In contrast, older "classic" syntax for record-replay mock tools generates "mock clutter" across the test--record, replay, and verify calls are littered through the test.


Note that the form can vary. If you're verifying a static function, there may be no need to Arrange anything. And you may also want to introduce preconditions that verify things are in an appropriate state before the Act step--you could end up with Arrange-Assert-Act-Assert, or even Assert-Arrange-Act-Assert. And it's also possible for Act and Assert to be combined effectively in a single line of code. I don't believe there's value in being dogmatic about the organizational form, but there is value in striving to ensure that the intent of the test is clear. Keeping sections clear and visually separate from each other helps!


Arrange-Act-Assert is a simple concept, and probably only adds marginal value. But it costs nothing to practice, and it gets us that much closer to being a community willing to agree on some standards. What I also like about memorable acronyms like AAA is that they provide a consistent way to communicate simple ideas, which often don't have concise and consistent names.

Stay


I was reading an article by Cherie Berklee at Payscale on the topic of surviving layoffs (having not survived one not too long ago) and was inspired by some of the points. I recommend the article to those who have been laid off, and those who hope never to be.
  • Stay Positive is an inspiring bit of advice which no doubt has origins in antiquity, but which was all the more powerful in Berklee's article. I have not always followed this advice, and even had disregarded it for some time in my career and was the worse for it. Staying positive (not fecklessly hopeful or naive) when things are difficult is not just good behavior. It is leadership.
  • Stay Engaged. Though I don't have a reference, I seem to remember Robert Martin talking about professionals, and Craftsmen in particular, being more highly engaged (attentive, focused) than your average code monkey. It is sometimes a struggle to stay engaged, which is why we have things like the Pomodoro technique and pair programming to keep us focused.
  • Stay Professional should be the motto of the Craftsman movement (if I may call it a movement). Always do your best work, and always look for ways to raise the bar on "best".
We should be mindful of these points well before our companies start to have financial trouble. These are things that make us better employees and better people in general. I've since hand-written these three points on a sticky-backed index card stuck to the lower edge of my second monitor. It is there to always remind me of simple ways to be more effective and thereby more valuable.

Ten Principles for Agile Testers



Source: Crispin, Lisa, and Gregory, Janet. Agile Testing: A Practical Guide for Testers and Agile Teams, Addison-Wesley, 2009.


Lisa Crispin and Janet Gregory wrote the recently-published Addison-Wesley book Agile Testing, a thick tome that fills a much-needed gap in agile literature. Prior, detailed guidance for testing in an agile environment was sparse. With Agile Testing and a couple other fairly recent books (2007's Test Driven: TDD and Acceptance TDD for Java Developers by Lasse Koskela and Bridging the Communication Gap: Specification by Example and Agile Acceptance Testing by Gojko Adzic, 2009), we now have a good foundation for comprehensive agile testing knowledge.



The ten principles that the authors published should sound familiar. Four of these principles directly cover XP's four values of feedback, communication, courage, and simplicity; these and the remainder are also largely echoed in the agile manifesto and its supporting principles. So what's relevant about how these ten principles apply to agile testing?


  • Provide continuous feedback - The agile tester is central to providing the team with feedback: Acceptance criteria is the most concrete way to measure positive progress on an agile project. Tests also help identify issues and capture decisions on appropriate future direction.

  • Deliver value to the customer - The insistence on acceptance tests is a "reality check" on scope creep. Acceptance tests help us all understand what it means to realize a customer's needs.

  • Enable face-to-face communication - Testers can often be the ones on a team responsible for bridging the communication gap between customers (BAs, product owners, etc.) and programmers. A tester can be the one who physically brings these people together, as well as the one who drives derivation of a common language between the two parties.

  • Have courage - One of the larger challenges of agile is in sustaining a fast-paced iterative environment, where every two weeks we need to ship quality software. This challenge demands significant courage. Yet the irony is that we also need to understand that iterations afford us opportunities to learn how to fail and adapt--something that can require an even heavier dose of courage!

  • Keep it simple - Agile testers can help push back against an insistence on overly-elaborate features. Testers can also help the customer understand how to incrementally deliver value. They must learn an appropriate balance of iterative testing-- just enough to provide the right confidence in delivering software.

  • Practice continuous improvement - A key element of using iterations is to allow for learning to take place. Testers should be part of retrospectives (and if you're not consistently adapting based on the results of retrospectives, you're not agile enough.) Testers should also treat their career as a profession by continually learning more about testing practices, tools, and the system itself.

  • Respond to change - Agile testing is dramatically different in that there are few true "cutoff points"--things keep changing and thus must be continually re-tested. This requires automation! The agile tester learns to cope with the customer changing his or her mind from iteration to iteration, and correspondingly learns how to incrementally flesh out necessary testing specifications.

  • Self-organize - In a true agile team, everyone has the capability to act as a tester. Agile teams know how to shift focus as needed; from time to time, for example, it may be prudent for programmers to turn their attention toward helping verify a "done" but not "done done" feature.

  • Focus on people - Testers are often at the bottom of the totem pole in a non-agile software development team. Work is thrown at them, their available slice of time is continually squished, and programmers often look upon them as lessers. In an agile team, every shares the responsibility for ensuring that we are building quality product. Agile testers are key in bringing their testing expertise to the team.

  • Enjoy - The ability to help drive the process and be a true, equal contributor to a team can be extremely gratifying for an agile tester.


The use of acceptance tests to drive agile development is perhaps one of the most critical needs for a team that wants to sustain success. With that in mind, it's amazing that it's taken over ten years since the explosion of XP for us to begin to fully document just what agile testing is.

Make It Work, Make It Right, Make It Fast

Today is our first ever reader contribution from Brian DiCroce

Our font today is called "j.d." See bottom of post for details.



Content Source: Kent Beck at C2.com wiki

When working on a feature, let yourself be driven by this little principle to actually get things done right.

Make It Work
Program with your mind focused on the feature's basic behavior. Just make the feature work. Ensure that all the test(s) pass for that feature.

Make It Right
Now that you have your feature working (all tests passing), focus on refactoring the code. Tests will provide the necessary feedback. Clear up structural and aesthetic issues, remove duplication, rename variables, etc.

Make It Fast
Once the the tests are passing and the code is clean, you can focus on tweaking its performance. Use a profiler of course. Once again, you can feel confident in your changes because the tests will ensure that functionality is not broken.

I abide to this principle whenever I'm developing a feature. It help to shift my focus toward specific development efforts when working on a single feature. The initial effort is toward getting a feature working for quick feedback from users (or potential users). Improvements can be made after the fact, making the code faster and smaller.

This principle is easily applied in conjunction with TDD. The test-first approach helps me drive the design or API of the feature, while the pre-existing tests ensure that the rest of the system continues to function correctly. Refactoring can be applied naturally and at will as the new tests provide a safety net for the code. With the functionality assured, performance improvements may be added with confidence.

If your quick-running, hand-optimized system does not do what it is suppose to do, it is not worth investing time and resources in making it any faster. After making sure that the feature works correctly, you can focus on the performance of the feature. Once again, the tests act as a sidekick in that they will continuously provide you feedback whether changes broke the system.

About the font:
"j.d." is a windows/macintosh truetype and postscript type 1 font, handcrafted in the Emerald City by Steven J. Lundeen, Emerald City Fontwerks, Seattle, Washington, USA.
Generously released as freeware, and copyrighted ©2001.

Legacy Code Change Algorithm


Source: Feathers, Michael. Working Effectively With Legacy Code, Prentice Hall PTR, 2005.

A simply-written technique is not always easily written. The best reference for this technique is Michael's book, of course. Second best is the paper available through Object Mentor's web page (Michael's published papers).

To identify change points is either very easy or very hard. Find the place where you want to make the next change in order to get a new feature added or to eliminate a bug.

The point of change may be nested too deeply inside other methods or into a long if/then/else case, or buried in classes referenced by other classes. Michael suggests that this effort is proportional to the the sickness of the code.

When you know where the code needs to be changed, you need to find test points . Michael calls them "inflection points." The inflection point is in the call tree where any change below it will either be evident or insignificant. The test point is often not the change point.

Break dependencies that make it difficult or impossible to start writing tests to get some coverage of the current behavior at the test point(s). It is normal, in a legacy code base, to do some "pre-factoring" to make testing possible. This is tricky territory, since you don't yet have test to protect you as you work. Expect to spend time running and manually validating basic functionality. You are of course better off if there are some tests that cover the test point.

Write tests to cover existing behavior at the test point. Remember your tests will need to comply with the F.I.R.S.T. principles.

Make changes and refactor the change point in the normal test-first manner, enjoying the test coverage you've built.

Extreme Measures


(font is Flourine)

This is a dangerous "power" card. This is not the first card one should reach for, and one should not make these changes without some consultation with peers. These tend to not be the kinds of changes a transitioning team would make for itself. Still, the practices do have merit and can be used to train a team and the organization around it to adopt agile behaviors. These are mostly "trellis" measures, probably best selected by a transition consultant or coach.

You may shorten iterations to force priority when you find that a team is suffering slump and binge cycle. Teams may slump for a number of days with knowledge that they still have plenty of time to complete a feature, and then cram in overtime at the last minute to complete their work before the deadline. This syndrome is often related to term papers, finals cramming, and amateur theatre rehearsals.

With shorter iterations, the excitement of picking up new work and the immediacy of due dates brings focus. The goal is that each team member goes home happy and tired, and comes back refreshed and ready to work after a full night's sleep. That can work with shorter iterations and shorter days. This extreme measure should be taken to stop overtime, rather than to inspire it.

Mandate that a subject-matter expert can only help others complete tasks so that expertise will spread through the team. If an expert works alone in her area of expertise, then the team continues to be starved of experience. Worse yet, you may find that work has to queue for the expert and "steel threads" abound. An expert may not want to "own" an area of the application, but the organization may force it to be so. This does bad things to "truck number." It is best if a subject-matter expert not be siloed for the sake of the expert, the team, and the software organization.

You might require that 40% of all work is done at the iteration midpoint to avoid the slump-and-binge cycle listed above, since this practice essentially cuts one iteration into two, with a slightly softer deadline for the first one.

If you revert or discard old, unfinished work you will cut down on the Work-in-progress (AKA: "waste") of a team. People don't want to do work that isn't going to be deployed, so they tend to old onto unfinished work in hopes of completing it on the sly "when time allows". Sadly, code becomes dated outside of the current line of version control. Code that is old may no longer merge into the codeline. The longer the interval since the last integration, the less likely it is that code can be integrated. It is often better to scrap and rewrite old features. It certainly makes a statement. Overplaying this card causes depression in programmers and outrage in Customers, so be careful with it. Not playing this card can result in risky rework, which is waste. It is better far if the team only takes on the amount of work it can complete and successfully field in an iteration.

Random weekly team rosters will force closure on features if the team is suffering from soft iteration boundaries. Often teams take credit for work not fully completed (for shame!) and will try to quietly squeeze in the completion of hung-over features during the next iteration. Of course, if they couldn't complete 12 points of work last iteration, why do they think they can complete another 12 points of features plus three points of last iteration's work in the same number of days? If the team is gaming the iterations in such a way, create two teams and randomly shift members between the two. It is especially handy if one team is tasked with new features while the other deals with production issues and bugs. If you don't know where you'll be next week, can you afford to let a feature run long? If you have to complete more work than you can do in an iteration, you really must seek help from teammates. You also need someone who can take over if you're shifted into a new team, so you need to pair with several people on your team, just in case. One risks resentment and lowered short-term productivity with this extreme measure, but one can benefit by spreading more code knowledge and by getting more bugs fixed with the second team.

If you find that your team is suffering from "pair marriages" you might need to stir pairs (at least) twice daily. A bell, loudspeaker announcement, or other mechanism can be used to signal that it's pair-switching time. You might pass a rule that a pair must switch out one partner each morning and after each lunch break. Either way, you can push your team to learn from each other by pairing with someone different for a change. Pair programming was never intended to be conducted by two people chained to one desk for the duration.

It is wise to eliminate individual work assignments as they create a disincentive against pair-programming. If you have work to complete, and I have work to complete, I am less likely to help you because it will put my work at risk of non-completion. Since my name is on my feature, I will be evaluated on my reputation for completing work. In such a system, pairing is an act of great bravery and potentially high risk. Esther Derby has already said everything that needs to be said about the follies of such a system.

I worry a little about this card. I know that agile is about values, and that a primary value is that we value people. We value individuals and interactions over processes and tools. Yet sometimes the people we value need to spend some time in a system that encourages interaction and completion so that they can learn to work together more successfully. I expect this to be the set of ideas that bring us the most angry reader mail.

Yet I think that you have to change the system sometimes. So be it.

SOLID



The SOLID principals are a big topic these days (in the post-Spolsky/Atwood v. Martin war of words). I suppose that is a good thing, because these principles have been around a pretty long time. We taught these as principles of Object-oriented Design at least 15 years ago, and they've appeared in a number of Uncle Bob books.

These principles were developed upon observation of how good code should be structured (and partly by sniffing out why bad code is bad). Never were they presented as a methodology. Always the assumption was that code was being written for good reasons and that it was written to work. They focused on "building things right" rather than on "building the right things."

There is more here than would fit comfortably on a hand-written 3x5 card, by the way.

Single Responsibility Principle (SRP): A class should have only one reason to change.


The original formulation was "a class should do one thing; it should do it all, it should do it well, and it should do it only." This was subject to a lot of interpretation and didn't address the dependency problems in software design, so it was reformulated. A feature of good design is that all classes have clear, crisp responsibility boundaries. When code is munged together or poorly organized by responsibility, it is hard to determine where a change should be made.

Open-Closed Principle (OCP): Software entities should be open for extension, but closed for modification.

This was originally formulated by Bertrand Meyer to say essentially that published interfaces should not change. It evolved to a larger meaning that new features should be added primarily as new code, and not as a series of edits to a number of existing classes. A quality of good design is the extent to which new features are bolted-on instead of woven-in.

Liskov Substitution Principle: Subtypes must be substitutable for their base types.



Barbara Liskov's paper Family Values addressed a notion of the proper use of inheritance. There have always been a lot of design errors from overuse or misuse of inheritance between classes. When a base class has methods that don't apply to all of its children, then something has gone wrong. When a class uses an interface, but some implementations are inadvisable or incompatible, then the design is unclean.

Interface Segregation Principle (ISP): Clients shouldn't be forced to depend on methods they don't use.

In a good design, dependencies are managed. To keep irrelevant changes from flowing up into classes that don't really care about them, it behooves the developer to keep interfaces small and focused.

Of course, the problems of conglomerated interfaces don't manifest the same way in dynamic languages because of late binding, but the problem lives on in C++, C#, Java and other statically-typed languages. In dynamic languages interfaces are not declared, but just understood to exist. If my python program only calls an add routine and an assignment on an argument, then it is understood that the argument must include an add and an assignment in its interface. I automatically depend only on the methods I use in my code, and changes to the underlying class do not seep unbidden into my code.

On the other hand, we find that some dynamic languages are adding declarative interfaces, and some do interface with java or C programs through declared interfaces. Maybe the principle lives on after all.

Dependency Inversion Principle (DSP): Abstractions should not depend on details; details should depend on abstractions.

Since abstractions are built with the intention of writing interface users and interface implementations, it is reasonable that most of our code should depend on abstractions (opening the code to open/closed goodness) rather than concrete implementations (making further change a matter of weaving new code with old). Again, problems with this principle do not manifest the same way in dynamic languages, but not everyone uses dynamic languages.

And of course, even if one uses dynamic languages one might find it useful to use an interface that limits exposure to details. This warning still applies to leaky abstractions.

If one follows the SOLID principles, one may find that their code becomes more fluidly maintainable than if they did not. Ultimately, that is what the whole good/bad thing was about from the beginning.

BTW: font of the day is Anime Ace, a free font. I'm not sure that it will appear in the final version of this card because of its all-caps nature.

UncleBob's Three Rules of TDD



This was one of the three TDD cards I posted while at Object Mentor. A more attractive set of hand-drawn cards then appeared (with full attribution) at Brian DiCroce's site a little while after. I still wish I'd drawn them first. The other have been presented here: FIRST principles and our site's most popular card to date, the Red, Green, Refactor card.

These three laws originated with Robert "Uncle Bob" Martin, who has provided such a wonderful write-up that there is no value I can add other than shrinking the sentences to fit on a card. Bob is a great guy and a solid techie. And by solid, I mean SOLID.

By the way, I've submitted a paper to Agile2009 to do a little session on doing "in a flash" teaching sessions with index cards. If it's accepted, I'll see you there.