Search on TFTC
Invariant 2: Don’t Design Without a Strategy

Invariant 2: Don’t Design Without a Strategy

Jan 3, 2024

Invariant 2: Don’t Design Without a Strategy

In Invariant 1: Think, Then Do, we ended up with a strategy document of some kind. This strategy has been vetted by the team, and everyone remembers the snappy calls-to-arms, knows the general direction to take the product, and how to tell if the product is winning or not. So it’s time to write some code!

What the hell-no-what is wrong with you? We’ll get there, but we still have to do some thinking. Don’t Design Without a Strategy aligns with the Discovery atomic unit. The one that states: Iteratively figure out exactly what we want to build, and how it’s going to work in very specific detail. We know we’re ready to figure out exactly what to build 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. Well, we have a strategy, so let’s get to designing.

Figuring Out Exactly What to Do

That line carries a lot of weight. What do we mean exactly? And how do we know what’s enough? Also, knowing exactly what to do seems to imply a LOT of inputs from designers, product managers, researchers (if you must), programmers, and customers. 

The Discovery phase is the busiest of the five phases. It’s hyper collaborative, and super dangerous, because it’s the easiest phase to get lost for long periods of time. Finding out exactly what to do is hard, and it does involve all of those people listed above and more. The best way to start the Discovery phase is to define what the output at the end of discovery is, which is a spec and a schedule. This is where a spec means all the functional specifications required, all the technical specifications required, and all the designs required to make the actual building of the software straight forward. And where schedule means a detailed understanding of the requirements and how that affects the code base so that an engineering team can estimate down to the day of when the software could be released. So if the end output of Discovery is to produce a spec and a schedule, what might all these people be doing in Discovery? Here’s a list of things that always and sometimes happen in Discovery:

  • Customer research
  • Usability testing
  • Competitive research
  • Data analysis
  • Design patterns
  • Mockups
  • Prototypes
  • UX workflows
  • Demos (internal and external)
  • Data model visualizations
  • Shaping
  • *Functional spec writing
  • High fidelity designs
  • Technical specs
  • *Schedule

*Always happens.

The reason we say Discovery ends with a spec and a schedule is not because other artifacts won’t necessarily exist, it’s just that we always have a spec and a schedule if we are writing code. 

That’s an overwhelming amount of things you could be doing, which is why we fall back onto Invariant 2: Don’t Design Without a Strategy. You have a strategy, and as we learned in Invariant 1: Think, Then Do, one outcome of the strategy is that it narrows down the range of acceptable software solutions to the strategy. That narrowing down should give the product team a pretty good sense of the size and risk of the project. If it isn’t intuitive, those product and engineering leaders should start with figuring out the size and risk. They should ask themselves:

  • Are we inventing something new?
  • Have we done something like this before?
  • Do we already have the expertise to execute on this in house?
  • Will this introduce any new dependencies into our code base?
  • Does this require major changes to the data model that will require a migration?
  • Will we be relying on outside forces of any kind to execute?

You may be asking yourself how to answer these questions if we haven’t defined in precise detail yet what needs to be done. I reject this paradox. We are not meant to get everything right yet, we’re just starting out, and as reasonable people (or salmon) we can come back to this if the process unfolds differently. So do it to the best of your ability early because your answers are going to determine how many of the things you could do during Discovery, you’ll end up doing as part of the designing phase.  

If you’re inventing something new, need to pull in outside expertise to execute, and are going to make major changes to the code base, you’re operating in a high risk building environment. With these high stakes, you’ll do more of the things above than if you’re not inventing anything new. If you have a pretty straightforward goal, know that something similar is working in the market, and have the team to execute, maybe you only end up with a simple functional spec and engineering schedule. Research be damned.

Quick Aside:

One thing I’ve done for years now that I stole from someone who probably stole it from someone else is a very quick exercise called Core vs. Context.  In this exercise Core means something that will help you win in the market. Context means something that, even if necessary to make the product work, is not going to help you win in the market. You can use this framing when prioritizing multiple features, or when trying to time box an individual feature. An example from Zaprite may look like:

  • Zaprite is trying to fulfill a strategic goal of expanding into e-commerce from solely doing business invoicing. As part of the expansion into e-commerce, we have to update reporting for the new use case. Merchants selling things online have slightly different needs from people sending out business invoicing. Ok, these reports obviously need to exist, but are they Core or Context?
  • Well, I have an idea, run it by my colleagues, and make a case for why I believe it is necessary but not differentiating. I then run it by a few customers and prospects, and confirm my initial instinct. These reports are context.
  • Now when I’m getting through Discovery, I’m not going to do a bunch of UX research, spend time on prototypes and demos to customers. I’m going to write a good spec, negotiate a time frame to actually build on this (the engineering schedule) and move on.

