In my last post, I alluded briefly to the concept of “tribal knowledge” when developing software. I’ve heard this term defined in various contexts, but for the sake of discussion here, I’m going to define this as knowledge about how to accomplish a task that is not self-evident or necessarily intuitive. So, for instance, let’s say that you have a front door with a deadbolt lock. If you hand someone else the key and they are able to unlock your door, the process of unlocking the door would be general knowledge. If, however, your door is “tricky” and they have to jiggle the key twice and then turn it to the left before turning it back right, these extra steps are “tribal knowledge.” There is no reasonable way to know to do this except by someone telling you to do it.
Today, I’m going to argue that eliminating as much tribal knowledge as possible from a software development process is not just desirable, but critically important.
Often times when you join a new team, you’ll quickly become aware of who the “heroes” or “go-to people” are. They might well have interviewed you, and, if not, you’ll quickly be referred to or trained by them. This creates a kind of professor/pupil feeling, conferring a certain status on our department hero. As such, in the natural realpolitik of group dynamics, being the keeper of the tribal knowledge is a good thing.
As a new team member, the opposite tends to be true and your lack of tribal knowledge is a bad thing. Perhaps you go to check in your first bit of code and it reads something like this:
var _foo = GodClass.Instance.MakeAFoo();
var _bar = SecondGodClass.Instance.MakeABar(myFoo);
var _baz = SecondGodClass.Instance.MakeABaz(myFoo);
var _reBar = GodClass.Instance.ReDoBar(myFoo);
You ask for a code review, and a department hero takes one look at your code and freaks out at you. “You can never call MakeABar before MakeABaz!!! If you do that, the application will crash, the computer will probably turn off, and you might just flood the Eastern Seaboard!”
Dully alarmed, you make a note of this and underline it, vowing never to create Bars before Bazes. You’ve been humbled, and you don’t know why. Thank goodness the Keeper of the Tribal Knowledge was there to prevent a disaster. Maybe someday you’ll be the Keeper of the Tribal Knowledge.
Forgetting any notions of politics, seniority, or the tendency for newer or entry level people to make mistakes, the thing that should jump out at you is, “How was the new guy supposed to know that?” With the information available, the answer is that he wasn’t. Of course, it’s possible that all of those methods are heavily commented or that some special documentation exists, but nevertheless, there is nothing intuitive about this interface or the temporal coupling that apparently comes with it.
In situations like the one I’ve described here, the learning curve is high. And, what’s more, the pride of having the tribal knowledge reinforces the steep learning curve as a good thing. After all, that tribal knowledge is what separates the wheat from the chaff, and it forces tenure and seniority to matter as much as technical acumen and problem-solving ability. What’s more, it ties knowledge of the problem domain to knowledge of the specific solution, meaning that knowing all of the weird quirks of the software is often conflated with understanding the business domain on which the software operates.
This is a problem for several reasons, by my way of thinking:
- A steep learning curve is not a good thing. Adding people to the project becomes difficult and the additions are more likely to break things.
- The fact that only a few chosen Keepers of the Tribal Knowledge understand how things work means that their absence would be devastating, should they opt to leave or be out of the office.
- The need to know an endless slew of tips and tricks in order to work on a code base means that the code base is unintuitive and difficult to maintain. Things will degenerate as time goes on, even with heroes and tribal knowledge.
- When any question or idea raised by somebody newer to the project can be countered with “you just don’t know about all the factors,” new ideas tend to get short shrift, and the cycle of special tribal knowledge is reinforced that much further.
- Essentially, people are being rewarded for creating code that is difficult to understand and maintain.
- More philosophically, this tends to create a group dynamic where knowledge hoarding is encouraged and cooperation is minimized.
What’s the Alternative
What I’m proposing instead of the tribal knowledge system and its keepers is a software development group dynamic where you add a customer or stakeholder. Naturally, you have your user base and any assorted marketing or PM types, but the user you add is the “newbie.” You develop classes, controls, methods, routines, etc, all the while telling yourself that someone with limited knowledge of the technologies involved should be able to piece together how to use it. If someone like that wouldn’t be able to use it, you’re doing something wrong.
After all, for the most part, we don’t demand that our end users go through a convoluted sequence of steps to do something. It is our job and our life’s work to automate and simplify for our user base. So, why should your fellow programmers–also your users in a very real sense–have to deal with convoluted processes? Design your APIs and class interfaces with the same critical eye for ease of use that you do the end product for your end user.
One good way to do this is to use people new to the group as ‘testers.’ They haven’t had time to learn all of the quirks and warts of the software that you’ve lived with for months or years. So ask them to code up a simple addition to it and see where they get snagged and/or ask for help. Then, treat this like QC. When you identify something unintuitive to them, refactor until it is intuitive. Mind you, I’m not suggesting that you necessarily take design suggestions from them at that point any more than you would take them from a customer who has encountered sluggishness in the software and has ‘ideas’ for improvement. But you view their struggles as very real feedback and seek to improve.
Other helpful ways to combat the Keepers of the Tribal Knowledge Culture are as follows:
- Have a specific part of code reviews or even separate code reviews that focus on the usability of the public interfaces of code that is turned in.
- Avoid global state. Global state is probably the leading cause of weird work-arounds, temporal coupling, and general situations where you have to memorize a series of unintuitive rules to get things done.
- Unit tests! Forcing developers to use their own API/interface is a great way to prevent convoluted APIs and interfaces.
- Have a consistent design philosophy and some (unobtrusive) programming conventions.
- Enforce a pattern of using declarative and descriptive names for things, even if they are long or verbose. Glancing at a method, GetCustomerInvoicesFromDatabase() is a lot more informative than GtCInvDb(). Saving a few bytes with short member names hasn’t been helpful for twenty years.