Work on Features, Not Repositories

Starbucks’ iOS App

Why organizational boundaries shouldn’t change where development happens.


Recently on Twitter, Kent C. Dodds asked:

It’s an interesting question, as we often have various reasons to split projects into multiple repositories. (e.g. if I don’t share code between the client & server, then they should be separated, right?)

In my experience, a repository should house all of the code necessary to make developing & shipping features relatively frictionless.

Software is like Jello: poke it in one place, and another place jiggles.


A Real-World Example

Starbucks’ Progressive Web App (PWA) is basically a single-page React app managed within a single repository. The GraphQL API is in another repository.

In practice, working on the UI that requires API changes means:

  1. Having to npm link our API to our PWA.

  2. Working on the UI changes until real data is needed, then…

  3. Working on the API changes, until the UI is working again.

  4. Pushing 2 pull-requests for approval.

  5. Once approved, bumping & releasing the API first.

  6. Finally, bumping & releasing the UI.

There are a lot of places this process breaks down, especially on large teams with a lot of work in-progress.

But the real problem is that the repositories are splitting up features based on implementation.

Ideally, I’d like to see:

  1. Working on the UI & API simultaneously. (In practice, this expedites discovery & turnaround!)

  2. Pushing a single pull-request can be reviewed, approved, and tested.

  3. Once approved, the UI & API is shipped as a single feature slice.

A single repository, properly structured, can deploy to multiple hosts, as separate NPM packages, or as a single monolithic app.

How code is shipped does not have to mirror how it is developed.


But We’ve Known This Already.

Just Look At React Components

When I first started working with React, it was normal for separation of concerns to mean separation of file types.

src/
components/
App.js
Button.js
...
styles/
App.css
Button.css
...

But overtime, possibly expedited thanks to CSS-in-JS, we began to encourage natural coupling of technologies around features.

src/
components/
App/
...
Button/
...

If you want to touch the UI and it means the API has to change, that’s perfectly natural. Self-imposed splitting of code into repositories is a form of premature optimization.

Instead, make adding value easy. And when it’s not easy, split up your code, change your tools, re-architect your app, or whatever.

It’s much easier to blow something up than to piece it back together.


For more content on co-locating files with their features, check out Kent C. Dodds’ “What code comments can teach us about scaling a codebase”.

If you enjoyed this & would like more insights, follow @ericclemmons on Twitter or subscribe to my newsletter!