Outside of this series I’ll likely go down the list of every single thing you could do in Discovery and how to do it well, but for now, I’ll focus on just the things that we always need to do: specs and schedules.

Specs and Schedules

While I have a lot to say on functional specs, I’d like to point to two very different ways of spec’ing that have influenced me greatly. 

Joel Spolsky - Painless Functional Specifications - This multi-part series goes into very specific detail on how to create very specific specifications. I follow roughly this model when words are enough, when I don’t have a designer in house to work with, or when I’m extremely opinionated in what I want to be built.

Ryan Singer - Shape Up Chapters 4,5,6 - In Ryan Singer’s Shape Up, Find the Elements (chapter 4), Risks and Rabbit Holes (chapter 5), and Write the Pitch (chapter 6) roughly align with what I mean by creating functional specifications. That is, find out exactly what to do. Shape Up is a bit different from the way I do most functional specs in that I like to have high fidelity designs before writing a lot of code. But again, it’s a rough mapping and I worked this way prior to Shape Up’s publishing, but appreciate the style immensely. 

With those influences out of the way, I’ll provide a simple definition of a good specification: a visual artifact with enough detail that:

  1. The author gets all the functionality they wanted when the project is completed in the Build phase.
  2. The author gets no functionality they didn’t want when the project is completed in the Build phase.
  3. Engineers are capable of reading the spec, and accurately estimating the time it will take to build.

If you can check those three boxes after the project is done, chances are you wrote a good spec. The reason I linked to two very different ways of getting to a “spec” artifact is that there are many ways to check those three boxes. If you can check them, it is valid.

If you’re the person responsible for writing specs, typically you’ll be called something like a Product or Program Manager, and you should view yourself as a handyman. Yeah, the guy that comes to your house and can fix your toilet, solve an HVAC issue, and can do lots of things with grout. Your spec customers are the designers and engineers actually designing the pixels and writing the code. They’ll be more productive in different circumstances, they have different personalities and abilities, so you should have several tools in your tool belt to get to the same result, a spec.

Example Spec

Let’s jump back to Zaprite and our report. That’s the one we decided was “context”. It’s a good example because it’s short enough to read, but you can get a good sense of what it would look like even if it were a core and more complex problem.

Transactions CSV Updates

It’s ok if you’re mildly underwhelmed by this example. The context of this spec is that it is a very small feature, and really it’s an update to an existing feature based on the expansion of the Zaprite product into e-commerce. It is, however, very detailed. This is actually the first version of the spec. There were 5 or 6 async comments made by a designer and engineer for me to clarify a few of the columns, and to correct a couple of errors I made. The engineer helped me avoid some semi-serious mistakes I made in column R based on a misunderstanding I had about whether Invoices only had an Invoice Number and not an Invoice + Order Number. It’s all kind of tedious stuff, especially in your shoes, but it was a very effective spec. I was able to correct those errors, and the engineer was able to tell me what day he’d have it done by. From beginning to end, this particular product went from Discovery > Delivery in about 3 days. We already had the strategic case made that would include this type of work.

Where you could see this spec being expanded in a larger product or feature would be:

  1. Links to related documentation. Related features, research, designs etc… that would help bring context and understanding for the engineer implementing.
  2. Designs (although in this case, the linked CSV serves as a sort of design)
  3. Multiple phased work. IE: do part one, then part two, then part three 
  4. Detailed customer UX flows if not a part of a single page app
  5. Very detailed testing plan that included new funnels, tracking, etc… to know if the feature was working.

However even if it were more involved, it would still essentially read like this. I would be remiss if I didn’t mention how important detailed designs are, and how interlinked are designs and specs. I even called this “Don’t Design Without a Strategy” because I consider designs and specs to essentially be the same thing. In this case, we didn’t have many pixels to change, but the spec is still a design. In other cases, you’ll be changing the visual experience of a product and not have to write as many words. The design is the spec, the spec is the design, and Finkle is Einhorn

Quick Design Aside…

I’ll write more on the process of design in the future, but I’d like to provide a few quick hits for the purposes of this series:

  • I almost always start with a design pattern (yeah I like Ryan Singer). The only thing I don’t do, is I almost never deliver the sketches as described here unless I really really know what I want and want to bias the designer in a massive fashion. 
  • Collaboration with designers on early versions of the spec is important. Oftentimes I’ll do the design pattern before writing a V1 of the spec, and have two parallel working flows with a designer while I’m writing the spec.
  • As it pertains to primary UX and UI, I prefer a critical back and forth between the spec author and designer as the spec and high fidelity designs are being developed.
  • As we converge on a final version of the spec and design, I want the designs to be present in the specification. One artifact that has both elements.

