patrickwilsonwelsh.com

Agile coding, agile testing, agile coaching, the agile enterprise, and Network Weaving.

Wasteful vs. Necessary Types of Variation and Complexity

Premise: No, Software Dev Ain’t Like Manufacturing

So it’s pretty old news that software development is not manufacturing. The reason many of us have questioned manufacturing metaphors  is that software development involves inherently much more variation. Compared to a factory line for a sports car, building the average corporate CRUD web application (not to mention much more interesting app types) is just a completely different animal.

Once a factory line for a sports car is designed, built, tuned, and humming along, it includes no equivalents of test-driving an object model, or storytest-driving requirements. In real manufacturing of sports cars, using approaches like Lean, you can reduce away nearly all of your variation in the actual manufacture. You want to eliminate muda. You can get to a point where the exact steps required to build any one of your sports cars are very nearly identical. This kind of perfectly repeatable, fully-automated process is just not possible for converting feature requirements into actual running, tested features. Sports cars and software system features are completely different animals. Fair enough.

Yet We Do Eliminate Wasteful Variation & Complexity in Software

Nevertheless, a lot of what we do in the world of agile development, and agile coaching and mentoring, is exactly this: reducing or eliminating wasteful, useless variation. Things that complicate our lives unnecessarily, that make the whole system less repeatable, predictable, and more expensive. A fleet of best practices and their literature, I would claim, are about exactly this: squeezing the wasteful variation out of our development.

This doesn’t make us mechanizing, reductionist, draconian Taylorists. We are not being less humane, but more, when we squeeze out wasteful variation. The difference between humanizing and Taylorizing turns on being able to distinguish between useful and unavoidable variation/complexity (things that can be crafted) and useless and wasteful variation (things that really can, and should, be simplified or automated).

Indeed: the more of the latter, wasteful sorts of variation we eliminate, the more freedom we buy for ourselves to really shine in those areas where complexity and variation must be crafted.

So what are the kinds of variation that are unavoidable in software development, and what are the kinds of wasteful variation we always want to consider eliminating? Here are my initial lists. I am trying to launch a discussion here, not finish it, so please comment. As usual, I reserve the right to revise this blog post to include smart observations made by commenters and pals.

Necessary Variation Types

When people like Pete McBreen write books like Software Craftsmanship, and people like Eric Evans write books like Domain Driven Design, much of what they are talking about are the varieties of variation and complexity in software development that are unavoidable. The kinds of things that must be crafted, that unavoidably require skill, discipline,  experience, and even trust-community, passion, autodidactic reflex, and courage. These kinds of inherent variation include (but are not limited to):

Requirements Variation

Yes, from a Portfolio Manager or Product Manager’s perspective, it often makes sense to master the art of saying No to requirements. Joel Spolsky, for example, has written wisely about the nature of the “Consultingware” that results from essentially never saying No.

Nevertheless, we have no real control over the kinds of requirements pressure the market will bring to us, and to which our Product Manager might sensibly say Yes. You cannot, in 2002, anticipate rich-client web app behavior that your hand-crafted Web 1.0 application might be “required” by the market to suddenly include. A great deal of requirements variation is not only unavoidable, but wonderfully necessary: this is how, as an industry, we innovate new value flows.

Object Model Complexity

Yes, we want to keep our designs as simple as possible. Yet, over the course of 10 releases and thousands of lines of code, even in the best factored, best test-driven systems, there will be plenty of unanticipated variation and complexity in the object model. This is the problem to which we apply as much Software Craftsmanship as we can. We try to keep the order of complexity of our solutions relatively in line with the order of complexity of the problems they model, release after release. It is very complex to learn to write very simple code. And there is no avoiding it, if the goal is lowest TCO codebase assets, highest-velocity value flow, and good clean fun.

“Given” Technology Stack Variety

I’m not talking about technology/framework selection, but about instead how, for a given set of such selections, some amount of variation comes along. If your team is required to keep working in Java 5 /Spring MVC /Hibernate /Oracle 10g or whatever, then bang, you have a wide variety of syntactic and semantic variations that you cannot avoid, and which, to some extent, you must master.

Team Dynamics

People get hired and get ramped up. People go on vacation and get sick. People quit and get promoted and get fired. Many team membership changes are unavoidable and inherent. Some variation in team membership, experience levels, etc, are unavoidable. (But see below on the importance of optimizing that variation.)

Wasteful Variation Types

OK, here is where I start to enjoy myself. I get to list the kinds of problems I keep trying to solve, better and better. The ways we can improve. Again, this is a draft, partial list of main categories. Feel free to help me flesh it out with your comments.

