🤝 Our engineering working agreement
[Author: Will]
One of the most high impact things we did when setting up our team was creating a culture. A very effective tool I had used in the past in other teams I lead was a working agreement. My manager and mentor at Monzo and Improbable came from Atlassian, was an all around agile wizard, and he first introduced me to the concept. It seems only fitting to post a link from the excellent resources Atlassian offer to give more insight of what a working (or team) agreement is. Long story short, working agreements are a set of guidelines that teams create together in order to get the best from each other.
We decided to publish ours, to give more insights to potential new joiners on what is it like to work at Pactio!
We Code Good
We try to avoid premature abstraction. If we can’t see an abstraction, we leave it for a later moment. Rule of 3 is really helpful in these cases.
We try to keep the code as close to its consumption as possible (this is sometimes known as the locality principle). There are bad examples of this in the codebase, but we want to stop this going forward. A specific file with a specific name close to its usage it’s much more useful than a generic top level lib folder with thousands of methods in it.
We try to keep documentation as close as possible to the code. We try to add comments on the why (not the what) of the most tricky parts of the code. Examples and tests are the best kind of comments / documentation.
We care about developer experience as much as user experience
We recognise that projects and codebases should be easy to setup and understand (simple code, simple setup).
We aim at reducing pain for everyone, i.e. reduce build time, proposing a tool which save time for the whole team and can accumulate to a lot of save time.
We are obsessed by the quality product
We strive to test as much as possible! Time will always be a constraint, but if the historic tests aren't there for a feature we’ve been working on, we try to at least add tests for the parts we have been working on, if not incrementing the old test coverage
We strive to test logic at the unit level as much as possible. We add tests to all functions that are complicated and have deep implications (e.g. the calcs!) but are easy to test.
As we focus more and more on quality, its worth sometimes checking out the branch of a PR while reviewing and playing around with a new feature (try and break it). For lots of things we shouldn't have to, but it could be a way of catching bugs at the source rather than them cropping up weeks later.
When we add new front-end features, we always keep in mind that our customers do not have powerful machines and they might be across the pond. It’s therefore always worth to understand how the product performs with:
- a 4x CPU throttling
- 100ms artificial latency (in case we can’t have an optimistic UI)
We are the change we want to see
We communicate honestly and often
We default to transparency, preferring public means of communication over private ones. There are no stupid questions, and our question might be someone else's. We make the eng-team
channel a safe place where people are not afraid to ask questions. We use it to share as much knowledge as possible. We are also committed to knowledge sharing in the form of talks, pair programming, code reviews.
We truly believe that there are no stupid questions. No one is an expert at everything. We should always be able to ask anything and get a good answer. We must always be able to seek validation of our ideas from peers, listen to their opinion without interrupting, and understand the merit of what they are saying. It’s still OK to disagree sometimes, but these are not personal attacks. We debate ideas, not people.
We are committed to successful Pull Requests
We want to merge early and often. We strive to make PRs as clear as possible: we summarise changes and context, add screenshots/ videos and flag any possible contentious points so it's easy and fast as possible for the reviewers
We aim to have 0 PRs pending review at the end of the day. We always prioritise PRs over our current work, as we recognise that 1 PR merged is better than 2 non merged. We review PRs assigned to us as soon as possible. If we are reviewing a PR assigned to someone else, we let them know. We acknowledge we are responsible for getting alerted when a PR gets assigned to us, in the form we prefer.
We commit to light touch code review. We try provide good actionable feedback that will benefit the company and the team, without slowing us down. Preferential feedback can be suggested if we feel it’s important, but should never be blocking.
We are committed to successful meetings
We should have timed discussions, and avoid going off on tangents when discussing a topic. We recognise that impactful meetings usually produce an artefact, like a plan, an action item, a decision record, etc.
We are hard on problems, not people
We are kind, everyone makes mistakes, hindsight bias doesn’t help anyone. People take the best decisions with the information that they available at the time. We recognise that there are perfect systems and systems in production. When something bad happens, we all come together to fix it. No finger pointing, no blame shifting. There is no value in knowing who broke something, or what a much better design would be, there is value in fixing it.
We take decisions, and own them
We are in a startup, there will be a lot of uncertainty. Don’t be afraid to make mistakes. We need to be able to navigate ambiguity, take conscious decisions, and document why we have taken them.
It’s always important to have engineering discussions for technical topics, and seek validation from our peers. It’s fine to do this in the medium you prefer. It’s not ok to have a discussion and not documenting decisions and outcome, otherwise we’ll have them all over again.
We always demo changes which introduce new features or are changing behaviour to at least our PM, but preferably to the broader company audience.