…Back to the Example

There is other interesting history to this rather mundane looking spec. I wrote this a few months ago (from when this is being published), but these aren’t all my ideas. As best I can recall what happened was:

  1. We launched Payment Links, a major strategic move for Zaprite into the bitcoin e-commerce payments world.
  2. I demo’d, or at least spoke about Payment Links at the Austin Bitcoin Club.
  3. Several people brought up some of the reporting issues they had with other solutions and wondered if we had fixed them with Payment Links (we hadn’t).
  4. Several Zaprite employees confirmed the concerns of those prospects at Austin Bitcoin Club with current customers.
  5. The engineer that was to work on this feature gave me and the designer an ear full of what he thought of the current state of the report, things he thought were poorly named, and ways he thought we could get some of the new stuff in without a lot of trouble.
  6. Our head of Biz Dev/sales who sat next to me told me what he thought we should call the new columns. 
  7. I couldn’t remember all these fancy names, so opened up a spreadsheet, and we together created the example CSV linked to in the spec.
  8. I wrote the doc based on all the inputs from prospects, customers, designer, engineer, and biz dev person.

In this very simple example, we ended up doing a LOT of the things you would do for a much bigger feature or product, but it was condensed in time spent because it is a relatively small piece of software being built. The end result, a 2 page document with only one joke that was easily estimable and measurable. Success.

Example 2: Specificity Seriously Matters

My dad is a software engineer. He also was one. Back in the 1980’s he got a contract to write software for a large client. His little software consultant shop was hired to write software that would select from an employee database who and when was to be drug tested at the client company. It was important, the client had employees operating heavy machinery, and there had been accidents. 

Arrangements like this didn’t start with a “spec” per se. They often never got a spec at all. But they did talk an awful lot, and my dad’s company being the professionals they were, wrote their own spec. The requirements gathering would look something like this.

  • (Consultant) - Who from the employee database is eligible for drug testing?
  • (Client) - Everyone who is marked as operating machinery, and the entire roster of executives (to show solidarity).
  • (Consultant) - How often do you want to drug test each eligible employee?
  • (Client) - We want to do drug tests every week on a Wednesday. We don’t want to necessarily drug test each eligible employee, we want it to be random.
  • (Consultant) - Got it. So you’re OK if the CEO of the company gets drug tested six weeks in a row?
  • (Client) - No we don’t want that at all, we want it to be random.

(Four day discussion about the nature of random ensues.)

This actually happened, and it is not a failure case. Figuring out exactly what to do, which is the whole purpose of a spec, is difficult and sometimes tedious, but absolutely necessary. If the consultant here, my dad, had not hashed out the meaning of random with the client, the CFO would have been drug tested three weeks in a row and he would have thrown a fit. Who the hell runs this drug testing software and why the hell have I been targeted? The internal tech team would come back to the consultants and chew them out. Why is our CFO being treated so poorly by your system? Didn’t we tell you this was supposed to be random? And then a four day discussion about the nature of randomness would ensue, and the software would be updated. And everyone would congratulate themselves because they had just discovered the art of agile development 20 years before the agile manifesto. Probably not that last part though. My dad’s consulting firm would have likely been fired.

I believe these types of arrangements, consultants working as an outsourced development team, is why we got “agile” to begin with. But I’ll save that theory for later. The truth is that even in the 80’s, and even in outsourced arrangements, companies like my dad's were already building in an agile manner, iteratively shipping software to their clients, but they knew to Think, Then Do, and Don’t Design Without a Strategy. In this example, the entire success or failure of the product, and therefore the contract, rested on the definition of a single word. A good spec will get to that level of detail, and the road to success is to not debate that definition in the codebase. 


When it comes to schedules we should get something out of the way first. It matters how long it takes to build things. Like a lot. In many cases of building software, how long things take is the primary factor in how much something costs, as the salaries of those building it are the vast majority of the expense of bringing the product to market. I know it’s a trope that engineers don’t like setting schedules, and that it’s an impossible task, and that John Carmack was famous for saying: “It’ll be done when it’s done” and he’s the most successful game developer ever so to hell with your schedule we’re building stuff here screw off.

