Kent Beck, in the prologue of the second edition of Extreme Programming Explained, laments that the first edition is already stale. Just a few years after its writing, the ideas were already adopted and the goal posts needed to be moved ahead once again.
It’s been 13 years since the second edition of XP Explained was released. Since then, we have not had further editions from Mr. Beck but the ideas first seeded by him continue to evolve within the industry.
Things like modern continuous integration, small feature branches, and test-driven development are less extreme and more the new norm of effective engineering teams.
For me, I looked to the many of the early blog posts and ideas of GitHub as a source of early inspiration, a way that software development could be when done right. I remember sitting in the audience of the Future of Web Apps in 2008 and seeing Cal Henderson draw teeth on a release graph. The smaller the teeth, the less likely they will pierce the skin.
Reading programming books, like Domain-Driven Design, at this point is interesting because so much of it is in the water these days. Still, there are riffs on the ideas within those books that might be relevant to the work we do today.
This is my book review of XP Explained, and what we might take from it 13 years after it was written.
economy people, stupid
Extreme programming is about social change. It is about letting go of habits and patterns that were adaptive in the past, but now get in the way of us doing our best work. It is about giving up the defenses that protect us but interfere with our productivity. It may leave us feeling exposed.
Or, to have it put more recently:
The two hardest things in Computer Science are: People, and convincing others that "People" is the hardest thing in Computer Science.— Brad Grzesiak (@listrophy) June 17, 2017
It’s a trope at this point but it bears repeating. The software we write is easy. We are often just smashing bytes together in new and interesting ways. Organizing people to build, maintain, and stay excited about software is difficult.
Creating software is compromise. Are we okay with lots of dependencies buried in a
node_modules directory or does each string transformation need to be a bespoke effort?
Something about software has a Midas effect that causes anyone to touch it to collectively rehash arguments that should be long dead. Designers have been asking “Should designers code?” for a few years now.1
It’s a good chuckle to think of ancient carpenters disagreeing over which way a screw should turn. Did it take them decades to decide that clockwise—which I suppose would be difficult to describe because a mechanical clock was a millenium away—was the One True Way? Did people call each other names in the public square? Did some counter-clockwisers sequester themselves, insisting that their methodology was far superior to the cargo-culting clockwisers?
Perhaps some of the disagreements we have in our work will be washed out with the sands of time, forgotten entirely as the rooted standards survive.
Reading XP Explained gives a sense of permanence to a craft that seems to be constantly upended.
Practices are the things you do day-to-day. Specifying practices is useful because they are clear and objective. You either write a test before you change code or you don’t. The practices are also useful because they give you a place to start. You can start writing tests before changing code, and gain benefit from doing so, long before you understand software development in a deeper way.
Writing software mechanically is a great feeling. There is a proportionality to the difficulty of the problem in front of you and how much you must engage your brain.
Needing to engage your brain on insignificant details is fine if you like solving puzzles, but it’s not what we are paid to do. These details can be anything from What is this variable supposed to do again? or Is this thing adequately tested?
Beck’s description of practices and why to use them resonates.
Throughout my earlier career, I had stumbled in the dark toward some practices that turned out to be helpful. Code shouldn’t look like a mess, I would tell myself. Making my code not look messy early on was difficult. Sometimes things would be made to look clean, but would mask rottenness: needless modularity, incorrect abstraction.
But once I had learned how to modularize better and abstract sensibly, making the code clean was not also a difficulty. Onto the next challenge.
In software development, “perfect” is a verb, not an adjective. There is no perfect process. There is no perfect design. There are no perfect stories. You can, however, perfect your process, your design, and your stories.
This endless perfection is something I’ve learned to get used to. Software engineers probably FigureItAllOut and then have to retire the next day.
Sacrificing quality is not effective as a means of control. Quality is not a control variable. Projects don’t go faster by accepting lower quality. They don’t go slower by demanding higher quality. Pushing quality higher often results in faster delivery; while lowering quality standards often reults in later, less predictable delivery.
As a young software engineer, I learned three variables by which to manage projects: speed, quality, and price. The sponsor gets to fix two of these variables and the team gets to estimate the third. If the plan is unacceptable, the negotiating starts.
This model doesn’t work well in practice. Time and costs are generally set outside the project. That leaves quality as the only variable you can manipulate. Lowering the quality of your work doesn’t eliminate work, it just shifts it later so delays are not clearly your responsibility. You can create the illusion of progress this way, but you pay in reduced satisfaction and damaged relationships. Satisfaction comes from doing quality work.
How many times have we cut a corner in skipping a test and were bitten by it later that week? Eventually, we get to a point where the hardest part of individual work is fighting against that human instinct to cut that corner, just this once.
No one wakes up and wishes their app was slower. No software engineer wakes up and wishes the tests were fewer and more poorly written.
Because software engineering is still in its infancy, it seems rife with many counter-intuitive thoughts. One of them being this: focusing on quality almost always improves the ability to meet deadlines and reduce maintenance costs.
It also improves short-term, less-tangible aspects. Writing good code encourages us to write more code (or responsibly delete what we no longer need). Writing bad code makes us not want to code ever again.
I took two lessons from that experience. One is that no matter what the client says the problem is, it is always a people problem. Technical fixes alone are not enough. The other lesson I took was how important it is to sit together, to communicate with all our senses.
When we write software, we must remember the human implications of the work we do. The externalities of our work are important, but so are how we work with our colleagues.
Extreme Programming Explained gives us practices and a compass for navigating a young industry. It gives us a standard to measure against. Does this new thing allow us to deliver value faster to the customer, without sacrificing our own standards of quality and sanity?
If we recognize that our failings are only of our own making, perhaps we may build something great.
Special thanks to Justin Duke for providing feedback on early drafts of this post.
If you’re interested in receiving blog posts like this regularly to your email inbox, join hundreds of developers and subscribe to my newsletter.
This book is just chock-full of deep ideas. I couldn’t find an adequate spot to include them in this review, so I’m just appending them here with some commentary.
I visited a team that used to deploy every week. It had more and more problems, until it was taking six days to deploy a week’s worth of software. The team chose to deploy every two weeks. This amplified their integration and deployment problems. Any time you move away from flow, resolve to return. Resolve the problems that disrupted your flow and get back to weekly deployment as soon as you can.
Don’t get bitten by The Teeth.
It is as if we started with a dog house and, by gradually replacing pieces, ended up with a skyscraper, all the while continuously occupying the structure. This is absurd in the physical world but it’s a sensible, low-risk way to develop software.
Well when you put it like that, I guess it’s not so bad.
As I began to work in software development, I found the same imbalance of power that Alexander fought in architecture. I grew up in Silicon Valley, where engineering was king. “We’ll give you what you need even if you don’t know you need it,” was the often-explicit motto. Software written this way tends to be long on technical virtuosity and short on utility.
The cardinal sin of software development is to not listen to your customers. I’ve made this mistake many times.
I suppose this friction must exist in just about every business that is trying to do something new. The difficult part is knowing what are the important disagreements to have. ↩