Agility within software teams
Tags: Programming, Agile Development, Software Development

By Petteri Sulonen, Lead Software Designer at Avaintec

Writing code is easier than reading it. In particular, it’s relatively easy to write code that runs and works, but that is hard to understand. This is because the computer treats code as instructions, whereas humans think in terms of ideas — objectives, means, structures that interact and fit together to produce something that serves some useful purpose.

The consequence is that as software starts to pile up, it becomes locked behind individual people. Only the person who wrote the code knows what she was thinking when she wrote it, and because the code is written so that her thought process can’t be reconstructed easily by reading it — or, indeed, at all — switching someone else to work on that piece of code is expensive. People become prisoners of the code they wrote. As this dynamic picks up speed, the whole team becomes more rigid. You can’t put Andrea to work on the Kerbodyne project although her skills would be a perfect fit because only she understands Rockomax, even though Nabil is free at the moment. In practice, this will mean that Andrea will be assigned to Kerbodyne but will keep hopping back to Rockomax, which fragments her focus, lowers her productivity and the quality of her work, and makes her unhappy — not to mention Nabil, who’s sitting there looking at the Rockomax code feeling really stupid because he can’t make head or tail of it even though he’s supposed to be working on it.

The biggest loser of all, however, is the Rockomax project — Nabil will be making additions and changes without understanding how they fit into the whole and without daring to remove things that are no longer needed, which means the Rockomax codebase will bloat, become more entropic, even harder to understand, slower, and buggier. Repeat this cycle a few times, and you will end up with a big codebase that simply cannot be comprehended by the human mind, with individual coders nibbling at the edges in small areas they know in an empirical way.

”In the long run every program becomes rococo — then rubble.” – Alan J. Perlis

People don’t multitask well. Some are better at it than others, of course, but there’s always a cost, in productivity and quality, and it’s often quality that’ll end up costing more in the end. Somewhat surprisingly, a team that can easily switch people between projects or products doesn’t have to — not all that much, anyway. If, somehow, Nabil could reconstruct Andrea’s thought processes when jumping into the Rockomax project, that would free up Andrea to work on Kerbodyne, and both would be productive, happy, and could stay focused on what they’re doing, occasional questions notwithstanding.

Free your code, the rest will follow

As Perlis puts it in his epigram, the natural trajectory of every piece of code is towards rococo, then rubble. In the long run, it probably is inevitable — all that is compounded, is impermanent, as another famous epigrammatist, the Buddha, put it. In the long run, every automobile will be rust. However, just like it’s possible to expend effort to keep a hundred-year-old automobile running, it is possible to expend effort to keep entropy from taking over a codebase. The force which locks code behind individual coders is entropy, which makes the fight against entropy key to making a team agile. Conversely, the will to be free from the prison of entropic code is a powerful incentive to keep pushing away the rococo.

”One can only display complex information in the mind. Like seeing, movement or flow or alteration of view is more important than the static picture, no matter how lovely.” – Alan J. Perlis

Code is not just instructions for a computer. It is also — in large projects, perhaps primarily — an expression of an idea. Humans have invented programming languages for themselves, not for computers: a computer is perfectly happy executing microcode, flipping transistors in memory banks. Once above the ”hello world” level, a programmer shouldn’t be writing for the computer anymore; she should be writing for humans. Just like in writing an essay, a novel, a poem, or a play, her intention should be to express the ideas she has to other humans as clearly, elegantly, and comprehensibly as possible. Style matters. Grammatical conventions, formatting, and punctuation matter. iFIomitAllpunCTuaTIonaNdwhItesPacefROMMywriTingaNDRanDomiseMYCAPitalizatioNiTbeCOMESDraSTicaLlyHardErTOPArse.

From Vicious to Virtuous Cycles

A program’s natural trajectory towards rococo and rubble derives from a feedback cycle. As a piece of code that starts out perhaps a little hard to understand gets modified under pressure and by different people, it gets a little more complex and a little harder to understand every time. Unnoticed, a critical point passes: now, it’s no longer possible to work on it without the active contribution of the original author. At some point, it crosses an invisible event horizon where it becomes incomprehensible even to the original author, and can only be worked on empirically, by making adjustments and then checking what happened. More and more effort is expended in testing and debugging, but the cycle can no longer be stopped. The system picks up speed, enters the atmosphere, and eventually disintegrates in a spectacular plume of plasma and subroutines.

