The whole “tabs versus spaces” thing occupies sort of an iconic position in the programmer world. It represents the impossibility of winning arguments that are unwinnable by their very nature. These are so-called religious wars — our techie version of The Butter Battle Book but without the Cold War overtones.
But this and arguments like it rarely actually play out in team rooms and offices. At least, that’s always been my experience. I’ve only ever witnessed live “tabs versus spaces” arguments happen ironically.
Actual Arguments in the Programmer World
So here’s how it really goes down.
You take a job with a company, excited about the new office, the shorter commute, and the bump in pay. You’re riding high. But then the onboarding starts with the codebase.
Greg, the most senior member of the group, walks you through the codebase with a slightly smug affect of obvious pride. The codebase has everything you could ever want, according to Greg. To your mounting horror, this includes
- Inheritance hierarchies that are inscrutable, dark, and deep (with miles to go before you sleep).
- A generous portion of global state.
- Liberal use of reflection, often for no discernible reason.
- And, of course, an extensive, homegrown “framework.”
Greg finishes with a flourish: “So, anytime you need to add a new feature, you just open GodClass.cs, scroll down to line 12,423, add another method, and get started!”
You’re new, and you’re not entirely sure that this isn’t an elaborate prank, so you swallow and say, “Oh…great!” while already planning the lengthy suggestions document that you’re going to put together. And so the stage is set for what will become a never-ending string of arguments of variable politeness about the codebase.
Swap my hypothetical specifics for yours, but the formula is the same. Someone is asking you to exist in a codebase that you have philosophical reservations about, which will force you to write code you don’t like.
Winning Arguments: How Does One Define This?
I’ve now set the stage, but what does it actually mean to “win” an argument? This is pretty hard to define in a lot of contexts, such as people arguing on Facebook about politics or fighting at dinner. Is it the one who got the last word in? The one who was louder? The one who didn’t simply give up?
Luckily, in your quest to de-Greg your new company’s codebase, “winning” is easier to define (if admittedly something of a loaded term). You win if, by mutual consent, however grudging, the thing you think should happen winds up immortalized in the team’s source control. And the mutual consent part matters. Just slamming something into source control and being forced to revert later by an angry Greg doesn’t count.
You win when your argument carries the day and results in concrete action. So let’s look at some techniques for making that more likely.
Cite Credible Experts for Support
Let’s get something quickly out of the way here. There is a logical fallacy known as “appeal to authority,” and you’re flirting with it, following this first piece of advice. But your goal is to fix your codebase — not to win a high school debate club competition. So err on the side of citing respected industry figures for your arguments.
When you’re planning to initiate an argument, this is pretty simple. You want to convince Greg and team to ease up on the global variables? Cite Ward Cunningham on the matter. Think your team should adopt automated unit testing? Cite the eXtreme Programming (XP) guide. When you’re preparing your pitch, do your research and present it cogently and in an organized fashion: “I think we should do X, and here are both my reasoning and some supporting material.”
But you should also have counterarguments lined up for objections. That way, if someone initiates an argument, you can be prepared to counter either in the moment or, if you don’t think that quickly off the cuff, in a follow-up email. Someone telling you that TDD is actually bad for architecture? Check out this article where Uncle Bob Martin refutes that idea.
Rely on Systems (e.g., Static Analyzer Guidance)
Finding blog posts or conference talks isn’t your only option to bring in a favorable supporting case. You can also rely on static analysis tools.
For instance, perhaps Greg packages his global-state wolf in the sheep’s clothing of the singleton design pattern. You want to argue that this is a problematic approach, but that’s tough since the pattern was in a seminal book on object-oriented programming.
So, fight back with static analyzer guidance. NDepend, for instance, has a rule entitled, “avoid the singleton pattern.” This guidance is much more recent than the one in the book, and a company that specializes in static code analysis tells you it’s a bad idea.
So enlist the various flavors of linters and analyzers at your disposal to look for a supporting case for your argument. This can prove quite powerful. It makes Greg look like he’s lobbying in favor of compiler warnings.
Show, Don’t Tell
A while ago, I wrote a post talking about the discrepancy between what we think our architecture looks like and what it actually looks like. We think it looks like a nice layer cake or some kind of hexagon, but it actually looks like the Death Star:
Think of how powerfully you can use this understanding gap. Does Greg’s architecture actually look like this? Probably, if it’s as I’ve described it.
Keep in mind the cliche that a picture is worth a thousand words. You can tell Greg and the group, “This architecture is way too coupled, and we should look to remove superfluous dependencies.” Or you can show them. “That’s our architecture. Does that look good to you?”
A/B Test and Prototype
Many arguments about code and architecture amount to trying to predict the future. You propose a solution, and people say things like the following:
- That will take WAY too much code to implement — my way will be simpler.
- Nobody will be able to understand that pattern.
- We’ll have to make a bunch of changes the next time someone wants to add a feature.
- That won’t work.
Both parties then proceed to argue about a speculative future. In this case, the scales generally tip, by default, to whoever has the most experience or management trust. In other words, in the future-prediction game, you will almost always lose to Greg.
So, roll up your sleeves and spend some of your spare time building a prototype. It won’t work? Build it and show people that it will. It’ll take too much code? Build a representative prototype and show them that it won’t. Nobody will be able to understand it? Build it both ways and solicit opinions.
Obviously, this requires a fair bit of extra effort, some of which you may have to expend during your spare time. You can do that, or you can always propose what agile folks call a spike. Propose a time box during which you run an experiment to see what happens, instead of speculating. It’s a reasonable proposal that, frankly, looks bad for the other party to argue against.
Prove It Empirically
I’ll close with what I think of as the most powerful way to win arguments about code. Simply prove it.
You could argue that this is what I talked about in the last section, but I’m actually introducing a stronger concept here. With prototyping and A/B testing, you’re devising a representative experiment to serve as a compelling argument. But it’s still somewhat speculative — just less so.
Here, I’m talking about cold, hard proof. Often this will arise when people argue about performance. Don’t argue — run time trials.
But it can also apply to things like architectural concerns and code properties. You can literally prove that Greg writes more complex code than you do. Whenever possible, look to predicate your arguments on verifiable facts. You’d be surprised what you can measure when you get used to doing so. Frankly, for me, this was an enormously appealing use case for NDepend all those years ago when I discovered it.
Maintain Perspective
Everything I’ve said here will help you win arguments that you might have about code. Fight the good fight, as it were. But here’s another benefit that might not immediately occur to you. These techniques can also help you see when you’re wrong.
You might do an A/B test and discover that “B” carries the day. You might go looking for expert support and find only counterarguments. All of it can help prevent you from making arguments that you shouldn’t make.
And this speaks to the importance of perspective. Every one of us casts ourselves as the protagonist and Greg as the villain. But winning arguments is really about doing the right thing for the codebase, the business, and our customers — not simply getting our way.