Chapter 9. Corollary Practices

The practices in this chapter seem to me to be difficult or dangerous to implement before completing the preliminary work of the primary practices. If you begin deploying daily, for example, without getting the defect rate down close to zero (with pair programming, continuous integration, and test-first programming); you will have a disaster on your hands. Trust your nose about what you need to improve next. If one of the following practices seems appropriate, give it a try. It might work or you might discover that you have more work to do before you can use it to improve your development process.

Real Customer Involvement

Make people whose lives and business are affected by your system part of the team. Visionary customers can be part of quarterly and weekly planning. They can have a budget, a percentage of the available development capacity, to do with as they please. If this is the kind of customer who encounters problems six months before the rest of the market, making the system they want can put you ahead of your competition. If your product is valuable to them, they may be willing to pay for their participation. The point of customer involvement is to reduce wasted effort by putting the people with the needs in direct contact with the people who can fill those needs.

Whole Team seems to me to imply customer involvement, but I haven't seen many teams go as far as they could toward involving real customers. You will get different results with real customers. They are who you are trying to please. No customer at all, or a “proxy” for a real customer, leads to waste as you develop features that aren't used, specify tests that don't reflect the real acceptance criteria, and lose the chance to build real relationships between the people with the most diverse perspectives of the project.

The objection I hear to customer involvement is that someone will get exactly the system he wants, but the system won't be suitable for anyone else. It's easier to generalize a successful system than to specialize a system that doesn't solve anyone's problem. Ensuring that the system stays generally useful is the job of the marketing members of the team. Generally, the closer customer needs and development capabilities are, the more valuable development becomes.

“The sausage factory” is another objection to customer involvement. “If the customers knew how messed up software development was, they'd never trust us.” Are you sure they trust you now? Software reflects the organization that builds it. The customers are already using the software so they already know a lot about how you develop. If they don't yet, they will soon. When you act trustworthy and have nothing to hide, you are more productive. (Think of all the time you no longer have to spend hiding or covering up.) When you are ready with accurate estimates and low defect rates, including customers in the development process fosters trust and encourages continued improvement.

Incremental Deployment

When replacing a legacy system, gradually take over its workload beginning very early in the project. I was talking with a friend recently about a grocery chain that was planning to switch from its sophisticated home-grown software to a package. The plan was to reimplement the current functionality in the package and then cut over one Sunday night. My instant response was, “That trick never works.”

Every once in a while a big deployment works. You spend months not adding any new functionality just getting ready for D-Day. People work long hours and weekends. If the bet pays off and the new system runs well enough, everyone is too exhausted to return to productive development for weeks or months. And if the bet doesn't pay off and the new system has to be pulled, the costs are even higher. Big deployments have a high risk and high human and economic costs.

What's the alternative? Find a little piece of functionality or a limited data set you can handle right away. Deploy it. You'll have to find a way to run both programs in parallel, splitting and merging files or training some users to use both programs. This scaffolding, technical or social, is the price you pay for insurance.

I used to believe in incremental deployment in my head, not my gut. A job helping to migrate nine thousand contracts to a new system changed my mind. After a couple of months we could handle 80% of the contracts, but because of data quality problems we couldn't match the answers for the other 20%. We spent six months trying to get the rest of the contracts working, including duplicating the errors in the old system. (You wouldn't believe what they did to round floating-point numbers!) Then our manager changed priorities and asked us to convert a different set of contracts. At the end of the year we hadn't gotten any of the contracts deployed in the new system and I lost a bonus equal to the cost of a new house. Now I really, really believe in incremental deployment.

Team Continuity

Keep effective teams together. There is a tendency in large organizations to abstract people to things, plug-compatible programming units. Value in software is created not just by what people know and do but also by their relationships and what they accomplish together. Ignoring the value of relationships and trust just to simplify the scheduling problem is false economy.

Small organizations don't have this problem. There is only one team. Once you gel, once you earn and offer trust, nothing short of shared calamity can pull the team apart. Large organizations often ignore the value in teams, adopting instead a molecular/fluid metaphor for “programming resources”. Once a project is done they go back “into the pool”. The goal of such scheduling is to get all the programmers fully utilized. This strategy maximizes micro-efficiency but undermines the efficiency of the organization as a whole, striving for the illusory efficiency of keeping individuals busy typing while ignoring the value of enabling people to work mostly with those they know and trust.

Keeping gelled teams together doesn't mean that teams are entirely static. I have been astonished at how quickly new members begin contributing to established XP teams. They insist on signing up for tasks the first week and they are independently contributing after a month. By mostly keeping teams together and yet encouraging a reasonable amount of rotation, the organization gets the benefits of both stable teams and of consistently spread knowledge and experience.

Shrinking Teams

As a team grows in capability, keep its workload constant but gradually reduce its size. This frees people to form more teams. When the team has too few members, merge it with another too-small team. This is a practice used by the Toyota Production System. I haven't actually used it, but it makes so much sense to me that I include it here. The other strategies I've seen for scaling up to larger workloads, like creating bigger and bigger teams, work so poorly that alternatives are worth considering.

