I’ve written before that programming has two audiences: the CPU and your fellow programmers.
There are also excellent articles like Suffering-oriented programming that help align what your goals could be while programming – make it work, make it beautiful, make it fast, in that order, is the suggestion from that article.
“Make it work, make it pretty, make it fast” is brilliant programming advice, and advice I’ve tried to take to heart since first reading it.
Sound programming advice
The programming advice suggests that the program targets the CPU first – thus “making it work.”
Then the advice targets your fellow programmers, the people who have to maintain or look at the code, by making it beautiful.
And once your code has successfully met its computational requirements and met the requirements of being understandable by the mere mortals we work with, then we are able to zero in on what we need to do to make it perform well, assuming there’s an actual need, and the fact that the code is “pretty” means that it’s likely to be easy to find opportunities for improvement, because under most circumstances making the code “pretty” means smaller, isolated functions that make optimization easier.
I recently was talking with a friend online and he presented a problem that reflected experiences I’ve had as well: he was tasked with integrating a body of code that had been created without oversight from a team in a silo. The code lacked tests, and having been written in a silo, didn’t follow the same coding standards as the main project.
It’s a tough situation to be in. Integrating such code means trying to figure out what the entry points are – things that tests would show – and since there are no tests, you have to trust that the coders actually fulfilled the requirements, because under ideal circumstances the tests would show that the requirements were fulfilled, too.
What would you do? What programming advice would you give?
Confronting without confrontation
Like I said, I’ve run into things like that, and while I think I could have handled it better than I did, I also think I navigated the situation fairly well.
People don’t like to be confronted, and it doesn’t matter what they’re being confronted with. Dietrich Bonhoeffer had a really good observation, that people can be stupid, but that groups can be amazingly stupid – and worse, resistant to challenges, with the resistance growing based on how many people are involved. (You can change a single friend’s mind fairly easily – but changing the minds of a gaggle of seven people is a challenge where angels would struggle.)
So what I did was portray myself as the one who was challenged by their codebase. I didn’t comment on the actual code or how horrible it was: I asked how I could learn from the code, because I didn’t understand it.
“Where are the tests for this feature?,” I asked, even though I knew there were no tests. After all, I might have been wrong… and asking where the tests were is a gentle prod to them as to what I needed from them.
That question gives them a lot of leeway.
They could point out where a test actually did fulfill what I needed; perhaps I just didn’t see it? (In this case, no test existed and I knew it, but that wasn’t the point. I needed them to think about the possibility.)
They could also observe to themselves that perhaps the test didn’t exist, and as a requirement for handoff, maybe they could write one.
Testing is hard when you haven’t designed your code for testing, but that’s not your problem until you accept the code, and this gave them an opportunity to revise their own understanding of the code, without having to deal with my opinion of their code.
Of course, perhaps you don’t have the authority to request tests like this. In this case, you may need to request help from a stakeholder – someone who’s responsible for the delivery of the code – and point out that integration of the untested code introduces variable reliability (i.e., it’s unreliable, because you can’t assume it is reliable).
A conversation with a stakeholder about reliability might give you the authority to go back and have the conversation about structure and tests.
Programming advice psychology
And that conversation, again, can be entirely inverted. If they wrote spaghetti code and they’re proud of it – and who wouldn’t be? – you would simply ask that they write it so that you, of little brain, can understand it as easily as you can understand the code written according to your organization’s conventions.
“Wow, that 243-line function is awesome, but I don’t understand it. Can you show me how we could break it down and refactor into something that had smaller functions and composition? And this reference to `j`, is that an index? Could we name it what it actually represents? It’s a window handle? Please help me, I just don’t get it.”
This is basic psychology at work. In a way, it’s manipulation, but we manipulate people in gentle (and hopefully kind) ways every day and in every interaction: we smile when we greet people, to trigger specific endorphins, we mention the good news first (or perhaps not) to create specific mindsets favorable to what we want. It’s not abnormal to use how people think and perceive for your own ends, and it’s not evil to do so when the result is a net positive.
Don’t be afraid to use psychology to help you program. It can be hard, because sometimes it means that you can’t shout at people who might honestly need some shouting – but shouting tends to be counterproductive, and if the goal is to be productive, then we need to think about how to create the circumstances where we get stuff done, rather than satisfying our egos by putting people in their places.