This vicious cycle has a mirror image: a virtuous cycle, where a variety of practices and incentives reinforce each other to keep the program aloft. This requires a change in mindset from the very beginning.

Write code for humans first, computers second. From the start, a piece of code must be written for other humans. It’s not done when it runs, doesn’t fail, or is secure; it’s only done when someone else is able to read it and reconstruct the thought process of whoever wrote it in the first place. Naming, style, and adherence to a shared convention are even more important than efficiency, performance, or adherence to functional or non-functional requirements: if the code is understandable, efficiency can be improved and functional or non-functional features can be added, but if it’s not, this becomes orders of magnitude harder.

Communicate laterally first, vertically second. Share what you’re doing with other team members on a daily basis, both in formal checkpoints like the daily scrum, and, perhaps more importantly, informally. If you feel you’re getting stuck, as a peer for help. If the code you’re working on has been written for humans, you don’t need the author to puzzle it out: you just need some time, patience, and, perhaps, a second or third set of eyeballs. Conversely, strict vertically-mandated tasks or roles, especially if they’re perceived as a disincentive to help each other out, reinforce author lock-in.

Maintain relentless peer pressure for quality. Code that doesn’t adhere to agreed-upon standards must not be tolerated. Humans don’t need the threat of punishment or drastic sanctions to accomplish this: it’s enough if a sufficient number of people in the team simply says ”this is not OK” when seeing a non-compliant piece of code. We are social primates, and if the team has a strong social norm emphasising quality, clarity, and style, most of us will do our level best to live up to it.

The sufficient number varies. One is rarely sufficient. Two may be, if they enjoy the team’s respect. More is good. Everyone is best.

The sufficient number varies. One is rarely sufficient. Two may be, if they enjoy the team’s respect. More is good. Everyone is best. Polishing things up isn’t a luxury, it’s a necessity. All too often, a coder will say that there was no time to polish something up after they got it running: instead, it was just rushed through QA and into production in the state that it is, /** NOT FOR PRODUCTION, DEV ONLY! **/ comments and all. This is classic penny-wise, pound-foolish thinking, because time will be found when it breaks down, as it inevitably will — even well-written code does that. And that rush job will take much longer to fix when the inevitable happens.

Hand things over: infrequently, responsibly, and with sufficient support, but do hand things over. If you never hand things over, author lock-in will inevitably follow. Very few programmers are disciplined enough to write for their future selves with as much emphasis on clarity and style as when they know they’re writing for their teammates — especially if said teammates like to nag about quality. Conversely, entropy, turbulence, rococo, and rubble will follow if people jump from task to task and project to project rapidly and uncontrollably, or attempt to work on multiple things at once.

Handing things over

Handovers take time and effort. The individual taking over will need to get into the codebase, study it, tinker with it, and slowly reconstruct the ideas behind it. However clearly the code is written, he will need the original author’s support for this. This time and effort must be taken into account when planning handovers: the receiver must start working on the codebase right away, but the original author must be available to answer questions and clarify her thoughts. The handover is the crucial phase which closes the cycle and starts to create a genuinely agile team. The more human-readable the code being handed over, the less painful the handovers will be, and regular handovers will intensify the pressure to write human-readable code.

Towards a genuinely agile team

Regular, controlled handovers of code written for humans will gradually spread knowledge around the team. Over time, more and more members will have worked and become familiar with an ever-larger section of the codebase, and moving around it becomes easier and easier. There is a limit to this — the human mind is not infinitely expandable after all — but that limit is much higher than you might expect. A genuinely agile team where members move with relative ease around the codebase — and where things become easier over time, rather than harder — is possible. In the Avaintec dev team we have been working hard towards this goal for many years now, and the benefits have become tangible. We can shift resources between products and projects, not completely painlessly, but at least without causing a massive productivity hit and swathe of entropy every time it happens. All it took was a change from writing code for computers to writing codes for humans, and some years of practice.