First, John Carmack “largely recanted” the idea of not having a set schedule, and suffered tremendously for not doing so sooner. Second, we’re all grownups here right? It’s a decidedly un-grownup thing to do, to not attempt to figure out how long things will take and how much they cost. I also know where engineer reluctance to setting schedules comes from. Bad and changing specs. Bad and changing specs make the process of estimating literally impossible. I mean literally like a grownup, not literally like my niece. Where a bad spec may be under or over specified, a changing spec (while Building, we’re supposed to change specs in Discovery) just means that whoever wrote it never read this blog series and doesn’t know what they’re doing. So for the sake of moving forward here, we’re going to assume a reasonably good spec has been created when discussing schedules. And in this world of good specs, schedules are possible.

There are many ways to get to an engineering schedule, but what they all have in common is that they require a mastery of understanding of the requirements in a spec, as well as a mastery of the codebase to achieve. Asking someone to estimate with precision who has never looked at or worked in the area of the codebase that will need to be changed or added to is not going to go well. If it is the case that the engineer is unfamiliar with the area of code to be worked in, we’re going to cheat a little bit. We may need to write some code (the horror). I don’t believe in zero-tolerance, and while it is advisable to not write code before finishing with Strategy and Discovery, we may need to code a bit to show mastery of the spec and mastery of the codebase in order to produce a reliable schedule. Unfamiliarity may be the impetus in most cases, but really anyone with the task of estimation would be well within their rights to interrogate the code base and make some changes here and there to determine how difficult and how long they’re going to spend coding in the future.

There are loads of ways to to do engineering schedules, but as the Invariants are methodology neutral, I’ll try and focus on the key questions and tactics that engineers should be asking themselves and doing when coming up with a schedule, and not the specific methods of estimation:

  1. Have I done something like this before? If yes, how long did that take me?
  2. Have I worked in this area of the code base before? How long does it take to do things here?
  3. Will this require a migration? Those things tend to take longer than features that don’t require migrations.
  4. Will I have to bring in new libraries or external dependencies? That’s a risk, could require me to interact with outside software teams, and takes longer than if we didn’t have external dependencies.
  5. Will our current infrastructure run this new code without changes, or do I need a new specialized server or a bigger server to run it?

After asking those questions, and considering the written spec, an engineer is likely getting things narrowed down to the days, weeks, months category. Now they can ask themselves:

  1. Is my wedding anniversary in the middle of these days, weeks, months? That would set me back.

But a good schedule isn’t days, weeks, or months. In fact, we do estimations like those (some people call this T-shirt sizing) before we even have a spec. What good engineers almost always do is break things down into even smaller chunks: hours. 

They’ll go through a spec and with every requirement and task determine how many hours that would take them. Four hours here, nine hours there, two hours for the tests on this one etc… They know they usually have 4-6 hours to actually write code on any given day, as long as the product manager isn’t bothering them with meetings about meetings, and so for this spec with six requirements and a break down of 2,3,1,4,1, and 5 hours, they can complete this in 16 hours, or 4 days. They know sometimes they get 6 hours of coding in, but everyone would be happy if on day 3 they announced it was ready to be tested, but wouldn’t be so happy if on day 4 there was a problem, and a meeting for why the feature was not ready to be tested was scheduled, and it was actually going to be 6 days to account for the meetings about why it wasn’t ready in 3. So they’ll say 4 days because that’s a reasonably safe bet without sandbagging.

During this process of breaking down a spec, interrogating the code base, and maybe even writing a bit of code, the engineer is going to have questions for the spec author. Those questions could lead to clarifications or changes in the spec. They could even cause changes to the strategy. That’s good. That’s iterating through a problem. That should happen 95% of the time, because engineers know a lot about building software, and should have an impact on specs and strategy. Hopefully by this point, the engineer was well represented in the previous phases and these changes are rather small, but if they weren’t and the changes are big, the changes MUST HAPPEN before we all move to Build. Because without a schedule, we aren’t ready for Build.

At the end of this process, the engineer has broken down the tasks into small chunks of hours of work, and built it back up into days or weeks to execute. If it’s months, you should seriously consider breaking up the spec to make it smaller. That means we have a DATE. An actual day, like December 25th, no not that one, but like December 19th, where the rest of the product team should be prepared to start testing the completed code. So you really have two artifacts that emerge from a schedule:

  1. A list of tasks broken into hours of work. This is typically tracked in some sort of kanban board or project management software.
  2. A date the code will be done and testable.

The date is not a shipping date, and the tasks are not a spec. They are solutions to problems lower down our layers of abstraction.

On that note we’re also lower down on the layers of abstraction, so…

Please Sir, May I Write Some Code

Do we have a spec? Do we have a schedule? Yes, we can start building and writing code. Which brings us to Invariant 3: Don’t Build Without a Plan, coming soon.

Originally published in Tools of Ignorance


Current Block Height

Current Mempool Size

Current Difficulty