Since I don't have experience with this practice, I'll explain by analogy. Say five people work together in a manufacturing cell. Rather than load them all equally, make sure that as many people as possible are fully engaged. The fifth person, then, might be working only 30% of the time. This is good. The team members, as they do their work, also think about how to improve their work process. They try ideas until they eliminate enough wasted effort that the fifth person is no longer needed. Trying to keep everyone looking busy obscures the fact that the team has extra resources available.

Try the same in software development. Figure out how many stories the customer needs each week. Strive to improve development until some of the team members are idle; then you're ready to shrink the team and continue.

Root-Cause Analysis

Every time a defect is found after development, eliminate the defect and its cause. The goal is not just that this one defect won't ever recur, but that the team will never make the same kind of mistake again.

In XP, this is the process for responding to a defect:

  1. Write an automated system-level test that demonstrates the defect, including the desired behavior. This can be done by the customer, by customer support, or by developers.

  2. Write a unit test with the smallest possible scope that also reproduces the defect.

  3. Fix the system so the unit test works. This should cause the system test to pass also. If not, return to 2.

  4. Once the defect is resolved, figure out why the defect was created and wasn't caught. Initiate the necessary changes to prevent this kind of defect in the future.

Taiichi Ohno has a simple exercise for this last step, the Five Whys. Ask five times why a problem occurred. So, for example,

  1. Why did we miss this defect? Because we didn't know the balance could be negative overnight.

  2. Why didn't we know? Because only Mrs. Crosby knows and she isn't part of the team.

  3. Why isn't she part of the team? Because she is still supporting the old system and no one else knows how.

  4. Why doesn't anyone else know how? Because it isn't a management priority to teach anyone.

  5. Why isn't it a management priority? Because they didn't know that a $20,000 investment could have saved us $500,000.

