Culture is the Spec; Process is the Code
A while ago, Yehuda Katz tweeted the best thing I’ve ever seen about tech management.
I thought of this as just a pretty good joke for a while, blending the messiness of management with the classic software joke-rule Greenspun’s tenth rule.
But then I had a few enlightening conversations with Noah Brier, co-founder of Percolate. Percolate is experiencing enviable success and growth, but the thing that’s really impressive to me is their documented culture, which features ten values that Noah and company have sweated to produce. It’s not just a list of pretty things to say. According to Noah, every item on the list should be something a viable business could disagree with and still achieve success. It’d be pretty dumb to do the opposite of every item on the list, but this litmus test has produced a document that helps people at Percolate make hard decisions that they come across every day.
This did not happen by mistake. Noah is actively applying the tenets of software creation to the creation of his company.
And that led me back to Yehuda Katz, and that informally specified, bug-ridden implementation of management.
What you’re looking at above is not a pretty list of values that’ll get thrown out (ahem) when they no longer suit the ambitions of the company and its shareholders. What you’re looking at is a functional spec.
A documented culture is the spec of your organization. If you’ve ever written one or read a good one, you’ll start to see the similarities between documenting your culture and writing a functional spec. I find the analogy goes quite deep:
- If it’s communicated informally, especially verbally, you’ll end up micromanaging your way to a poor result
- Once written down, it can look obvious
- The spec is an artifact of choices that seemed easy until you had to reason them out in writing
- The work of writing it down is the work of settling arguments in advance
Let me explain that last one.
Settle Arguments in Advance
When you write a functional spec, you often stumble on situations that seemed obvious until you got right on top of them. Until then, it seemed like a straight shot, but now you realize there was a fork in the road, and it’s not obvious which is the better path. It’s the exact same thing writing down your culture.
When you go to write these tenets down, the process can feel stilted or obvious, especially when everyone already “gets it.” You end up with a list what look like platitudes. That’s fine, because it’s a starting point. The next step is to refine that list until it’s useful. Edit it until each item answers a hard question like:
- Should I bug the founders about this? I don’t want to be seen as a complainer and I’m sure they have other Important Things to consider
- Should I ship this feature if I’m not 100% sure it’s bulletproof? I don’t want to ship bugs and get yelled at
At Fog Creek, we have a publicly documented culture on our blog and in co-founder Joel Spolsky’s corpus of essays. But we also have a simple list that we go over at every company meeting, it’s just a distillation of the tenets that Fog Creek was founded on.
We write this stuff down so people don’t have to check with their boss (or anyone) every time they have to make a decision, and they’re only useful if they help us make hard decisions. Hard decisions are where you have to sacrifice one important thing to get another important thing. Getting information to the right people vs. navigating politics. Money vs. customer happiness. Getting features in the hands of customers vs. delaying and making them perfect.
Here’s a selection.
Everyone is available to everyone.
We have a flat organization, and everyone including the founders has enough time that they can listen to you. We do this to dispel the natural human tendency toward hierarchy, and to facilitate the flow of information in the organization without a bunch of standing meetings. The opposite of this is “go through the correct channnels to not ruffle feathers.” It’s a perfectly fine way to run an organization filled with humans, but we’d rather pay the ruffled-feather price to get the information flow.
We don’t want your money if you’re not amazingly happy.
A new employee faced with a dissatisfied customer is being put to a hard decision. Money is important, particularly for a bootstrapped startup, and customer happiness is important for any business. Which one wins? Well, there’s your answer in black and white above. If a customer is not amazingly happy and you give them their money back, no one is going to yell at you.
File a case.
If you want to get something done at Fog Creek, you file a case. Having a case filed against you is not seen as aggressive. Rather, it is respectful. It respects that you have a decision-making and prioritization process, the nuances of which I cannot possibly understand. Filing a case means that I submit to your tangle of competing priorities rather than trying to jump the queue and get you to do something because you like me (or I’ve been here longer, or I’m your boss’ boss). It forces me to reason out in writing what I view as success, so you have a snowball’s chance of making me happy. It allows you to reflect at leisure on how (or whether) you might go about implementing my vision of success.
Does any of this sound familiar? It should, because the hidden message in “file a case” is “write a spec”. Each case is itself a specification for your vision of success.
If you file a well-documented case and trust the assignee to handle it, no one is going to yell at you.
If you see something broken, fix it.
If you ship a new FogBugz feature and there’s a bug in it, no one is going to yell at you. They’re going to fix your bug and move on. By the same token, if you see a bug in someone else’s code, you don’t need to worry about stepping on their toes. No one is going to yell at you. Just fix it.
This might not look like a controversial thing. Who could argue with fixing broken stuff? But as part of our cultural spec, it helps in a very clear way: it prevents fiefdoms. If I see a bug in “your” code and I fix it, I know I’m not going to get yelled at. I don’t need to ask permission or forgiveness for mucking about with “your” code. This helps to answer the hard questions that arise when you see something potentially broken:
- Do I walk on by and leave it for the “people in charge” of this to fix?
- Or do I gingerly approach you and ask if this is the way you intended it to be, thereby possibly calling into question your competence?
- Or do I just fix it?
The answer is: you fix it.
How do you go about “fixing it”? Well, just file a case, fix the bug, write a test, create a code review, and move on.
Wait, What Just Happened?
One moment we were talking about “just fix it” and now there’s all these extra steps involved with code reviews and such. Didn’t we want to keep this simple? What’s up with all this new process, man!? This place is getting too corporate!
Just as the spec for your app is not the same thing as the app itself, the documentation of culture is not the culture itself. Software is implemented via code. Culture is implemented via process.
I’m no fan of process for process’ sake. If you find yourself in an organization where people actively resist new process, count yourself lucky. To me, that’s no different than a dev team that actively resists writing new code until it’s abundantly clear what it’ll do and why. In other words, a dev team that demands a spec before they’ll open an IDE. If you have a team that implements process or code without serious consideration about what it’s for, you’re quickly going to get into a Bad Place.
If your team resists all process for fear of becoming corporate, that’s like resisting writing any code because it inevitably leads to technical debt.
The whole Minimum Viable Something thing has been done to death, but I’m going to go there anyway. I suggest minimum viable process.
Minimum viable process means finding the bare minimum you can do to satisfy an emerging requirement, implementing it as independently as possible, and living with it for a bit. The tiniest bit of process can have far-reaching effects, some of them in line with your culture, some of them mildly against it. You won’t know all the follow-on effects until you’ve lived with a basic process for a while, sometimes for years.
Most importantly, every tiny little process you put in place should be defensible according to your documented culture. Every line of code should be supporting a feature called for in the spec.
Here’s an example:
At Fog Creek, we have a longstanding process (implemented in a few dozen lines of Python) of farming out cases to support engineers via lottery (rather than round-robin or self-selection). Frankly, I originally implemented it this way out of laziness; round-robin requires storing state (the last person we assigned to) and I wanted my script to be self-contained and stateless.
So I just used randomness, relying on the law of large numbers to make it fair over the long haul. The cultural tenet that defends this process is, perhaps counter-intuitively, “If you see something broken, fix it.” The corollary to that tenet is, “Nothing is no one’s job.”
This tiny bit of process has many cultural ramifications and follow-on effects:
- We all agree that getting through the whole queue every day is all our jobs and therefore doling it out equally is unnecessary. This reinforces our core belief that the shared responsibility of teamwork starts with personal responsibility.
- Randomness is not fair, so one engineer will sometimes get a large share of the day’s cases. We view this as a game-day exercise. GDE’s let you see what happens to a strained or failed system in controlled environment. If one engineer gets half the cases for the day, and the other five get 10% each, the strained engineer will learn to ask for help, and the others will be well-positioned to give it. When, later, the gods of randomness (or deployment) decide to give the company a triple dose of support load, we know how to deal with it.
The script I wrote, called random_assignment.py has been running for five years without significant changes. We had to put in a few features like respecting the vacation calendar and onboarding new hires gradually, but it’s substantially the same script.
We have dozens of these things all over the organization, some automated, some not. But they all connect deeply to our culture, and our culture is documented. When they break, we can refactor them, replace them, or, if they no longer serve us, throw them out altogether.
We do this with code all the time. We have to because it gets so complicated so fast. But somehow when it comes to operations and process, we lose our heads and let it get complicated and emotional. I think Yehuda and Noah are both onto a great idea.
Now we just have to implement it.