The goal of this document is to provide some reasoning behind our engineering strategy. If you prefer to read about the what rather than the why, please check out Picnic Engineering - How we work.

<aside> 💡 If this interests you, please check out our available roles at Careers at Picnic!

</aside>

Tactical vs Strategic Programming

<aside> 💡 Instead of just shipping working code, we should spend 10-20% of our engineering time on strategic investments.

</aside>

One of the biggest trade-offs in software architecture is between flexibility and stability: we want to have the flexibility to add, change and remove features as quickly as possible, but we also don’t want to break any existing code.

If we only focused on flexibility, we could just throw code anywhere: this would help in the short term, because we could ship the new stuff immediately. But as we pile on more stuff, it would get more and more difficult to figure out which code is responsible for what behaviour (or bug!). The codebase eventually evolves into a Big Ball of Mud, with code all over the place, tangled together.

This becomes especially tricky when finding bugs: changes in one place can (and very often will) affect code in other places. Untangling these can often take much longer than the time it takes to simply write the feature.

The key principle here is that working code isn’t enough: we must not introduce unnecessary complexity in order to finish our current task faster. Instead, our goal should be to produce a great design, which also happens to work. This is strategic programming, a concept from John Ousterhout’s A Philosophy of Software Design, which is essential reading for every engineer starting at Picnic.

Strategic programming requires an investment mindset. Rather than taking the fastest path to finish your current project, you must invest time to improve the design of the system. These investments will slow you down a bit in the short term, but they will speed you up in the long term.

Untitled

Ousterhout, John K.. A Philosophy of Software Design (p. 15)

However, some engineers love spending time “sharpening the axe” rather than actually shipping features. As an early-stage startup, we need to be extremely pragmatic about where we spend out time. Ousterhout suggests spending 10-20% of engineering time on strategic investments.

In some environments there are strong forces working against the strategic approach. For example, early-stage startups feel tremendous pressure to get their early releases out quickly. In these companies, it might seem that even a 10–20% investment isn’t affordable. As a result, many startups take a tactical approach, spending little effort on design and even less on cleanup when problems pop up. They rationalize this with the thought that, if they are successful, they’ll have enough money to hire extra engineers to clean things up. […] once a code base turns to spaghetti, it is nearly impossible to fix. You will probably pay high development costs for the life of the product. Furthermore, the payoff for good (or bad) design comes pretty quickly, so there’s a good chance that the tactical approach won’t even speed up your first product release. Another thing to consider is that one of the most important factors for success of a company is the quality of its engineers. The best way to lower development costs is to hire great engineers: they don’t cost much more than mediocre engineers but have tremendously higher productivity. However, the best engineers care deeply about good design. If your code base is a wreck, word will get out, and this will make it harder for you to recruit. As a result, you are likely to end up with mediocre engineers.

Ousterhout, John K.. A Philosophy of Software Design (pp. 16-17)

This provides a good answer for how much time to spend on strategic engineering investments, but where should we be investing?

The single most useful decision-making framework for engineering decisions doesn’t actually come from software engineering, but from ‘real’ architecture: the idea of shearing layers, a concept introduced by Stewart Brand in his book & documentary series How Buildings Learn.

Shearing Layers (aka. Pace Layers)

Untitled

[…] [Buildings] have different “shearing layers”, and each layer changes at a different speed: Site, Structure, Skin, Services, Space Plan, and Stuff.

The Site is the hardest to change; it is pretty much defined by the land itself and the legally defined lots.

The Structure remains in place from the time the building is constructed—the foundations, and the main load-bearing elements like columns and beams. It is possible to change the Structure, but usually only at great expense, and it takes time and a lot of skill. Good structures, when maintained, have a lifetime of centuries. Bad structures, only a few decades.

The Skin is the exterior surfaces. Paint, shingles, fake or real bricks. Those have a lifetime of a couple of decades and need regular maintenance or replacement.

Services are the electrical wiring, communications wiring, ducts, plumbing, air conditioning, and moving parts like elevators or escalators. They all need regular maintenance or replacement.

The Space Plan is the interior layout—walls and windows, floors, ceilings, doors. People regularly change them. A good structure allows them to be changed easily.

Finally, Stuff is the things we interact with daily: furniture, things hung on the walls, and all the paraphernalia in our living, working, and leisure spaces. It’s easy to move a bookcase or a table to a different place: it is very feasible to experiment with various configurations in a short time until you end up with one you like. That kind of experimentation is hard to do with Skin if you are just a dweller (Do you have the skills to lay tile?), and much harder to do with Structure (Do you have the money to tear down a wall and build a new one? Do you have permission to do it?).

From https://recompilermag.com/issues/issue-4/legacy-systems-as-old-cities/

When applied to code, we obviously won’t talk about bricks or furniture, but this metaphor stretches surprisingly far. It’s often useful to talk about the lower layers more generically as the core.

Shearing layers provide a useful framework for many important engineering decisions:

What technologies should we use?