After Five Whys, you find the people problem lying at the heart of the defect (and it's almost always a people problem). Addressing that problem and the other problems encountered along the way will give you some reassurance that you won't ever have to deal with this particular mistake again.

I've put formal regression testing, as opposed to just writing another test, in the corollary practices because most teams have too many defects to be able to invest heavily in resolving each of them. Once the defect rate is down to one a week or one a month, though, the investment is proportional and the team has practice improving in other ways. It is ready for a deeper look at its own weaknesses.

Shared Code

Anyone on the team can improve any part of the system at any time. If something is wrong with the system and fixing it is not out of scope for what I'm doing right now, I should go ahead and fix it.

One objection I've heard is that if no one person is responsible for a piece of code, then everyone will act irresponsibly. They will make expedient changes, leaving a mess for the next person who has to touch the code. The risk of this happening is why I've listed Shared Code as a corollary practice. Until the team has developed a sense of collective responsibility, no one is responsible and quality will deteriorate. People will make changes without regard for the team-wide consequences.

There are other models of teamwork besides “every man for himself.” The team members can collectively assume responsibility not just for the quality of what they deliver to users but also for the pride they take in their work along the way. Pair programming helps teammates demonstrate their commitment to quality to each other and helps them normalize their expectations for what constitutes quality.

Continuous integration is another important prerequisite for collective ownership. A two-hour programming session can touch many parts of the system if there are many opportunities for improvement. Two pairs making many, widespread changes increase the chance of expensive-to-resolve incompatible changes. If the team is making lots of changes, it may want to reduce the interval between integrations to keep the cost of integration down.

Code and Tests

Maintain only the code and the tests as permanent artifacts. Generate other documents from the code and tests. Rely on social mechanisms to keep alive important history of the project.

Customers pay for the what the system does today and what the team can make the system do tomorrow. Any artifacts contributing to these two sources of value are themselves valuable. Everything else is waste.

Code and Tests is a practice that is easy to approach a little at a time. A complicated five-stage document-driven process can be lightened up a little at a time as the team acquires more skill. The better the team is at incremental design, the fewer design decisions it has to make up front. The clearer the quarterly cycle becomes at expressing the business priorities, the slimmer the requirement document needs to be.

The trend in software development has been just the opposite for decades. Ceremony interferes with the flow of value. The valuable decisions in software development are: What are we going to do? What aren't we going to do? and How are we going to do what we do? Bringing those decisions together so they can feed each other smooths the flow of value. Eliminating now-obsolete artifacts enables that improvement.

Single Code Base

There is only one code stream. You can develop in a temporary branch, but never let it live longer than a few hours.

Multiple code streams are an enormous source of waste in software development. I fix a defect in the currently deployed software. Then I have to retrofit the fix to all the other deployed versions and the active development branch. Then you find that my fix broke something you were working on and you interrupt me to fix my fix. And on and on.

There are legitimate reasons for having multiple versions of the source code active at one time. Sometimes, though, all that is at work is simple expedience, a micro-optimization taken without a view to the macro-consequences. If you have multiple code bases, put a plan in place for reducing them gradually. You can improve the build system to create several products from a single code base. You can move the variation into configuration files. Whatever you have to do, improve your process until you no longer need multiple versions of the code.

One of my clients had seven different code bases for seven different customers and it was costing them more than they could afford. Development was taking far longer than it used to. Programmers were creating far more defects than before. Programming just wasn't as fun as it had been initially. When I pointed out the costs of the multiple code bases and the impossibility of scaling such a practice, the client responded that they simply couldn't afford the work of reuniting the code. I couldn't convince the client to even try reducing from seven to six versions or adding the next customer as a variation of one of the existing versions.

Don't make more versions of your source code. Rather than add more code bases, fix the underlying design problem that is preventing you from running from a single code base. If you have a legitimate reason for having multiple versions, look at those reasons as assumptions to be challenged rather than absolutes. It might take a while to unravel deep assumptions, but that unraveling may open the door to the next round of improvement.

Daily Deployment

Put new software into production every night. Any gap between what is on a programmer's desk and what is in production is a risk. A programmer out of sync with the deployed software risks making decisions without getting accurate feedback about those decisions.

Daily deployment is a corollary practice because it has so many prerequisites. The defect rate must be at most a handful per year. The build environment must be smoothly automated. The deployment tools must be automated, including the ability to roll out incrementally and roll back in case of failure. Most importantly, the trust in the team and with customers must be highly developed.

The trend towards more frequently deployed software is clear. My instant messaging program fetches updates every few days. Large web sites change imperceptibly daily. Daily deployment is an extrapolation of this trend.

Daily deployment is a good example of a practice that points in a direction. If you can't deploy more frequently than once a year, daily deployment might seem like a pipe dream. I've seen teams that think they deploy once a year actually deploy twelve times a year—one release and eleven patches. The team is capable of rolling out small increments of functionality, but the team is embarrassed about needing to do so rather than seeing its capability as an opportunity. Twelve releases sound a lot better than eleven patches.

How do you implement daily deployment when you have projects that take weeks or months before they are usable? There are many tasks involved in a big project: restructuring the database, implementing new features, and changing the user interface. As long as you don't change the user's experience of the system, you can deploy all the rest of that work. On the last day you put the “keystone”, the change to the user interface, in place.

There are many barriers to deploying frequently. Some are technical, like having too many defects or needing an inexpensive way to deploy. Some are psychological or social, like a deployment process so stressful that people don't want to go through it twice as often. Some are business-related, like not having a way of charging for more frequent releases. Whatever the barrier, working to remove it and then letting more frequent deployment come as a natural consequence will help you improve development.

Negotiated Scope Contract

Write contracts for software development that fix time, costs, and quality but call for an ongoing negotiation of the precise scope of the system. Reduce risk by signing a sequence of short contracts instead of one long one.

You can move in the direction of negotiated scope. Big, long contracts can be split in half or thirds, with the optional part to be exercised only if both parties agree. Contracts with high costs for “change requests” can be written with less scope fixed up front and lower costs for changes.

Negotiated scope contracts are a piece of software development advice. They're are a mechanism for aligning the interests of suppliers and customers to encourage communication and feedback, and to give everyone the courage to do what looks right today, not do something ineffective just because it is in the contract. They might be unwise for you at the moment for business or legal reasons. Moving in the direction of negotiated scope gives you a source of information with which to improve.

Pay-Per-Use

With pay-per-use systems, you charge for every time the system is used. Money is the ultimate feedback. Not only is it concrete, you can also spend it. Connecting money flow directly to software development provides accurate, timely information with which to drive improvement.

Lots of software is already pay-per-use. Telephone switches, electronic stock exchanges, and airline reservation systems all charge you a fee per transaction. While pay-per-use has business advantages and disadvantages, the information it generates can help improve software development.

The ultimate form of pay-per-use I've seen was in a messaging product. Users were charged per message. Each story in development was deliberately selected to encourage more messages. Support for a new handset, for instance, came with both a cost estimate and a revenue estimate. The team analyzed the usage of the system to provide feedback for the accuracy of the revenue estimates. The team used this information to optimize both cost and profitability.

Today's typical arrangement requires the customer to pay for each release of the software. Pay-per-release opposes the supplier's interests and the customer's interests. The supplier is selfishly motivated to have lots of releases, each containing the least possible functionality necessary to get the customers to pay. The customer wants fewer releases (because of the pain of upgrading), each containing lots of features. The tension between the two sets of interests reduces communication and feedback.

Even if you can't implement pay-per-use, you might be able to go to a subscription model, in which software is purchased monthly or quarterly. With the subscription model, the team at least has the retention rates (the number of customers that continue to subscribe) as a source of information about how the team is doing. An even smaller change of business model is to weight contracts more toward support fees and less toward up-front revenue.

One objection to pay-per-use is that customers want predictable costs. If the price advantage of pay-per-use is large enough, customers may not mind. A team using the information provided by pay-per-use should be able to do a more effective job than a team relying for feedback only on license revenues.

Conclusion

The primary and corollary practices are not everything you need to do to successfully develop software. They are, however, what my observations lead me to believe are the core of excellence for software development teams. If you find yourself with a problem not covered by one of the practices, that's the time to look back at the values and the principles to come up with an appropriate solution for your team.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset