In Invariant 2: Don’t Design Without a Strategy, we ended up with a spec and schedule. We could have ended up with a number of other artifacts, but we at the very least ended up with a spec and schedule. That spec and schedule means you have a PLAN, and if you have a PLAN, you can write code. That leads us to Invariant 3: Don’t Build Without a Plan.
When I was at Stack Overflow, we were a bit more on the nose in how we described Invariant 3. The incantation for the product team was: NO CODE WITHOUT A SPEC AND A SCHEDULE. We believed this so much that there was a recording of Joel Spolsky, with major Auggie Garrido energy, repeating the line over and over. No code without a spec and a schedule. Don’t Build Without a Plan.
If you’ve spent your career working in startups, this invariant may seem sacrilegious. If you’ve spent your career working in mid-to-large sized companies, this Invariant may strike you as the most necessary. And this makes sense. If you’re a small startup, under 10 people, the fact that the plan can take longer than the coding could cause your early dev team to have dreams of mutiny. You may not have anyone on the team that has ever written a spec, and the 26 year old CTO may have never had the discipline to sit down and figure out an engineering schedule. You convince yourself it’s not worth it, and at this size, you’ll sometimes get away with it. With fewer than 10 people, you can essentially rely on telepathy. Until you can’t. Then you’re in a seriously bad place. Best you do a good job of this before the telepathy bandwidth runs out.
Don’t Build Without a Plan lines up with our Build atomic unit. The one that states: Actually implement the thing you designed in the discovery phase with lines of code. This should be the easy part. I say this should be the easy part because for many teams who don’t build software in an opinionated way, this is the hard part. The reason this is the easy part on my teams is because we are following the most important concept in understanding the invariants, which is to solve problems at higher levels of abstraction before we move to problems at lower levels of abstraction. This is not to trivialize the complexities of writing code, only to show that it’s relatively easier to write good code if you have a strategy, a spec, and a schedule in place.
If the Build phase is all about writing code, then what exactly is everyone else doing? Let’s start with what they’re not doing. What they’re not doing is:
You know that scene in the The Social Network, where the guy who plays Mark Zuckerberg is speaking to Justin Timberlake who is pretending to be some other guy, and the guy playing Zuckerberg keeps telling people not to bother one of his developers because he’s “wired in”. I remember that scene coming off as corny, but it’s a powerfully real thing.
If you’re not a programmer, or are like me and haven’t programmed professionally in a very long time, it may strike you as odd that interrupting a programmer is such a taboo. If you were a novelist, or did some other form of deep writing it would seem intuitive. When someone is programming, oftentimes the time spent on the problem is the most important part of making progress. And that time gets progressively more valuable when it comes in chunks of uninterrupted focus. A programmer is more productive working on a problem after 30 minutes, than they were in the first 5 minutes, and after an hour and a half of uninterrupted time, they can see the matrix in its entirety. Time on target matters because programmers are using RAM in their brain that takes time to fill up with the useful stuff. This stuff helps them navigate the complexities of the codebase: changing stuff here has affects over there, this test needs to be amended to cover my new thing here, and let me build a firewall around this ungodly regex that if I touch, could shut down the county substation for some reason. This could build up to dozens or hundreds of files and linkages in some cases. When the programmer is interrupted (even a simple tap on the shoulder), the risk is that all that RAM gets dumped and the programmer has to build it up again from scratch.
The point is, don’t sit around doing nothing, and for the love of god don’t bother your engineering team. They’re wired in.
Pipelining
What you should be doing is pipelining. You’re always somewhere in the flow of the 5 atomic units. Most of the time, we want to be in a rapid loop of Discovery, Build, and Delivery. With that said, not everybody on the team has the same amount of work to do in each phase. Without being too precise about it, the following table is a rough approximation of how much time people on each team spend on each phase:
If the entire team works in lockstep, strictly doing discovery together, then build together, then delivery together, you get these very quiet periods for developers who are sitting around waiting for specs to arrive, after which you get these very quiet periods for PMs who have given their specs to developers and are waiting for the code to get built etc… Since we don’t want our highly paid tech team sitting around waiting for eachother, it benefits us to be able to build a system where all of these things are happening simultaneously.
Pipelining allows individual team members to spend their time where they are most impactful. Sometimes, that means while engineers are building, PMs are working on entirely different features or products, prepping for another build cycle. Sometimes that means that marketers have 90% of the assets they need to train their sales team, and build their go-to-market plan on the current project, and don’t need to wait for Build to complete to finish prep for Delivery.
The DevOps team realizes that once this thing is ready, they’re going to need a beefier server, and can get ahead and set it up now.
While there’s nothing particularly revolutionary about pipelining in this fashion, there is a price to pay– a coordination price. So while the PM may have work to do on delivery for this feature, or discovery on an entirely different feature, they’re still on the hook for keeping everyone informed with information and for deploying effort efficiently so no one is waiting around. This isn’t the 90’s where we all take coffee breaks while we write code and wait for it to compile. We’re doing lots of stuff here, just not bothering the people who need absolute focus.
Now about those people we’re not bothering…
Touché. We are at a point where I have less advice because I’m one of those guys buzzing off to another phase in the process while the code is being written. However, I have worked with hundreds of programmers at this point, so indulge me just a bit on how you, Mr. Programmer, can do a great job in the Build phase while working with someone like me.
So let’s take for granted that you’re working with me, and I know how to leave you alone. This doesn’t mean you get to disappear for three weeks. Here are some things that you should always be doing, and sometimes be doing, when you’re not wired in during Build:
So yeah, I have no grand advice to make you a better programmer. You can do that on your own. But what I have given you to this point is a major voice in all the thinking that goes on before we write code–a fabulous spec, a schedule you set yourself, and some peace and fucking quiet to do your work. You’re welcome.
This feels like as good a place as any to center ourselves on a very important modality. Are we iterating or are we incrementing through a problem? The answer will have an effect on both Discovery and Build, but the dynamic in Build is so vastly different if you’re incrementing vs iterating that I feel it’s best served to discuss here.
In Invariant 1: Think, Then Do, the title image was from Jeff Patton’s extraordinary post from 2008, Don’t Know What I Want, But I Know How to Get It. In the post, he defines iterative and incremental development as:
“By incremental development, I mean to incrementally add software a time (sic). Each increment adds more software – sorta like adding bricks to a wall. After lots of increments, you’ve got a big wall.
By iterative development, I mean that we build something, then evaluate whether it’ll work for us, then we make changes to it. We build expecting to change it. We never expected it to be right. If it was, it’s a happy accident. Because we don’t expect it to be right, we often build the least we have to to then validate whether it was the right thing to build.”
Both modes of working are completely valid. However, it’s vitally important that you know what mode you’re employing well before you exit Discovery. Why you ask?
Incremental Development
Iterative Development
Iterative development is not without structure and doesn’t live outside of the Invariants or the five atomic units. It just necessitates more communication and cycles between Discovery and Build. Incremental and Iterative development are not good or bad. They are both useful if you recognize what mode you’re in on any project. So how can you know what mode you’re supposed to be in?
Incremental Development
Iterative Development
The Invariants are of course methodology-neutral and are flexible enough to deal with changes in working style like Iterative vs Incremental development. However, the expectations of how Build and Discovery play out are dependent on the software team coming to an agreement before Build begins on whether you are Incrementing or Iterating.
So how do we know Build is “done”? We know it’s done when a programmer or team rings a bell, @here’s a Slack channel, or stands up and triumphantly announces: “Finished”. I’m not kidding though, it’s done whenever the programmer says it’s done.
As far as validation goes, once the feature or product is done, we want to check our engineering schedule and see how we did. Right on time? Early (hey, it’s happened .05% of the time in my experience)? Or Late? This is good information to have when the team does a retrospective or something similar in the future. Keep score and you’ll get better at setting schedules.
As far as accountability goes, we have an Invariant just for checking our work in Discovery and Build. It’s called QA, and everyone should do it all the time. However, really good programmers and product people stack the deck in their favor before QA starts. PMs, designers, and programmers will secretly test their own work, making sure it meets all the requirements as well as looks and performs the way they anticipated. They do this because it would be super embarrassing if the spec said that a button should be green, labeled “Submit”, and saves profile updates but instead was blue, labeled “Enter”, and didn’t save any changes. Whether you have dedicated QA people or not, the process of QA should be more challenging than that. Speaking of…
We’re close, so close. But before we do, we need to follow Invariant 4: Do What You Said You’d Do, coming soon.
Originally published in The Tools of Ignorance