For about a year and a half, I had the privilege to work with what turned out to be the highest performing development team in my career. Not only did we deliver some pretty cool stuff at high pace, we had a lot of fun and it was a joy walking into the office in the mornings. However, to start off, it was not that great or high performing. Nor was the transition to the great team it is today a coincidence. This article outlines some of my takeaways, lessons learnt and thoughts around how to do the same thing again with other teams. Before we start, a small disclaimer; none of the ideas below are mine. They all came from other people, mostly from the mentioned team. You will probably have heard it all before, there is nothing really innovative here. The value comes from how we put these things into our ways of working.

High and low, here we go.

How you describe the problem matters a lot

“He who cannot describe the problem will never find the solution to that problem” — Confucius

Like any other task the team is supposed to deliver on, this one starts with a ticket. And probably, it was written by your Product Manager or the like. And the quality of the ticket may vary a lot. Sometimes the PM understands the problem to some degree, but not always and rarely to the degree needed to actually solve the problem in a good way. Though the PM thinks so. I know, because I am one. So how do you improve the quality of the ticket and why does it matter? It is kind of obvious but if the problem you are trying to solve is fuzzy, you will waste time trying to understand what it is, or solve the wrong problem. You can spend days doing that actually without finding out. Instead, this is what you should do:

The more people that are involved in describing the problem, the better. Involve the entire dev team in writing tickets in the issue tracker. The dev team consists of some pretty smart people with great input on what the actual problem you want to solve is. As a PM, your role is to make sure you protect the customer perspective but apart from that, be open to the possibility that the problem you are trying to solve is something else than you think it is.

As a great side effect, the entire team now understands the problem which means that anyone can pick it up and complete the ticket. No need to explain again, do hand-overs, block tickets because people are on vacation etc. If a ticket is at the top of the board, the team can work on it.

Always write acceptance criterias/definition of dones or the like. Make sure they are measurable and understood by everyone in the team. That is, everyone understands all of the acceptance criterias. Always.

This process does not have to consume a lot of time. Less than an hour a week on average and it is time well invested.

How you solve the problem matters a lot

“We can arrive at better solutions to any problem or pain together, than we can by ourselves” — Desmond Tutu

Stating the obvious, most problems can be solved in a number of different ways and not all solutions are equally good. Of course it is hard to know which the best solution is but you will greatly improve the chances of success by discussing several different options before setting out.

Do not assume your PM knows how to solve the problem, though the PM may have opinions in the matter. Take that as input, nothing else. Also, do not assume that the architect, lead developer or the like, will come up with the best solution. They may have useful input but do not take that for granted.

Instead, the first thing you do when picking up a new ticket is to grab a few fellow team members (or all of them) and discuss different options. Take the time needed to agree on the best approach. The team decides. As part of the discussion, break down the ticket into smaller tasks, as many as you can come up with, as a start.

The benefits of this approach is that you will discuss the benefits and problems with different approaches and thus get a better understanding of the problem and how to best solve it. The team knows how to approach a particular ticket which means more people can work on it and you do not need to block the ticket just because one person is not there that day. You catch potential problems with the problem statement and solution early.

Tickets should not be too big

We tried different strategies for calculating ticket sizes. Story points, T-shirt size, what not but in the end we felt it was only one thing that mattered. The ticket should not be too big. If it is too big, you run into the risk of trying to solve a too complex problem, you will write code that lingers for days and may rot. You want to be able to do something small, contained that can be shipped to production as soon as possible. It is a matter of minimizing risk. So what is not too big? If you by reading the ticket feel that you understand what has to be done and can visualize the end result and that you can complete the task in 1–2 days you are probably OK.

Sometimes you get it wrong and end up with a problem that takes way more time than expected. That’s totally fine. To catch those we used the dotting method. At standup, dot tickets that you worked on the previous day. If a ticket gets 3 dots, make a team decision: if you feel you can complete the ticket today, do it. If not, spend time splitting the ticket into 2 or more.

You may not start working on a ticket unless ….

That acceptance criteria or definition of dones are important is quite wide spread in my experience. However, much more important are the criteria for when you are allowed to start working on a ticket. The rationale is that the better prepared the ticket is before you start, the less time you will waste doing the wrong things. So, these are the things we came up with. You may not start working on a ticket unless

it is prioritised by the PM. Basically, do not start working on random stuff or things that you feel like doing. Trust that the PM does a proper job of prioritize the work.

