I’ve had to help more than a few teams get their version control systems sorted out over the past few years, and so I thought it would be easier if I just wrote down the philosophies I use for initializing a repository and getting the whole system set up. If you’re looking for some specific advice on how to set up and use a specific version control system, the Pragmatic Starter Kit Series for CVS, Subversion, or Git is a great place to start.
What should go into a source code repository?
The short answer: the repository should contain everything necessary to perform a clean build of your system. In most cases, this includes the code, third-party binaries necessary for building, tests, and documentation.
It’s ok to assume that everyone has their build environment “properly configured” for building. To make sure, make a list of everything that must be setup in the environment to build the software and put it on the team wiki. These things don’t need to be stored in the repository but you should at least write down what the standard build environment is supposed to look like. Depending on what the required software is, it might also be a good idea to keep a copy of it, just in case something happens to vendor in the future. The last thing you want is for a vendor to stop supporting the version of something you need, forcing you to upgrade because your hard drive crashed and you had to setup a new environment.
Include at least the following in your standard build environment list:
- Compiler versions
- Team sanctioned IDEs
- Required frameworks, toolkits, and build tools
- IDE extensions that the team has decided are so critical/awesome to the project they have to be used. Critical/awesome IDE extensions might enable a required tool-kit (such as GWT in Eclipse) or configure the IDE is specific ways (such as coding styles or static analysis settings)
Putting code and tests in the repository is fairly obvious, but third-party binaries (e.g. libraries) might not be. Put these in version control so that it’s easy to check out a project from source control and build without monkeying around with anything. I’ve found it best to create an “ext_lib” folder for storing all the external libraries. This way there is no confusion over what versions to use, and all the build paths can be set so that anyone can build just by checking out the code.
Here’s a real life example. Let’s say you’re writing a web application using the Google Web Toolkit and you rely on a caching library. The caching library should go into your ext_lib folder and you should tuck a zip of the GWT version you use away in a safe place just in case you need it later. Say your team is also using JUnit. Put the version you use in the ext_lib folder. This way everyone can build and use whatever GUI they want to run tests, be it the JUnit GUI or an Eclipse Plug-in.
Another real life example. Let’s say you use the excellent Sharp AutoUpdated component. Should you version the binary or the source? That was a trick question since it depends. The best answer is to only keep the binary of the library, but this isn’t always possible. One of the awesome things about open source software is that you have access to the source if you need it. So, let’s say you find a bug in the AutoUpdater and for some reason the maintainers aren’t responding quickly enough for your immediate needs. You can’t live with this bug so you have no choice but to fix it yourself. Congratulations, you just took ownership over your own fork of the AutoUpdater component. You now are responsible for maintaining the code – either in your version control library or in a public fork, and merging with the original code base may be more difficult in the future.
What doesn’t go into the source code repository?
Remember the DRY Principle for writing code (Don’t Repeat Yourself)? Well, that applies to your version control system too. Anything that can be derived shouldn’t be held under version control. Since your source code is already in the repository, storing the built binary is a violation of the DRY Principle. The penalty? Confusion, mistakes, and avoidable headaches. Third party libraries in the ext_lib folder don’t violate DRY since you can’t build them – you don’t own the source.
Also, do your fellow developers a favor and keep your personal stuff out of the repository. If you’re testing, nobody else wants to see your test reports. When you run the application, keep your logging messages to yourself. Also keep anything related to how you set up your personal environment in your personal environment. The last thing I want is to open up my IDE and see the last tabs you had open because you committed your personal user settings.
The easiest way to keep these sorts of undesirables out of the repository is by setting up an ignore list. Share it among the team.
How often do I commit?
Generally you should commit your changes anytime you think you’ve finished something useful that doesn’t introduce problems into the system. On the average, you should be committing changes at least once a day.
There’s two parts to this commit rule. “Finished something useful” might mean many things. This is by design. When you’ve finished a logical chunk of code that does something, feel free to commit it. “Doesn’t introduce problems” is a common courtesy to your fellow developers. Make sure, at a minimum, the system builds and passes any automated tests you have. And always update before you commit. Depending on your team size and how important the code is, you might establish a checklist for committing. Google has theirs automated. Every change the system has to build, pass tests, and pass a peer review before it can be committed.
Remember this mantra: Commit early, commit often.
But if everyone is committing all the time, isn’t that going to cause problems?
When you’re working with people and coordinating effort, problems will inevitably arise. Just remember, if you’re going to fail, fail early. It’s better to cause a conflict today through miscommunication while there’s plenty of time to fix it than the day before it’s time to deploy. Why? The conflicts will be smaller since you’re incrementally growing your code base. Also, since you made the changes recently they are fresh in your head and easier to work with. Code more than a week old might as well have been written by someone else.
Taking a risk management approach makes mitigating this easy. The risk: “Developers use a shared repository and commit changes frequently; might cause code conflicts that break the build.” The source of this risk is communication; therefore anything which helps facilitate communication can reduce the likelihood of this risk becoming a problem. Daily stand-up meetings are perfect for getting the word out about what everyone is working on. Automatically generated email updates from the version control system keep folks abreast throughout the day as changes are made. Continuous integration acts as a smoke test for uncovering integration problems while they’re small. Good merge tools can help reduce the impact of the consequence.
Once everyone gets used to the update-then-commit cycle, most of these problems go away. In my experience, big problems with code in the repository are usually a symptom of larger problems such as poor communication or failing processes.
What are some of your version control philosophies? What helps you keep things organized so you can get things done?
Everyone has a chore they hate doing. For me it’s cleaning the dishes. I’m a busy guy so I usually don’t get around to cooking and eating dinner until fairly late. Rather than cleaning anything, I stack the dishes in the sink and maybe soak a pan if something burned to the bottom. If the dishwasher has space, I’ll load it and set it going but most nights I leave a big pile of dirty dishes sitting around. After two or three nights of this, all the pots and pans are dirty and there’s no room for cooking thanks to the piles of dirty dishes. It’s actually kind of disgusting.
My wife takes a slightly different tact. After the meal is finished she immediately cleans all dishes, pots, pans, and utensils used while she was cooking. She has the forethought to run the dishwasher beforehand so there is plenty of room to load dirty dishes after the meal. She even wipes down the counter and stove so everything is ready for the next meal we cook. She’s quite amazing actually and a good cook to boot (especially when she’s following a recipe).
Professional chefs take matters a step further still. They clean as they cook.
I procrastinate doing something I hate and the result is a monumental, exhausting chore which takes an hour or more to finish. My wife spends 10, 15 minutes tops a night “tidying up” and though she hates doing dishes just as much as I, she makes it seem effortless. Professional chefs make miracles in the kitchen minutes at a time.
So it is with software.
Integrating software, even with a small team can be a chore. Which would you prefer? Approach A: write a lot of code, get everything working individually, and then do a big bang integration at the end; or Approach B: write a little code and integrate a little. While putting off integrating might satisfy your immediate needs, much like skipping dishes and moving straight to dessert, Approach A is going to cost more than Approach B in the end. Why?
- Integration problems aren’t uncovered until you integrate (profound, I know) so the longer you wait to integrate, the longer it takes to find out if there is a problem. Of course, no one ever plans for problems…
- Conflicts have further reaching consequences the longer you wait to fix them. Modern version control systems usually do a pretty good job merging changes but even magic has its limits.
- The full power of refactoring can’t be realized because the turnaround time on changes is too long. The side effect is that you don’t refactor which means the code becomes more brittle over time.
- More code changes means more time to bring it all together and a higher likelihood of introducing defects through integration. Unless you’ve planned knowing that integration will take time, chances are good you’re going to ship late.
Even better than big bang and nightly builds: continuous integration, cleaning as you code. Automated build servers have made huge advancements over the past few years. I highly recommend Hudson. It’s super easy to install and get started and has plug-ins for practically everything. There are even Hudson plug-ins for C# and just about every version control system you could want (and even some you don’t).
Doing chores sucks, but don’t make it worse than it has to be by putting things off. Continuous integration is a no brainer. If I had a dishwashing machine that constantly washed dishes as I finished using them I would dance naked in the streets, celebrating the marvels of modern technology. (You should be thankful such a machine doesn’t exist.)
You really don’t have an excuse for not using continuous integration.
Most software processes are light in two areas: quality assurance and process improvement. Most processes prescribe specific techniques for ensuring the production of quality code. XP for example advocates unit testing with TDD, continuous integration with smoke tests, pair programming, and acceptance tests written by the customer (using something like FIT so you can run automated regressions). Process improvement in XP is accomplished in a ’round the campfire, Kumbaya singing, get in touch with your feelings brainstorming session. Assumptions abound and there is no systematic way of ensuring that either testing or process improvement is handled adequately. As we know, assumptions are never good enough.
The biggest assumption in XP (and indeed most software processes) is about bug tracking. Common sense dictates that you will create some kind of bug database. Hopefully it will at least be some kind of third party bug tracker such as Bugzilla or Bug Genie. Excel will work in a pinch but quickly becomes unsuitable for teams larger than one developer. But how does the bug tracking actually work? What bugs get reported? Will you record issues from inspections in your bug tracker or only “true” bugs? What is the process for fixing a bug? What is the process for closing a bug? Who has access to the bug tracker? What information is required in your bug database and what information is optional? How do you determine defect priorities? Or the severity of bugs?
The majority of software processes provide answers for almost none of these questions. You are largely on your own to make up whatever you think makes the most sense for your development environment based on the best practices for your software process and your understanding of “good” software quality assurance practices.
No matter what quality process you follow, you will need a defect control philosophy. Once again, in absence of guidance I turn to the Team Software Process, one of the few processes to define what it means to track defects. In the Team Software Process, defects are treated as blight, a horrific mistake injected through the ineptitude of a developer. To remove these blights, the TSP relies on a series of filters in the form of code reviews, code inspections, unit tests, function tests, and so on. XP has a similar, though somewhat less rigorous set of filters in the form of pair programming, TDD, continuous integration, and acceptance tests. Each filter is meant to remove more and more defects, until finally “all” defects are removed from the system by the time the software has passed through all the filters. Generally each filter is intended to remove different types of defects, though it is conceivable to capture escaped defects from a previous filter in a later filter.
Just as water passing through layers of sand and rock will remove debris, so too will code passing through layers of unit tests and inspections sift out injected defects.

