A Scandinavian Developer
Published on

How we work

A software engineering team is a constant work in progress. What works today might not work tomorrow. The software, business, and people constantly grow and change, so you need to continuously course correct as things start to break in subtle ways over time.

In the last few months my engineering team has been operating incredibly smoothly. Things just flow, and our day-to-day "vibe" consists of high engagement, strong collaboration, and shipping things quickly. It feels like we're riding on a wave of momentum.

I wanted to write this post to take a snapshot of what's working well for us right now, while acknowledging that things will change over time, as the team grows and the business requirements evolve.


For context: We're a team of 7 full-stack engineers (myself included), working in two "squads" centered around specific business objectives. We're a Growth team (product development focused) working on PLG, onboarding automation, first impressions and self-serve. We write code in TypeScript (React), Scala, and PHP. We're big fans of functional programming, test driven development, and domain driven design.


Inspiration

My main inspiration (so far) when it comes to engineering/product-development primarily comes from two places: The Shape Up methodology and Extreme Programming.

Shape Up introduced me to ideas such as:

  • Fixed time, flexible scope
  • Scope hammering
  • Small but mighty builder teams
  • The benefits of making the builder teams responsible for figuring out the details, instead of defining all the work upfront
  • Focusing on appetite over estimates (how much is this project really worth to us?)

While I'm a big fan of the Shape Up methodology, I've struggled applying it directly in my team (we tried for a while). Fixed time flexible scope makes sense in theory, but in a "normal tech company" it's really hard to drop a project once it's been started (even if it exceeds the original appetite). People inevitably make promises to key stakeholders and the sunk-cost fallacy is hard to shake in practice. Nevertheless, concepts such as scope hammering and letting builders figure out the details as they dig into the problem have proved to be a good fit for my team. Applying these principles creates an environment of high ownership and creative problem solving, which is a good fit for my team since we're a bunch of business minded engineers.

Extreme Programming is what I've been exploring most recently and that exploration has brought me a ton of good ideas. It's impressive how well the ideas have held up over time (the book was written in 1999!). Some of the key ideas that resonated with me and we've implemented in our team are:

  • Super short iteration cycles make your process lean and flexible
  • Pair programming & Test Driven Development make you move faster
  • Delivering concrete customer/business value every single week allows you to adapt to new requirements super rapidly

Principles & Practices

Although I've certainly been inspired by various different methodologies (some of them mentioned above), our team doesn't really follow a fixed methodology. Instead, we focus on picking ideas that resonate, trying them out, and for the ones that work well, add them to our toolbox. What this leaves us with is a set of core practices/principles that we use to guide us in our day-to-day work.

Here are the 6 practices/principles that have been most impactful in the last few months:

Short cycles

Keeping iterations and planning cycles as short as possible allows us to focus intensely on a few important things, and avoid unnecessary context switching. It also maximizes our opportunity to react to new insights and knowledge - we only have to wait until next week to change direction. Almost everything that comes in from the sides (bugs/change requests/new ideas) can wait at least a week. This allows us to go deep on our weekly goals, while keeping planning as light weight as possible. At the beginning of each week, the team gets together for ~30 minutes to discuss top priorities for the week and triage any incoming requests or new learnings.

Show your work

At the end of every week, each "project squad" demo's what they built during the week. This has proven to be a great forcing function to constantly focus on incremental delivery, since it forces us to always keep what we're working on in a demo'able state and (close to) production ready. This leads to less overhead in integrating backend/frontend since we're forced to do it frequently throughout the week. Keeping things in a "production ready" state each week also allows us to ship things incrementally. This is important for many reasons. I believe a core motivator for engineers is to ship stuff frequently, as Paul Graham explains here

Tech companies must keep shipping cool new things or die. Not because customers require it, but because the best employees do. If your best programmers stop being able to ship new things, they'll leave to work somewhere they can.

Besides, it's just really fun to show your work. It's really demotivating when you end up having your work hidden behind closed doors for too long, and makes it really hard to keep up momentum. Regular cadence of showing your work is a huge boost for momentum and team spirit.

Fewer meetings

I recently went on a rampage and cleaned up our recurring meeting schedule, by eliminating as many meetings as possible, and batching the remaining ones to clear up as much deep work time as possible. As far as I'm concerned, you can't really do any interesting programming work unless you have at least two hours of uninterrupted time (preferably more). By spending ~30 minutes on reshuffling our meetings we quickly improved our "available interesting programming time slots" by 38%, leaving Tuesdays and Thursdays completely meeting free.

It can be tempting as a manager to optimise your time schedule, by finding easy ways to "stay in the loop and give input on things". This is a mistake and it's important for anyone managing engineers to constantly consider the different between Maker's Schedule and Manager Schedule and the devastating impact it can have on team productivity to optimise for the latter.

Cutting down meetings does not mean that we don't discuss our current work synchronously, but these things are ad-hoc, and require less context switching. We do a lot of pair programming, live code reviews, and designer-programmer collaboration every single day.

Define your work while doing the work

Some teams go to great lengths to break down projects into milestones and tasks before starting on the implementation phase, spending vast amounts of time on technical discovery, planning and estimation. This makes sense for when you make promises to customers and have to set realistic and stable timelines, with little room to cut scope of what you deliver.

For our team, it's way more important to keep our process as light weight as possible, and leave as much room as possible to turn new learnings and ideas into released software as quickly as possible.

It's typically a lot easier to discover the work needed when you start doing the actual work, if you have the freedom to cut scope and change direction if things don't pan out exactly like you hoped. In my experience this is also generally a faster approach, but it comes with the tradeoff of less certainty about what's possible within a given timeframe. So if certainty is really important to your team, you should probably don't use this technique, but if you have flexibility to make adjustments as you go, it's an awesome way of building software.

Scope things down

The fastest way to deliver a project is to just do less stuff. We constantly question requirements, and try to identify pieces that can be trimmed, cut out, or simplified. This does not mean that we cut corners, but that we focus on simplifying things as much as possible to move faster.
Simplicity speeds things up in the long run, and opens up opportunities to work on other things. It's also generally a good strategy for fewer bugs and easier to reason about systems.

Small tech investments should be part of every project

I think it's harmful to split project work and technical investments (such as addressing tech debt) into separate buckets. Sure, it would be great if we could always guarantee that after a project is launched we can dedicate X weeks on reducing tech debt, refactoring the code, and improving test coverage. This is not how the world works, or at least I've never seen things play out this way. There's always something new, exciting, and more important to jump on next, as soon as possible. The product/business will almost always take precedence over "invisible" tech investments. The only way to get into a sustainable rhythm of investing in long term technical improvements, in my experience, is to tackle this work in small increments as part of the project work. It's better to push for 10% longer timelines, if it allows us to improve the long term stability and speed of development. I think it's our responsibility as engineers to set clear expectations about what it takes to build something responsibly and sustainably, as explained in Extreme Programming:

It’s your responsibility as a software engineer to communicate what needs to happen in order to build something responsibly. Harsh truths about what’s necessary is better than blind optimism to please stakeholders.