One of the more useful activities of Scrum involves a bit of self-reflection — namely the retrospect. Admit that what you did yesterday could be done better today, and you are on the way to continuous improvement — a goal in and of itself.
Scrum tells you to ask “What could be improved for the next sprint?” at each retrospect. It is usually hard to think of good answers to this question. In this post I make an effort to compile a list of the most usual suspects, and I also suggest some remedies we have seen to work.
If you are anything like us, your usual suspects would be:
Presented in no particular order, these are suggestions for improvement that we have discovered.
1. Complex and / or undocumented code
Did you stumble upon any code that were hard to understand and even the comments did not help you out? If you did, you know how time consuming and frustrating this is fixing such code. It is a giant waste of time — and you have to spend a lot of time understanding the whole picture in order to refactor it to simpler, documented code. Andidote : Refactor mercilessly. Stop writing legacy code.
2. Untested code
Did you ever struggle to track down a bug in code, only to find that it could have easily have been pinpointed in milliseconds if a test had existed? Did you ever fear improving a piece of code because you did not trust the tests to cover enough to tell you if you broke anything? This and similar kinds of project mistrust is a real killer for productivity. Antidote : Stop writing legacy code. If you have to use legacy code, write tests for the code you are about to use, first.
3. 90% done
Did you ever start coding on some functionality, only to find that it depends on something that is almost finished, but not quite? Obviously you’ll have to finish the 90% done item. And it takes a lot of time, you have to dig into it (losing the context of the current functionality you are working on) in order to complete it properly. Antidote : Schedule work one user-story at a time, and bring all code to 100% completion — i.e make it pass all unit-tests and acceptance tests (customer tests) — before proceeding to the next feature.
4. “Iterating quality in”
Thinking of iterations in form of “write incomplete code now” and the next iteration (whenever that is) “I’ll make it right(er)”, will bring you into all sorts of trouble. This kind of mentality leads to both 1, 2 and 3 above. Antidote : Add more discipline to your iterations. All iterations should end in all commited code being 100% done. Iterations are lovely and necessary, and you will improve existing code during each of them, but you should do your best the first time, as well.
5. You tested what?!
Did you just receive feedback on stuff you did a month / two months / three months ago? Delaying acceptance-testing (customer testing) until a developer has forgotten all about the code is very waterfallish. Antidote : Keep cycle time from checked in code until testing, deploying and feedback as low as possible (hours or days, not weeks or months).
6. Setting architectural goals, instead of functional goals
Setting out to “Create world-saving fancy-schmancy plug-in-environment” instead of “Allow programmer to paste text-data through a plugin-api” (much smaller and better defined) will usually lead us into creating a lot of code that will not be used any time soon. Also, it is much harder to measure “done” in “Create fancy plugin-environment” and the goal in itself is likely to bee too big for one sprint. It leads us into the “90% done”-problem. Antidote : Deliver value continuously and in increments by splitting the problem into smaller user stories, each with a value for the customer. The user stories will be much smaller, allowing feedback and quality into the process.
7. Big-bang integrations
Branching for a while is not a problem when you keep your branch synchronized to trunk all the time. Merging to trunk becomes a breeze. The problem is created for the other guy(s) that have another active branch (god forbid). When you merge to trunk, they are (when synchronizing) smacked in the face with your last week of changes. Antidote : Branch only when you must in order to keep commiting daily changesets which would otherwise make the trunk unstable. Merge to trunk as soon as you have a state of passing all tests. Aim for worst-case scenarios of day(s) between merging to trunk, not weeks.
8. The future is strangling the present
If you are spending a lot of time in requirements (user-stories) the future is killing the present. You are probably going into details too early. Antidote : Add just-in-time discipline to your process.
9. New functionality, but no users
Have you ever launched a new functionality that no-one were delighted to have immediately? This is a waste of time, and best-case scenario someone will start using it in 3 months and lead you into what resembles #5 above. Antidote : Your planning process is broken, involve real users in planning, make sure you are not planning to far ahead.
The “Standish Group Report – Chaos” (1995) points out a key difference between bridge building projects and software development projects (a difference besides the 3000 years of experience in building bridges). The key difference is that when a bridge falls down, it is investigated and a report is written on the cause of the failure. This is not so in the computer industry, where failures are covered up, ignored, and/or rationalized. As a result, we keep making the same mistakes over and over again.
Consequently, do not judge anyone by their mistakes, but by their ability to recover and learn from them. Ultimately this will determine your success.
Seeking to continuously improve materializes in admitting that the last time you did it, you did not do it as well as you could be doing it today. Finding out why, is the key. Today you can be better than yesterday, tomorrow you can be better than today, and so on. This is true if you are willing to take a honest and sincere look at your mistakes.
What could you have been doing better in your previous projects?
Do you recognize any of our usual suspects?