Software Engineering is a Team Sport

Neil Johnson
AppLearn Engineering
6 min readSep 6, 2022

­­­­­As a development team lead, I am passionate about the ways to make a team work effectively. That means ensuring knowledge is transferred, junior engineers are up-skilled and context switching is minimised.

When the team is healthy it can reduce stress, increase job satisfaction and provide better outcomes to problem solving.

Throughout my time as a lead, I have spotted many things that can reduce the effectiveness of a software engineering team and result in people working as individuals instead of collaboratively. Here are just five out of many.

  1. Oversized teams
    Imagine a football team with 25 players on the pitch. How does the manager organise the team? How does the captain keep morale up if everyone is stepping on each other’s toes or can’t keep track of what others are doing?
  2. Feature analysis, planning & implementation carried out on an individual level
    Is there a person in the team that is the only one able to fix a problem with a specific feature? Chances are they designed and built it alone. If this is the typical approach, how do we know if the feature was built in the most efficient way or if it is opinionated?
  3. Large code reviews
    I find developers tend not to like reading lots of code, especially someone else’s. If a developer has been working on a sizeable feature alone, chances are they will throw out a huge pull request at the end of the week and ask for it to be reviewed. If everyone is doing this, do we have to start putting code review time in our calendar?
  4. Too many items in progress
    You have 10 distinct features to develop or defects to fix. You have 10 developers. If each developer is assigned one of these tasks, how do we minimise context switching or multi-tasking when someone goes on holiday or is off sick? What about when a critical defect is raised? Can we maintain focus in this scenario? Is there a common goal?
  5. Knowledge not shared
    We make changes to lots of code and build lots of features but do we communicate these changes effectively? Even if done working as a team, it is possible that multiple members leave the organisation or move to other teams.

Solving these issues is not easy and there is no silver-bullet approach. What works for one engineering team may not work for another. However, some of the following approaches have worked well for the engineering teams at AppLearn.

Think teams, not team

Let’s start with the teams in general. Rather than having one large team, keep teams to a reasonable size. I find 4–8 to be a good number. An even number is often advantageous for pair programming.

A multi-disciplined team is also good for knowledge transfer and up-skilling. A team should be able to attempt any task they are presented with, not have one individual who has the knowledge to do something specific. This may include infrastructure as code, test automation or a specific technology.

Plan as a group

Features/stories should go through various iterations of refinement by product owners, architects etc. Once this is complete and it’s time to start getting into implementation specifics, this should be done as a team exercise or by a minimum of 2 developers that will be working on the story. Interfaces should also be clearly defined and agreed upon by the team.

Document

It is important that all discussions, planning, analysis and implementation details are documented. This doesn’t have to be a novel but should contain any key information or diagrams that help a team member or someone in the wider team to understand the problems and the solutions. This is a key part of knowledge sharing.

Break down the stories (without blocking)

If we want to work effectively as a team on a story, it is important to break it down into parts (subtasks) that team members can work on without blocking each other. Creating non-blocking tasks can sometimes be difficult but having a task that blocks everyone is not a good idea. Try to design each subtask as a pull request. There should only be a small amount of code required in each task.

Let’s look at what a typical breakdown may look like for a fictional feature.

Feature:
Record an event when any button is clicked in the web page

Tasks:

  1. Create http service and construct event payload
  2. Listen for button clicks in web page
  3. Create database table
  4. Create API endpoint
  5. Data validation pre-save
  6. Save event to database table
  7. Send event payload on button click to endpoint

You can see that there are still some tasks that need to be completed before others, such as 1 and 7. However, there are enough non-blocking tasks for multiple team members to work on in parallel.

If developers are working on the client-facing parts, they should be able to mock the server-side parts and vice-versa from the interfaces defined in the planning session.

Nobody likes to review huge pull requests!

By ensuring more than one developer is working on a story, pull requests should be small and quick to review. Each developer should be familiar with the implementation and be able to address a pull request when required.

If working on a single codebase, branching can be important. I typically like to use a branch prefixed with, ‘story/’ which all developers will branch from and merge back into for each subtask. If a micro-service/micro-front-end architecture is used this may not be so important unless there are multiple tasks for a single service.

Pair programming

This is a great way to up-skill developers who may be unfamiliar with the areas of the code needed to be worked on to complete a task. It is also good to use pair programming on any tasks that have an unusual level of complexity.

I advise against pair programming for an entire feature as it can be quite tiring for a developer who is not in the driving seat, and you must ensure that developers agree on when to take a break. An alternative is to pair on individual tasks, especially on the occasion that there may be a blocking task.

Short pairing sessions do encourage developers to discuss finer details and can lead to simpler solutions being created.

I advise reading Martin Fowlers’ great article, On Pair Programming.

Workload limits

If we have n developers, the maximum number of stories in progress should be n / 2. This is not a hard and fast rule as sometimes there will be issues that can be addressed quickly by a single developer. However, this should only be the case for well-known (by the team) areas of the codebase.

Setting limits can help keep focus and ensure people are working towards a common goal by limiting context switching.

Constant communication

Ensure that the team are in communication with each other regarding the tasks they are working on. In agile, things can change quickly, and people must be kept aware. Use daily stand-ups for this and encourage team members to call each other if working remotely. If the team is using Slack, the huddle feature is a useful tool for getting the team together.

The team should aim to transfer knowledge as much and as often as possible, so if any unexpected details emerge, or an alternate solution to that originally planned is discovered.

In organisations where multiple teams exist, it is a good idea for teams to hold regular workshops to discuss how features were implemented or defects were resolved. This helps if teams are re-organised or members leave as knowledge is not lost.

Communication is key to ensuring that no one person holds all the knowledge.

Conclusion

I hope some of the suggestions above help with working better as a team.

Teamwork is key to successful outcomes when delivering software and working to deadlines.

I would love to hear more about the strategies used for collaboration in your software teams. Please feel free to comment or get in touch.

--

--