« 2016/10/30 - Ownership » |
The catalyst for this post was a discussion at work, and I felt it a good candidate for getting my thoughts down onto virtual paper to clarify my position.
Why should we promote ownership?
I believe programmers are most productive when they are trusted. When someone owns a task you are implicitly stating that you trust them to do it to the best of their ability. They might screw up, and you might have to get involved, but you're starting from a position of trust where you believe the programmer will produce what is required.
Trusting your programmers makes them accountable and reminds them of the consequences of their actions. No longer are they looking to appease people in a code review and move on to the next thing, they're looking to be efficient and minimise their own maintenance burden. They can opt to take the quick or exhaustive approach, their judgment determines whether they get the balance right. When they make a mistake, they learn from it, because they must manage the system through it's lifetime.
Giving ownership leads to proper prioritisation of short- versus long-term goals. When a programmer completely understands a system intimately, they are the best judge of what is important and what is not. They understand the customer's needs, the inefficiencies, the code rot and can quickly react to emergency changes in scope or direction.
Communication also improves. They are known as the go-to person when changes are required. Decisions about the system happen internally in the programmer's brain, without the inefficiencies that result from consensus driven development. The programmer is an expert, with deep understanding of the problem domain, but can still draw upon the experience of others if needed.
A programmer with ownership over a system can feel pride in their work. They can point to that thing and say "it's mine, I made that." They can take care over the system, care that it is easy to use, care that it performs well, care that it meets the goals of it's users. By being accountable the programmer is putting their reputation on the line, and they want to give a good impression.
The perceived downsides
The big three perceived downsides of ownership over code are:
a) The bus factor
b) No swarming
c) Possessive owners
The bus factor
The bus factor, for those who don't know, is when the owner of some system is metaphorically hit by a bus, and thus the company loses all knowledge and expertise in a particular area. It could be that the person is on holiday, or leaves the company, or is actually ill or otherwise incapacitated.
It's a compelling argument on the surface. All you need is one anecdotal story of a company getting screwed over when a particular team member leaves, and you've got a potential threat to mitigate. But drill into this reasoning and I think you'll find it lacking.
When you worry about the bus factor, what you're really worrying about is that your other programmers aren't good enough to get up to speed in any sensible time period. It's true that you could be left with a delirious spaghetti monster that cannot be unpicked, but I would posit that this is the worst-case scenario that actually doesn't occur all that often.
I have worked with many engines over the years, mostly written in-house, but some middleware as well like Unreal. And whilst I have often looked at some systems wishing they weren't written in a particular way, or were just less crazy in general, I've never been so stumped as to be completely unable to understand or adapt a system. Programmers are smart people, they can figure it out. If they can't, hire better programmers.
So if the worst case is overblown, then we're faced with an optimisation problem. How long does it take for the new owner of the system to get up to speed? This is a problem we can solve.
In the worst case, the literal bus case, the programmer has nothing to go on but the code itself and the changelist comments that accompany it. This is bad but doable. With some sensible standards like requiring comments that include some form of intent, you can reconstruct the thought process that went into a change. By piecing together the evolution over time, a better understanding can be obtained for the new owner.
If the programmer is leaving, then you need a proper hand-over period, which is what the notice period is for. The old owner will likely be in no mood to do proper development, knowing that they're leaving, and will likely relish the opportunity to mentally unload and decompress all their knowledge to the new owner before moving onto pastures new.
If the programmer is just on holiday, can you wait until they're back? Surprisingly often the answer is yes, so just do that. If you absolutely need to fix a mission critical bug before they're back then you need to task a random programmer to do so - pick someone senior and smart, they'll get it done. If you need a mission critical feature then you have bigger problems than ownership of systems - that is a failure of management, fix that first.
As I hope you can see, the bus factor isn't as big of an issue that people make it out to be. With proper planning around hand-over periods, it can be avoided in most real-world cases, and even in the hypothetical worst case scenario you just pay the price of a programmer getting up to speed as they would at an ownerless shop. Is the cost worth the perceived benefit?
Swarming
Swarming is when you want multiple programmers to swarm onto a system to speed up development because of workloads. If you have owners, the theory goes that non-owners won't know anything about the system and so can't help out as easily. If you have an ownerless shop, then in theory everyone knows enough about everything to be able to contribute.
There are a couple of things wrong with this theory.
Firstly, the mythical man month is real. You cannot swarm an unlimited number of programmers onto a system and get linear returns. It doesn't matter how much you split up the tasks, or how well the programmers know the system, the simple act of multiple people all working on a system with similar goals is going to lead to breakdowns in communication, dependencies and all the inefficiencies that come with that. Trying to avoid the mythical man month is a fool's errant, don't do it.
Secondly, swarming starts to break down the bigger the piece of software you apply it to. The more systems there are, the more information a programmer has to keep in their head, and eventually they cap out.
When you have three systems, three programmers, and one is overloaded, it is perfectly possible for all three programmers to maintain a good working knowledge of all three systems and thus efficiently roam from system to system helping out as the load demands.
When you have three hundred systems, three hundred programmers, and one hundred are overloaded, everything breaks down very quickly. There is no way three hundred programmers can keep the intricate details of three hundred systems in their head at all times; there just isn't enough headspace. Obviously my example is extreme, but it illustrates the point that as the number of systems increases the idea of an ownerless approach becomes unfeasible. Where the threshold lies can be debated, but there is a threshold somewhere. The solution doesn't scale.
When you think about how the programmer learns about the system, things get even more ropey for the ownerless approach. Lets say you have 30 systems and 10 programmers; nobody owns any system, the collective knowledge is spread across all 10 programmers. If programmer A needs to do something in system A, they have two options; 1) dig into the system themselves on their own and learn everything from scratch, 2) talk to the other 9 programmers to piece together the knowledge they need to do the work they need to do.
Of course, after working with this system they will likely forget most of the details they learnt, or the system will change underneath them, since they have to keep knowledge of the other 30 systems in their head as well.
And so here we have effectively an O(N^2) problem that perpetuates itself.
For a body of programmers to swarm effectively, they have to be able to turn their hand to any system. They don't have enough head space or attention capacity to keep a working knowledge of every system in detail, so every time they need to do some work they have to remind themselves, relearning from scratch, or bothering all the other programmers to piece together the required knowledge. The more systems, the more programmers, the worse the problem gets. Eventually, said programmers are drowning in interruptions, never sure of how systems work, and waste all their time learning something they'll forget in a week because they have to learn something new.
Contrast this to the ownership model. When you need to swarm onto a task, you move programmers to work for the owner of a system.
The owner is the single point of contact for all information about the system. Rather than bothering all the other programmers to piece together the knowledge required, or trawling the source code to re-learn the whole thing, you just ask the owner.
The problem becomes O(1). Yes, there will be some bottleneck on that one owner. But thinking you could achieve perfect scaling with an ownerless approach was madness anyway - mythical man month. At least this way, the owner provides defacto leadership and an expert eye over everything. It's inefficient, but it's obviously so, and trying to fix that inefficiency just moves it elsewhere to all the things associated with the mythical man month - more meetings, wasted work, fuzzy direction, misunderstandings and miscommunication. You can't win, so don't try, fix the problem in other ways.
Possessive owners
My personal opinion is that possessive owners are a goal, not a negative, because in the vast majority of cases when someone takes ownership over something they tend to do a better job in my experience. However, possessiveness can become destructive, if someones coding style wildly breaks from convention, or if they refuse to take changes from other developers for superficial reasons.
These people exist, but ultimately this is a people problem, one that programmers often try to avoid and will go to great lengths to do so.
If someone is possessive and it is destructive, it needs to be dealt with. It is a symptom, not the cause. They need to be managed or fired.
With an ownerless system, that person sprinkles the code with their oddities, gets into fights on code reviews and generally causes problems across the team. They tend to bubble under the surface and never get addressed. By boxing them into their own playground, these sorts of problems get exposed very quickly and the problem children can be removed.
What happens when we don't allow ownership?
Honestly, I believe that most of the negative aspects of software development can be attributed to a lack of ownership. It's a bold statement to make, but bear with me.
By spreading knowledge, programmers never gain mastery in any particular area. They know a little bit about all the systems in the product, but never deeply understand any of them. This is in direct competition with how we recruit, and why we pay so much more for a physics programmer than a gameplay programmer. The physics programmer has a specialised skill that only they possess, we should leverage that skill to the maximal value.
What this leads to is a development team that knows a little about everything and nothing about anything specific. When you ask how the animation system works, you have to piece together snippets of knowledge from three or four people; when you want to understand why something was done a particular way, you get a series of blank expressions and "I just followed the style that was there already." This problem becomes circular - because everyone is working on everything, everyone needs to know everything about everything, and so spend half their time talking to everyone else to try and piece together the knowledge of a system in its entirety.
If anyone actually manages to get to deep understanding of a system, the thing they've been working hard towards for months by piecing together information from others, this is branded a bad thing and something to be avoided - we mustn't use this asset we have because that would expose us to the bus factor, instead we want that programmer to give a talk or write some documentation to educate the other programmers.
This leads to time being spent writing up documentation that is out of date as soon as it is written. Presentations that people watch but cannot absorb because there are so many of them on so many different subjects that they just switch off. When everyone has to learn about everything from everyone else, the problem is O(N^2) and highly inefficient as a result.
The result of all of this is that it is likely that nobody truely understands any system. Everyone has a rough idea of what each system does, and has some experience mucking around with parts of it when they did the last thing on it, but nobody really understands it, and every edit they make is accompanied with a period of learning they must overcome.
If the result of no ownership means nobody really understands any of the systems in your codebase, is that not the same as losing the owner in the first place? In both cases, the programmers are coming to a system with an incomplete knowledge. In both cases, the programmers will need to educate themselves on whatever area they need to understand to make the required modifications. Whilst a ownerless shop might have instilled some knowledge in all their programmers about a system, how useful is that information? Is it fresh enough that they won't have to re-learn everything due to time passed or changes made, will they have touched on the area of the system they need to this time, or is another learning period required?
I would posit that running ownerless is a theoretical win in an unrealistic world. To get the benefits you need everyone to understand everything and remain current on everything. You need everyone to be able to turn their hand to any system and any task at the drop of a hat. This is the sort of goal managers dream about to construct the perfect team, and then waste everyone's time in pursuit of said goal at the expense of actually getting work done.
Separate to all this is the psychological aspect, as I mentioned near the start of this post. I believe a programmer who has ownership over a system is more productive, happier and more of an asset to the team. If you don't allow ownership due to the bus factor, what you're actually saying is that you want that programmer to be replacable - you don't want to realise their individual worth, you want them to be a drop in replacement for the lowest-common-denominator required to maintain your product. If programmers figure this out (thankfully most don't) it can be extremely damaging.
If they do figure it out, then there are one of two paths to take. Either they accept the status quo, be a subserviant tool, deployed from task to task, and treat the job as a pay check; or eventually, they move company to somewhere they think they will be appreciated. Frankly, if you treat a programmer like a replaceable cog, they will act like one.
Summary
It is my opinion that the theoretical benefits of an ownerless shop (bus factor, swarming, no possessive owners) cannot be realised to the extent proponents suggest. I believe teams that force this way of working end up being less productive and unhappier as a result, all to facilitate avoiding a perceived edge case (bus factor with a convoluted system), leverage a debunked theory (swarming, due to the mythical man month) and burying personnel issues (possessive owners).
By allowing ownership over systems, teams gain assets in experts that develop over time. These experts aide communication by focusing information in a single place that does not go out of date. Programmers take pride in their work, understand their systems and can react quickly and sensibly to changing demands. By putting in place proper handover periods during notice periods, teams can avoid the most common bus factor cases and realise all the benefits of an ownership approach.