Work on Features, Not Repositories
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:
- Having to
npm linkour API to our PWA.
- Working on the UI changes until real data is needed, then…
- Working on the API changes, until the UI is working again.
- Pushing 2 pull-requests for approval.
- Once approved, bumping & releasing the API first.
- 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:
- Working on the UI & API simultaneously.
(In practice, this expedites discovery & turnaround!)
- Pushing a single pull-request can be reviewed, approved, and tested.
- 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.
But overtime, possibly expedited thanks to CSS-in-JS, we began to encourage natural coupling of technologies around features.
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”.