Defect Data
With these ideas in mind, bug tracking has three basic goals.
- Record defects so they can be analyzed and fixed.
- Identify the means by which defects are injected.
- Identify the means by which defects are removed.
We write down bugs so we can go back and fix them later. This is obvious. But bug data can be used to measure process improvement also.
Since many parts of a software process are dedicated to filtering out the defects we’ve injected, understanding how defects are injected is essential to preventing similar defects from being seen in the future. The idea is that we want to learn from our mistakes. To achieve this, record the type of defect and the reason it was injected. The TSP gives us a good starting point for each of these, shown in the tables below. You should feel free to modify the types and reasons so they make sense for you, your team, and your project.
The defect type characterizes what kind of defect is injected and captures the essence of what is needed to fix the defect.
| Defect Type |
Description |
| Documentation |
Problems with documentation, documents, comments, or messages |
| Syntax/Static |
This usually is a compile error. These days, this is most applicable to dynamically interpreted languages such as JavaScript or Python since compilation is basically free. |
| Build/Package |
Errors due to incompatible versions or problems with packages (e.g. Java). |
| Assignment |
Incorrectly assigning a variable or method, for example an incorrect expression or object assignment, calling the wrong method, or missing an assignment or method call. |
| Interface |
These are design problems, for example class interface issues or function parameter issues (e.g. order, type, or missing parameters). |
| Checking |
Problems arising from incorrectly handling errors. For example, an if-statement or loop invariant does not work as expected. |
| Data |
Defects involving data representations within the software. |
| Function |
Algorithmic or functional defects, usually involves more than a few lines of code. |
| System |
Issues that result from outside the software, for example hardware timing issues or network problems. |
| Environment |
This is development environment can is used to categorize problems in the environment such as compilers, frameworks, or support systems. |
The defect’s reason characterizes why the defect was inject.
| Reason |
Description |
| Education |
You didn’t really know how to accomplish something. |
| Communication |
You were misinformed through either documentation or personal communications. |
| Oversight |
You forgot to do something that you knew needed to be done. |
| Transcription |
You understood what to do but you simply made a mistake. (The Personal Software Process advocates writing down code, reviewing it, and transcribing it to the computer before compiling. This is a bit of a throwback and I’m not sure that it really makes sense these days. You might interpret this more loosely to be problems in translation from architecture or design to implementation). |
| Process |
The process you are using led you astray by encouraging you to make a mistake. |
Assigning the reason can be a little tricky. I have found it is best if the person who injected the bug assigns the reason. On small teams (or if you’re following the PSP), this is generally pretty easy. It’s not about rubbing their nose in the problem – well, actually it is. Ok, it’s not about embarrassing or punishing the person but creating an opportunity for learning from our mistakes. If you can understand the reason why a defect was injected, it’s possible to prevent the defect from occurring again. For example, if there seems to be a rash of education related defects in a particular module, perhaps some training is in order.
Ideally we’d also like to know when the defect was injected, as in at what phase of development. It is possible to realize this information with additional analysis but I’ve found the return to be rather diminutive. Basically, you’ll learn what we’ve known all along – that the longer a defect is in the system, the harder it is to get out and that the most expensive defects are injected during the earlier phases of development (e.g. design defects are costly). Rather than track when things were injected I think it makes more sense to track when defects are detected. The point is to gain an understanding of how well the quality process filters out defects. To accomplish this, simply write down what you were doing when you found the bug. If you’re using XP, the list might include designing, writing new code (in a pair), writing new code (alone), refactoring, unit testing, integration, and acceptance testing. With this information you should be able to determine how effective each activity filters defects and over time whether the quality process is having issues. For example, I would expect interface defects to be detected during integration. If they are being detected earlier, say during unit testing, or later, say during acceptance testing, then my continuous integration and smoke test suite might not be as robust as it should be.
Better Bug Tracking
The strategies I’ve outlined here are a little more sophisticated than your average bug tracker, but add a lot of punch for very little effort. Tracking defect type, reason injected, and phase detected allow you to get a better handle not only on how defects are being injected into the software, but also how they are being detected. Both these chunks of information are necessary for understanding how defects are making their way into the system and how your process is helping you ferret them out of your system.
Posted: October 15th, 2009
Categories:
Process
Tags:
bug tracking,
bugs,
defect tracking,
defects,
Process,
process improvement,
process tailoring,
software engineering,
Team Software Process,
Testing,
XP
Comments:
No Comments.
Process improvement is a tricky mistress. Usually it’s sufficient to feel that something can be done better, but often, especially for larger organizations or folks looking for higher CMMI rankings, it’s necessary to quantify improvements in terms of measurable effects. There is a cost to process improvement; every hour spent beefing up process is an hour less spent doing “real” work. And if you optimize out the wrong processes it could seriously damper development. The key is to determine the most cost-effective changes and only execute those process improvements. Return on investment analysis is one way to understand cost-effectiveness (PDF), but I’ve found this technique conceptually difficult to apply to software. How much is quality worth? How do you put a dollar amount on developer happiness? What’s a line of code worth to you? It’s enough to make your head spin, but a good friend of mine, Kenny, once gave me some great advice that helps me keep things straight.
You’ve got to know when to hold ‘em
When you’ve got a process that works, keep using it. It’s a great feeling and there isn’t much better than finding a process that works well for you and your team. When you finally settle on a process that works it can lead to a boon of productivity. If you’re disciplined enough to capture data, use it to prove that your processes are actually working. If you aren’t the data type you’ll have to rely on heuristics and intuition and the best heuristic I’ve found is the KA Index. The KA Index is a subjective measure of how much your team Kicks Ass. The best processes are the ones that make you awesome – fewer defects discovered in the field, better predictions of when you’ll finish tasks, fewer fires to fight – all of these are “gut measurable” data points indicating that your process is probably working.
Your gut can get you far but eventually you’ll need data to convince your boss to make the investment. I can highly recommend the Personal Software Process if you’re interested in learning how to use data to objectively measure your processes.
Know when to fold ‘em
When you’ve got a process that isn’t working, drop it. Data can be used here too if you’re collecting it. If you’re not, I’ve found carefully examining process affordances to be helpful in uncovering bum processes but affordances can be extremely subtle. The trick when giving up a process is to quit strategically – not too early, before you might see benefits, and not too late, after you’re experiencing severe problems. (The Dip by Seth Godin is an excellent, short read on this subject.) The other thing to look out for is the cost of dropping the process. Even if your process is terrible, if worse habits fill the process vacuum you could be worse off.
Know when to walk away
Once you’ve decided to abandon a problem process it usually pays to gently transition to something else. Changing processes can be expensive between learning curve, tool changes, and the requisite burn-in period when trying out something new. If your bum process is only killing your team slowly, take a little time to read up on a replacement and avoid setting yourself up for failure. For example, when my team switched to Scrum, we finished the iteration we were in when we decided to make the switch before making drastic changes to our operating procedures.
Know when to run
If your process is absolutely killing you, drop it. Immediately. When considering this route I recommend a thorough impact analysis including some back-of-the-envelope ROI calculations. Changing a horse mid race will be expensive, I’ve seen it happen enough times in the DoD to know that you will pay dearly in the short term, but if the long term costs justify the change and you’re willing to go through the pain, do not hesitate to make the change.
Never Count your money when you’re sitting at the table
Generally I’ve found that processes out of a book need a few iterations of development before I’m able to understand how they really work and how I’m supposed to use them. If you’re following an established process (XP, Scrum, TSP, ACDM, and so on), then try to follow it to the letter before tailoring it. Most processes have built in mechanisms for changing them once you’ve gained some experience and by all means, tailor once you know something doesn’t work.
There’ll be time enough for counting when the dealings done
Postmortems are one of the most powerful tools in your silver toolbox. No matter how the project goes down, always take the time to reflect on what happened, why, and what you should have done so you can use that knowledge next time. Personally, I hate the idea “lessons learned” and much prefer recommendations for next time. “Lessons learned” implies that you’ve learned the lesson and no further action is required but this is hardly the right attitude for effective software process improvement.
Every process is a winner and every process is a loser
So every software engineer knows that the secret to surviving, is knowing what to throw away and knowing what to keep. And in the right hands, the right process can be a savior while under the wrong circumstances the same process might kill a project. I can’t offer any concrete advice other than to not be afraid of data, listen to your instincts, and look back on what you’ve done.
The Amsterdam airport was able to reduce the amount of urine “spillage” that hit the men’s room floor by 80% simply by etching a life-like image of a fly near the urinals’ drains. The fly was specifically engineered into the urinals to alter gentlemen’s behavior without their having to think about it. The concept is called nudging and it’s been used in domains other than restroom sanitation to encourage desired behavior. Other examples include the use of uncomfortable chairs in fast food restaurants to encourage people not to linger and real-time gas mileage displays in cars to encourage more economical driving. If you’ve read Donald Norman’s The Design of Everyday Things then you’ll know this as an affordance – a hint given to the user prompting them to take a specific action at a specific time.
Obviously the idea of affordances is directly applicable to devices as well as software usability but it wasn’t until I read about the urinal flies that I realized affordances don’t always have to have a physical representation. For example, a well designed software process should gently nudge a team to do the right thing. Since there is no one-size-fits-all process that works for all teams it is essential that the process complements the team and that the process’s affordances nudge team members to do what’s best for the project and the team.
Using a process that lacks the right affordances could have one of two possible outcomes. In the best case, the team abandons the process because they realize subconsciously that it is telling them to do the wrong things at the wrong times. This is bad because it sacrifices repeatability; you’ve regressed back to an ad hoc, “make it up as we go” state. In the worst case, the team sticks with the process and it leads them astray. This introduces risks into the project and could lead to complete project failure.
Software is already difficult enough to build successfully and processes are supposed to make software development easier. Unfortunately, knowing when something isn’t working is not an exact science, but with a dash of experience and little team reflection (for example from regular postmortems) it is possible to figure out when you are working for your process instead of your process working for you. To demonstrate this I am going to tell you a story.
Our Process
My studio team in the Carnegie Mellon software engineering program is charged with building a web-based requirements elicitation tool that helps users follow the SQUARE process out of the SEI. About halfway through the Elaboration Phase of the project (sometime in the spring semester) the project was going downhill. The warning signs were fairly apparent, we were missing milestones, tasking priorities were confusing, and a lot of work was stalling out at different levels of partial completion. Though we knew there was something wrong we weren’t really sure what was causing it, what we were doing wrong in our planning and tracking process.
The planning process we were using was fairly simple. At the beginning of the phase we looked at all the activities and artifacts that need to be completed by the end of that phase. For each identified milestone we enumerate specific entry criteria, general tasking, validation procedures, and exit criteria. This is a technique known as ETVX (entry, tasking, validation, and exit). Next we used planning poker to estimate how long we thought each milestone would take to complete. Finally, with this information we created a phase timeline which includes known due dates and dependencies between milestones.
Since we’re using an iterative approach to complete work in a phase, iterations follow largely the same planning process on a smaller scale. As a team we identify the milestones on which we will work during the iteration. Each milestone is assigned an owner whose job it is to ensure the milestone is completed by either delegating tasks or working on it themselves. The planning poker estimate is used to determine the approximate workload allocation on the team. This estimate is validated with bottom-up estimates that team members create based on their individual tasking.
There are several good things about this process. First, it’s written down and the team follows it. This is good because it means we can produce repeatable results over time. Second, this process makes use of several practices that are generally considered “good” by software experts. ETVX is a great way to clearly identify project milestones. Planning poker is similar to the wide-band Delphi estimation technique. Third, we’re using two forms of estimation to validate the plan as more information becomes known. Finally, the engineers responsible for the work determine the specific tasking and creating the bottom-up estimates.
You’re Good, but not That Good
In spite of all the good things we were doing, something still wasn’t connecting. The big aha! moment occurred about two weeks into the second iteration. Up to that point I had been working on my tasks that had carried over from the first iteration. The team leader noticed that almost no work had been started on the milestones I owned. [An aside: this, to me, says that at least our tracking process works somewhat well.] During the discussion that followed I became extremely defensive when the team leader asked me to shift priorities for the rest of the iteration. What should have been a simple request turned into a heated debate over tasking. I felt compelled to complete the past due work and here was this jerk trying to stop me. “Sure,” I thought, “I’ll do what you ask, buddy, but when this whole project comes crashing down it’s on your head, not mine.”
Later, as I looked back at the incident, I wondered to myself, “Why was I so defensive in light of such a simple request?” The reality was that the project wouldn’t come crashing down if I shifted priorities and I knew that. So why defend these older tasks when it was obvious that there were more immediate needs?
It turns out that the affordances built into the planning process were encouraging my behavior. There were a few simple things at play that, when combined, decreased our ability to plan effectively.
First, our process encouraged us to plan more work than time allowed. This was due to there being a missing connection between day-to-day progress and the “big picture,” the overall plan. Second, though the new team leader may have believed there was consensus, the team in fact did not wholly agree with the priorities for iterations. This behavior was not specifically discouraged by our planning process and so allowed to persist. Third, leftover work was not addressed during planning. Some tasks might simply expire while others may change priority, becoming more or less important with a new iteration. Since this wasn’t addressed it created a sense of urgency for individuals carrying over work from iteration to iteration. Finally, assigning milestone owners had unanticipated side effects. The goal was to ensure that someone was taking responsibility for coordinating and monitoring milestone work. This worked so effectively that milestone owners exhausted themselves attempting to finish milestones and resisted changes to the plan that prevented them from finishing what was promised.
When it came time to make a necessary modification to the plan, our process encouraged us to fight against the best course of action for the team. We didn’t have the level of flexibility needed due to our process’s affordances nudging us to do the wrong things. Milestones were slipping and people wanted to finish what they started. Project priorities were shifting as the project matured but team members were wearing blinders, ignoring the changing facts around us. To stand a chance at success we had to change the affordances in the planning process. We had to nudge the team in a new direction.
Our Solution
To try to solve this problem we decided to incorporate some of the planning principles from Scrum, specifically the product backlog, sprint backlog, and sprint planning meeting, into our planning process. Scrum takes a more task-oriented approach when planning iterations and correlates the sprint backlog with the product backlog. This better encourages the team to not plan more work than there is time to complete while connecting day-to-day work with the overall plan. Scrum also requires that the team reprioritize work when planning iterations and that we agree on the resulting priorities. This will hopefully eliminate the prioritization conflicts we experienced during iterations. With Scrum, leftover work from iterations is saved in the product backlog. This change decreases the anxiety team members feel when work is left undone (because the work is not forgotten) while simultaneously giving the team more flexibility to change direction as the project progresses. Finally, the team, rather than individuals, takes ownership over the milestones held in the product backlog. With each commitment made during iteration planning, the whole team buys in effectively shifting the passion and dedication individuals held for owned milestones to the commitments we agreed on as a team.
I’m not really sure how Scrum is going to turn out for us. I think the most important thing is that we recognized that something was not working and took action to correct it. I personally would rather see the team fail in a new and spectacular way rather than repeating the same mistakes again and again.
Add This to Your Silver Toolbox
Unfortunately, I don’t think there is a trick for detecting these sorts of process failures. Data and metrics can help but only if the process is repeatable and the team has the knowledge and discipline to collect the data in the first place. Team postmortems can help but if individuals are afraid to raise concerns, you’ll find yourself on a trip to Abilene before you realize it. In many cases, if you think something isn’t going well, others are probably thinking the same thing. Once I spoke up I found out that others thought something wasn’t working also. I was just the first person who was able to articulate it.
Affordances are powerful but subtle mechanisms. In well designed things, we aren’t supposed to be consciously aware of them. But that doesn’t mean they always nudge us to do the right thing.
Posted: March 13th, 2009
Categories:
Process
Tags:
affordance,
Carnegie Mellon,
Donald Norman,
nudge,
planning,
postmortem,
Process,
Scrum,
software engineering,
studio,
tracking
Comments:
2 Comments.