Non-Deterministic, Imprecise Scope

Just because we cannot control how much requirements variation might arrive at our doorstep does not mean we cannot be precise about describing, planning, and testing a given new requirement’s completeness and robustness. Much of the storytest-driving, acceptance test-driving that agilists push for is about exactly this: given any wacky new requirement, we ought to be able click on a test and have it turn green when we are done-done-done with it. No, this is not easy or cheap. But it is cheaper than continuous scope-related creep, misunderstanding, and kindergarten blamestorming (“It’s a bug!”  “Hell no, it’s a feature!”).  So Yes, we can squeeze out lots of useless variation here, and we do.

Manual Build and Deployment Steps

My pal Mike Hill has blogged hilariously about the courage to automate away manual build voodoo, what he calls Jiggling Toilet Handles. The manual voodoo is classic useless variation. Yes all the little manual steps might be difficult to completely automate away, end-to-end. Doing so might require courage, discipline, and after-the-fact forgiveness. Nevertheless, every time we automate away some dumb, non-repeatable, expensive manual handle jiggle, we start to reap immediate, repeatable rewards. Others who have been fighting this good fight for years include the Pragmatic guys, with books like the original Pragmatic Programmer, and Mike Clark’s lovely Pragmatic Project Automation. Indeed, the entire practice of Continuous Integration attacks this category of wasteful variation.

Manual Regression Testing

Manual regression testing is a classic Sysiphian struggle, wrapped in a Faustian bargain. Your manual test-recorders or manual test plan executors are cheap per hour?  An indescribably false economy! No manual QA team can ever really hope to catch up or keep up. The untested items and defects pile up. Trust erodes. This, truly, is the canonical thing we can automate away, with one or more tiers of automated testing, most critically programmer-level TDD. Squeezing out this variation yields gigantic benefits. Skillful automated testing may well be the most critical contribution to software development of the last 15 years.

BigBallofMud Code

Every un-test-driven, unrefactored codebase eventually gets muddy, then really annoying, then unmanageable, then completely toxic. As a code asset deteriorates, the cost per new feature goes up dramatically in that codebase.  Yes, as we mentioned above, some complexity in a codebase is inevitable. But most complexity in most codebases is entirely useless and wasteful, and about as avoidable as the lung cancer deaths traced to smoking. Courage and discipline and skill and several specific practices are required to produce Clean Code.

Conveyance Muda

As a team, we knock down our cubie walls, we sit in the same open space, we pair, we have standups, and we write story tests (and programmer tests, for that matter). As a team, we continuously estimate, we continuously plan, we continuously retrospect. We do these things for several reasons, but they all have the partial effect of reducing the cost of getting some knowledge or work product from one person to another, from one state to another. These practices make all manner of conveyance vastly cheaper.

The alternative mass-creation of Word, Visio, Excel, and similar artifacts, then firing them in volcanoe-ash volleys over walls between our silos (using emails with dozens of cc’s!), then discussing them vaguely at large meetings, must surely be orders of magnitude more wasteful. It has repeatedly seemed so to me and my colleagues.

Wasteful Skill-Level Variation

Another silo thing. The lottery number: if you were the Nuxeo/Liferay/Maven guy, and none of the rest of us knew that stuff, and you get “hit by the lottery” and quit, how much money is wasted recovering/reconsistuting/reverse-engineering your knowledge?  Ouch!  We pair, and sit together, and collaborate closer and closer on a story’s definition of done, to squeeze out the useless variation in who knows what and who can do what.

Context-Switching Thrash

If you move programmers too frequently from one team to another, where they must struggle to learn whole new (to them) problem domains, solution domains, technology stacks, local customs, it is much like moving all the cab drivers from Miami to New York, and from New York to Miami. How long will it take before anyone gets to the airport on time?

No, you should probably not keep anyone on any agile team forever. But teams should mostly persist. If you let them persist, self-organize, and continuously improve, and if you mostly bring work to teams, instead of people to work, then you save all kinds of thrash cost, and you gain hard-to-describe production economies from new levels of passion, craft, collective courage, and overall quality and throughput.

OK. Enough for one session. Below are categories I have not yet fleshed out. I can and will. Meanwhile, what other kinds of main categories have I missed?  Where can I/we collapse categories together?  How useful is this principle of wasteful vs necessary variation useful to you, as a crude pattern language?  Lemme know, peeps and tweeps.

Poor Value Flows

Administrivia and Bureaucracy

Over-Engineering

Unnecessary Framework Complexity/Waste

Unnecessary Optimization

No comments yet. Be the first.

Leave a reply