Basically, do not start working on random stuff or things that you feel like doing. Trust that the PM does a proper job of prioritize the work. it has acceptance criterias that you understand. That is, read the ticket, make sure you understand everything that is in there. If not, the ticket should go back to refinement.

That is, read the ticket, make sure you understand everything that is in there. If not, the ticket should go back to refinement. anyone can start working on the ticket.

it has a purpose, what and value. The rationale for why this particular problem is on the table is clear.

The rationale for why this particular problem is on the table is clear. it is not too big.

it is not blocked by external dependencies.

Coding is not typing — never work alone

“Here’s the crux of it, typing isn’t the bottleneck in software development, and writing code isn’t building a product. The real cost is solving the problem, waste, and rework.”

- Karin Obermüller, Jeff Campbell

We never work alone. On every ticket, we do either pair or mob programming. Preferably mob actually. Like the quote says, it is not about typing:

Pairing is better than solo

More eyes catch more problems early

You come up with more solutions

You share knowledge

More people get to know the code

It provides focus

It is fun!

Mob programming is better than pairing

Work on the most prioritized ticket never stops — The Mob is always there

The entire team is always up to speed with, well, everything — Anyone can answer questions, go to meetings etc

Everyone gets to see it all. Code, tools, tests, production environments, pipelines …..

Things gets resolved here and now. Huge amount of overhead just disappears

You automate stuff. Doing manual work in a Mob over and over again just does not happen

You build on each other’s strengths and overcome individual weaknesses

You dare to try new things

You become a true team and not just a bunch of individuals joined by a team name

Before stand up is over, decide who is going to work on what. Do not assume that you have the same formation as yesterday. Actually make a point of not do the same thing.

It is better to complete one ticket than to move 5 tickets a little bit

Kind of obvious but if you complete a ticket, you have provided value. And the ticket that should be completed first is the one that is most prioritized. So it is much better to complete the most prioritized ticket as soon as possible than to move 5 tickets forward a little bit. As a PM, why would I want anyone to work on the fifth most important ticket when the top priority is not done yet?

So have few tickets on the board at any given time. Few means 1–2, max 3. Make sure several people can work on every ticket;

Pair or Mob. Always.

Break down each ticket into smaller tasks allows more pairs to work on the same ticket

Sometimes you cannot continue working on a ticket because of external dependences and the usual way to handle that is to block them in some manner. Don’t. Instead, rewrite the ticket to reflect the work that has been done up till now, write a new ticket describing the remaining work and tell the PM that there is a new ticket that needs to be prioritized. Move on to the next ticket.

If a line of code can go into production, it must

If a piece of code is done, however small, it should be pushed to production right way. Because that is the quickest way to provide value. New and improved code in production as quickly as possible. We did on average 20 deploys to production every day. There are lots of benefits to that.

If you deploy to production often, you get better at it. And you have to automate the entire process which removed the problems of manual errors as part of the release process.

The smaller the deploy, the smaller the risk. And if something goes wrong, finding the problem becomes much simpler and getting a fix out is really quick.

Huge amount of overhead is removed when releases just happens as part of the process. Commit code and off it goes.

It does require a few things to work though

Fully automated pipelines without manual steps

Automated tests suites that you trust — this is your safety net

Monitoring and alarms that you trust

Fast feedback if something goes wrong. We have monitors of our pipelines and monitoring in our team area so we can catch problems as soon as they happen.

As a result of the above way of working, we stopped using feature branches which again removed a lot of overhead. Instead we only do trunk based development. Feature branches sounds like a good idea but comes with a cost

It puts code on the shelf where it does not do any good. You spent the hours but did not get the benefit.

When it has been on a shelf for a while (a week or more) you have to re-remember what the whole thing was about, worry about merging problems and if you introduced other issues by working on other tickets in the meantime.

Ok, but what if a feature is not ready, how can I push that to production? It’s broken, right? Well, yes and no. Just because a bit of code is in production does not mean you have to allow real traffic to run the code. We push code to production anyway and if we are not yet ready to expose the feature to consumers we hide it behind a feature flag. In this way the code is always in a releasable state. All the time.

Is there a silver bullet?

The end result was that we went from 12 tickets a month to more than 50 tickets a month. I have since moved on to new teams and the question I ask is, can it be repeated or was it just a lucky coincidence? The right people, the right project, the right whatever? If there is a silver bullet, it looks something like this: