The extreme programming (XP) development process was built upon four core values: communication, simplicity, feedback and courage. The practices of XP, such as pair programming and test-driven development (TDD), all demonstrate fidelity to these underlying values. A few years after revealing XP to the world in Extreme Programming Explained, Kent Beck added respect as a fifth XP value in the next edition of the book.
XP hasn’t been the only place where agile proponents have wanted to elevate a value describing how we should present ourselves to others. You can hear echoes of the XP values in the values and principles of the Agile Manifesto, to which XP proponents contributed. And Joshua Kerievsky’s Modern Agile proposes a new take on the values for agile, one of which is Make safety a prerequisite. A team where safety is a prerequisite consists of team members who demonstrate respect for one another.
Scott Ambler proposed an additional value for his “agile modeling” process (a subset of XP focused on design modeling for software), that of humility:
“The best developers have the humility to recognize that they don’t know everything, that their fellow developers, their customers, and in fact all project stakeholders also have their own areas of expertise and have value to add to a project.”
Ambler considers humility to be on the same side of the coin as respect.
Get TestRail FREE for 30 days!
How Does Humility Help?
I consider respect for others to be an important value for any human, and I also think it’s essential to create a working environment where people can feel safe — to explore, to disagree, to sometimes fail. Yet it’s possible for me to show respect for others and help create a safe environment while lacking in humility. I can respect your opinion and politely choose not to accept it, because I “know better.”
If I instead focus on growing my personal humility, however, I might learn to more readily accept that I may have something to learn from your perspective. Humility allows me to accept facts, opinions and ideas I might otherwise dismiss, often based on my perception of your stature.
Over the years of promoting pair programming in teams I helped, I would often encounter senior developers who felt it was a waste of their time. I would counter that it was to their advantage to help the junior developers ramp up. Better we increase a junior programmer’s ability to deliver now than to discover late in the game that their contributions aren’t up to snuff. The senior devs would sometimes “respectfully” suggest that pairing was great for the novices, but they didn’t need to waste time with it.
As I paired more, I realized that I learned new and relevant things from other developers in almost every pairing session, no matter how inexperienced they are. The wonderful thing about acknowledging the diversity of people in general is that it opens your eyes to things you might never have tried.
People often mask their lack of humility with excuses. A classic scenario: In many organizations, the transition to agile starts with a single successful agile team. The organization seeks to grow the adoption of agile processes, so they point to the successful team: “We want you all to be this successful, so go work this way now.” The typical response is an excuse: “Yeah, sure, but they’re not like us. They had special considerations from upper management and didn’t have to worry about x,” or, “We have tougher challenges.” Underlying the excuse is an interest in retaining status quo — perhaps out of laziness, but ego can be another factor.
TDD and Ego
I teach test-driven development (TDD) classes at least half a dozen times a year, and I’m happy that people are interested in learning about the practice. In most cases, the students are up for the challenge and dig deep into the numerous exercises they work.
When I first started teaching TDD, I started the class by soliciting concerns from the students about TDD. The angst gushed out, and I realized quickly it wasn’t a healthy approach. Instead, I decided to launch them into exercises almost immediately, and we’d discuss how they felt about each exercise. Their demeanor leaving the class after day three was dramatically different from when they entered the class. They were enthusiastic about what they’d learned, and interested to try it back at their desks.
I hear the same concerns, more or less, with each new TDD class. A few are key to the fact that TDD demands a different approach: Rather than design and implement a large chunk of code all at once — which presumes we know what the end goal should look like — we instead take a very incremental approach. We introduce tiny pieces of the solution (units), bit by bit, by first designing small tests to describe each unit. Most importantly, we do not introduce complexity until it is absolutely demanded by the current set of tests, which summarize all possible behaviors to date.
This last constraint that TDD imposes — deferring complexity until we can prove it’s needed and we’ve coded a test to prove it works — helps because it minimizes the cost of speculation. Often we never get to the point of needing the complexity, or we find a simpler, preferable route as we go as a result of taking a more incremental approach. Much of the time we still need the complexity, but the incremental approach allowed us to build a solid body of unit tests along the way to it.
The incremental approach doesn’t come without a cost: We must rework tiny bits of code with every new test that drives in a small bit of code. If we absolutely know the exact way the code must look for the end goal, however, jumping to the chase and introducing the end-construct might be a more direct line. (That, surprisingly, is still often not the case for numerous reasons, including the fact that we’ll likely introduce more defects as we go with the direct-line approach. Think of defects as things that demand unknown, sometimes large chunks of exploration and rework.)
“I know I will need a hash map data structure in about 20 minutes; let me just code it now to support that inevitable complexity!” That’s a phrase I’ve heard numerous times. Deferring complexity until needed reflects the toughest test-driven pill to swallow, particularly for more experienced programmers — they’ve built code their whole career with this speculative approach. It seems stupid for them to consider the incremental approach if they know exactly how things are going to play out. It’s offensive for me to even be there teaching them about a different, purportedly better way to build software.
The developers I taught had survived because they had found ways to be successful. As such, they would absolutely not view their stance as arrogant. But it’s certainly not humble.
Three Days in California
Last year I taught TDD to a group of C++ programmers in California. C++ programmers are invariably among the most experienced, most meticulous programmers out there — they have to be, in order to survive in such a peril-filled language.
The reaction to my three-day TDD class typically plays out like this:
- Day 1: “This seems stupid in general.”
- Day 2: “This ‘deferring complexity’ thing is stupid, but I am starting to see some of the value in TDD overall.”
- Day 3: “Oh. This is pretty cool. I might not fully agree, but I’m starting to understand the reasons behind deferring complexity.”
The California class was a little different: There was still a lot of hostility at the end of day two. I’m pretty sure I spent too much time trying to talk through my set of reasons for preferring TDD. I was beginning to worry that the reviews were going to come back negative.
On day three I decided to step back, relax and just let them experiment with things. I worked on putting myself in their shoes as I talked about TDD. I also directly acknowledged that I understood how offensive my presence must seem to them.
The students appeared more relaxed as a result, then enthusiastically shared a bit more of their reality with me. The amusing part was that I got perhaps the best reviews I’d received in several years. The classic wisdom about applying Dale Carnegie concepts to resistance paid off, and dramatically!
Humility Goes Both Ways
I used to vehemently defend all the practices I espouse, particularly TDD. Over the years, I’ve heard programmers say things like, “I’ll never write tests for my code. It’s not my job.” I would often retort with an attempt to defend TDD, providing all the reasons I believed it was the right way to code.
Encounters like this expose a lack of humility on behalf of both parties. There is absolutely some sense of arrogance to saying, “I don’t need no stinkin’ tests,” but there is also arrogance to presupposing TDD as a solution.
I’ve since moved on. Mostly, I avoid the debate at all — if someone insists they don’t want to learn TDD and they think it’s stupid, that’s their business. If I’m working with them in a specific training or mentoring capacity, it’s a different story. I presume they’re there to learn, in which case I do address their concerns and rebuttals.
But my approach to handling the debate has shifted, particularly in a relaxed environment where we can work on their specific real-life coding problems. Rather than meeting them head-on, which isn’t effective, I find a way to get on their side and see things from their perspective. This means first assuming that I’m going to learn from them: I need to understand their codebase, obviously, but I also need to learn how they currently approach solving problems and about other wisdom they’ve collected over the years. I make it clear that they have expertise I need to learn. We work through things together, and I drop little reinforcing hints along the way about what’s happening as I help them shift their approach.
The attitude shift that results from a humble approach is nothing short of amazing. And demonstrating humility yourself is often a great way to foster humility in others.
Article written by Jeff Langr. Jeff has spent more than half a 35-year career successfully building and delivering software using agile methods and techniques. He’s also helped countless other development teams do the same by coaching and training through his company, Langr Software Solutions, Inc.
In addition to being a contributor to Uncle Bob’s book Clean Code, Jeff is the author of five books on software development:
- Modern C++ Programming With Test-Driven Development
- Pragmatic Unit Testing
- Agile in a Flash (with Tim Ottinger)
- Agile Java
- Essential Java Style
- He is also on the technical advisory board for the Pragmatic Bookshelf.
Jeff resides in Colorado Springs, Colorado, US.
Test Automation – Anywhere, Anytime