I was asked by attendees at my VTM talk on test-driven development a small collection of questions on a similar theme, which I’ll summarise here.
- How do I do TDD when my boss doesn’t want me to?
- What do I do when my boss wants me to ship untested prototype code?
- Can you give me rhetoric to convince my boss that I should be doing TDD?
I believe that I can adequately present these questions as facets of the following root issue, and then blabber away endlessly about that one instead.
I have externalised the obligation I have to myself to write software that makes me proud by delegating it up to my boss. Can you help me to sleep at night?
The fundamental problem here is one of cognitive dissonance. Belief: I, as a software engineer, believe that process/technique/tool is good for writing software. Introspection: I observe that I am not using said process/technique/tool. Justifications: it must be that my boss doesn’t hold my output to the same quality standard that I do. It must be that my deadlines and ever-shifting requirements don’t give me time to do things properly. It must be that this company doesn’t want great software engineers.
No. I have learned the hard way that such justifications are false. The only person responsible for how you write code is you. If you work on a team, or are handing your source code over to some other stakeholder (which means you’re working on a team), then you may have style guides that limit what source code you write; but ultimately how you get there is solely down to you.
You may be thinking “but I asked my manager for time to implement TDD/CI/buzzword-compliance on my current project and she said no. Also, by the way, you’re an arsehole for being so rude and presuming to know what I think.” Let me address the latter point first: suck it. Now onto the first point.
Your manager was correct to turn down your request for time on the project. Your customer doesn’t want unit tests, or comment documentation, or build server output. Your customer wants working features. The project exists to satisfy the user’s needs. Therefore the time allocated on the project should be dedicated to making working features.
Now it turns out that doing TDD is one way to write code that leads to working features, so what you should have done was to agree to the version of the product plan where you make working features, and then done TDD anyway. Where this all started going wrong was not when your boss turned down your request, but when you asked your boss in the first place. It turns out that you both have the same goal—making a good product—but that you have different views on the process and different motivators. By asking your boss how to write code you gave her permission to micro-manage you, then got frustrated when she did, and decided that the problem was all her fault.
I’ve seen this failure mode quite a few times now. As one example, I worked in a company where there was an ingrained antagonism between the product managers (who clearly just don’t get that software is a craft and a labour of love) and the programmers (who clearly just don’t get that we work in a competitive marketplace and would rewrite the product from scratch every day if they could).
As is common (and often correct) in our industry, the product managers owned the product requirements. As should be welcomed when we care about the products we make, the programmers were invited to criticise the requirements for the projects they were working on. Due to this antagonistic culture, the programmers would typically stuff “engineering requirements” onto the project, which were things like rewriting components from scratch, epic refactorings, or setting up new developer workflows.
Requirements were, as far as I could tell, prioritised based on how much revenue they would attract (i.e. new customers), how much revenue they would protect (retained customers) and how much they would cost. As you can probably already guess, so-called engineering requirements don’t protect any revenue, they don’t generate any revenue, and they do take time and money to implement, so they would inevitably get dropped or indefinitely postponed.
The moral of that little story is this: it is folly to try and express development processes and methodologies as business requirements, because they fail at being business requirements. It’s the equivalent of a taxi driver asking the customer to pay a $100,000 fare for one journey because he wants to switch to automatic transmission for the next journey and that means buying a new vehicle. The customer cares about being driven somewhere, and doesn’t care about how the driver operates the vehicle as long as the journey is bug-free. He certainly doesn’t intend to pay for the driver to select a particular mode of operation: if the driver wants to use automatic transmission, the driver should just get on and do that.
So what I’m saying is this: it’s not up to your boss, your customer or your project manager to choose how you write software. It’s up to you to choose how you write software, and as long as the approach you take leads to working software that delights your customers, the rest of the stakeholders won’t mind what you’re doing “under the hood”. My good friend and long-lost son @bmf once said “don’t let them see you making it.” I would go further: don’t let them know it was made. Let them use exciting, compelling software: the magic is your business. If you want to make the magic in one particular way, that would let you take additional pride in your creation, that’s entirely your call.
Phenomenal article.
If you want to be a programmer you are a professional responsible for delivering the best work possible to you, act accordingly.
Thank you.
Very good write up!
This approach works perfectly when you’re working on your own or with like-minded fellow developers. You don’t need to tell the boss about using TDD, Vim, FooBar 2.0. Only thing that matters is whether you’re meeting the requirements or not.
Now the problem might be if you have coders in your team that don’t give a shit about tests, especially if one of those other coders happen to be your boss! They’ll break your tests suite and you’ll be annoyed. I would argue that in many cases, it’s still worth doing TDD on the parts where it adds the most value: mathematical computation or complex algorithms (ie. things that are very difficult to test manually). Even if your test suite gets broken and eventually loses its ability to detect regressions, TDD will have helped a great deal with creating a solid foundation and individual tests will certainly still be OK when you need to update the corresponding parts of the code base.
The worts case I’ve encountered is the boss-coder that forces his developers to do TDD and then spends whole nights hacking on his own entire parts of the app without any tests! If you have any suggestion about *that* one ;-)
Really interesting points, thanks for raising them. Of course, if you think that pain and frustration lies down both paths, then you have to decide whether you’re going to persevere with the one you think “right” or take a hit for the sake of team cohesion. Or find a different team…
I’ve done both now, and I think that the perseverance option is the better one. Treat the times when the tests fail not as evidence that your team members are shaven troglodytes who manage to avoid dribbling on their keyboards long enough to mash out some curly brackets, but as opportunities to show that the test suite is actually working.
“Hey, Bob, your commit last night introduced a regression but it’s cool because the tests caught it before the build went to QA. See, here’s the page from the Jenkins on my desktop, we’re relying on this exception being…” is a better start to a story than “Oh great, Bob screwed up again, I’ll never get these simpletons to adopt TDD. This is pointless…” Notice that it’s not just the technical outcome that’s different, the teamwork aspect of each story is different too.
“Player managers”-the developer/boss super combo meals you describe-are awkward positions to fill because of the inherent difference between the coder view and the manager view of the team and its work: line management is about converting strategy (business/department goals and principles) into tactics (what the team needs to do next), and about reporting on how the team is fulfilling the strategy. The coder view is to execute on the tactics. I’ve worked for each on more than one occasion, the better managers are not doing any coding (even if they have previously been coders) and the better coders are not doing any management (even if they’ve been on the personal relations and coaching training courses).
So now, we think about why this developer-boss comes in late at night and screws up your code. Is it because he’s a jackass who likes to mess with his team? Or is it because it looks like the next milestone might be late, he doesn’t want to report that to the seniors, and he likes you guys enough not to ask you to pull the all-nighters yourselves? If it’s the latter, maybe you can suggest a change to the workflow that might increase the team’s efficiency and the code’s stability, and reduce the number of evenings he has to work on. A change like, I don’t know, TDD…
Thanks for your kind feedback! :-)
Great article!
Hi Graham,
For folks asking these kinds of questions, I’d add that it’s worth interviewing prospective employers on their testing practices (and on their whole software lifecycle). I’ve worked at places that didn’t know a test from a hole in the wall, and places that had testing and even periodic strategic refactoring baked into their culture and processes. Three guesses which of those was a better place to work and converged new features into a shippable state faster and more predictably.
While TDD, etc. certainly aren’t direct business deliverables, I view these as vital non-functional requirements of any serious software project. Failure of a team to get this means that they’re incurring technical debt with every product increment delivered. If the project is big enough and/or long-lived enough, this tends to result in some manner of breakdown eventually. The key idea is that necessary processes (TDD, refactoring, etc.) should be accounted for incrementally /as a part of the work required for each business deliverable/. Tom Demarco hits this from a different angle in _Slack_:
(Sorry to miss your talk at VTM this weekend; I really needed to be in two places at once…)