A Two-Person Agile Project (and what it teaches us)

Reading about "being agile", "agility", or one of the famous agile frameworks, we often think of growing startups, scaleups and corporations seeking to adopt more efficient ways of working, building their products better and quicker, and making their clients happier.

We might easily forget how agile small companies and software projects with only a couple of people involved can be, and how these can teach us a lot about the essence of agility.

Let me briefly introduce you to a past project.

The two-person agile project

Several years ago, I was involved in building a new software product - a tailor-made web-based platform solving a number of our client's business problems. While I will spare you the details of the client, the product and its functionality, I want to focus on some approaches we took back then.

First of all (you guessed it): our team was small, very small: there was the client, and there was me. That means I was doing pretty much all of the (technical) work: setting up the infrastructure, building the system's back-end, implementing the front-end, caring about security, and deploying and releasing functionality to the end-user. Nowadays, we would call this full-stack development, and this scenario resembles typical freelance projects.

I was lucky to have a single spokesperson on the client's side, and we were working relatively close together. We didn't spend time planning months ahead but instead discussed in a (bi)weekly meeting what to focus on next as a direct result of the most recently delivered features.

We were both happy: the client saw the product evolve, supporting business cases they had discovered along the way and refining existing features that were just not there yet. While myself, I was able to stay focused primarily on developing and didn't lose time with things that didn't matter.

This story will not sound very groundbreaking to some, while for others, it may be reminiscent of simpler times or your 90s hobby or school software project. No corporate silliness, only happiness!

Identifying the success factors

Frankly, I needed a few years to truly understand and appreciate the elements that made this project so rewarding. It only started to dawn on me after learning more about the core values of agility (beyond your typical Scrum, Kanban, etc.) through later jobs, workshops and interactions with mentors and peers.

Of course, it wasn't the perfect software project -- does that even exist? Yet, the necessary factors to make this a success with a happy client were in place.

1. Uncomplicated team structure

It doesn't come any simpler than that: I was the sole developer working on this project, and I did all the talking with the client.

By eliminating more complex managerial structures, hierarchies or third parties to align with, we also:

  • mitigated waiting time as much as possible;
  • avoided handoffs between business analysts and the team or even between a product manager and the developer(s);
  • and (perhaps most importantly) allowed me to be self-managing.

2. Close and frequent collaboration

Through our (bi)weekly meetings, we presented, tested and talked about what was finished and delivered since the previous session and what was in progress, and we identified what we can or should focus on next.

In this process, receiving and processing feedback was at the core of our approach. We didn't hold back to give honest feedback, think through budgetary or technical implications, and build mutual trust.

3. Don't stick to The Plan™

Infamous for many large organisations and corporations, elaborate plans, analyses, and specifications are defined months upfront and carefully tracked in their progress. Ah, ye olde waterfall approach to project management.

Throwing this overboard is a staple of agility. Embracing change.

By incrementally letting the product evolve, the following steps became obvious during each meeting, and so were the basic functionalities to implement. This approach made us avoid overhead work and allowed the client to experiment with the next evolution of the platform by the end of the next iteration.

4. Maintain a consistent flow

Working alone and mono-focusing on a single change made it pretty easy to get into the zone. I didn't need to split development work among colleagues, wait for their tasks to finish, review pull requests or solve merge conflicts to wrap up user stories.

Without the need to sidetrack all too often and lose time over said activities, there was a relatively fast but most importantly consistent flow.

5. Prioritize bugs

Mono-focusing made us prioritise bugs more efficiently and get them fixed "first thing in the morning".

This approach contributed to a certain level of quality that we wanted to maintain. There is less to no value in delivering broken functionality or leaving subpar, confusing or unused features in place.

Applying to typical teams

You may think this approach is both naive and unfitting for building products in larger teams or organisations. Surely, in the real world of complex SaaS products, it can't be this simple, right?

And you're (partially) right! Most products cannot and should not be built by a two-person team having a single developer. Aside from the bad bus factor, complex business domain(s) or combinations of technologies used are better carried by T-shaped teams of around five people (YMMV). Eventually, applying concepts of team topologies may help to tackle more considerable complexities.

Still, the success factors mentioned above can be projected onto larger teams, contributing to the success of more complex projects and software companies.

Let's dive into some aspects of lean software development.

"Speed is the absence of waste"

This quote is from Mary and Tom Poppendieck's book Implementing Lean Software Development: From Concept to Cash, a primer on applying lean principles in building software products.

I particularly like this quote because it stresses that high speed or velocity is achieved not by pushing the team to work harder and faster (often with disastrous long term effects) but rather by getting rid of wasteful work ("Muda") as much as possible.

  • Creating elaborate plans and specifications (user stories, documents) too far in advance is part of a waste called Partially Done Work and a threat for the Extra Features waste that Poppendieck identified in their book. These wastes are sometimes (originally) referred to as "inventory" and "overproduction".

    Making analyses and writing out specifications should -- if at all -- be done as late as possible. Otherwise, there is a potential risk of ending up with obsolete plans due to new insights, changes in the market or newly identified pains by the client, and risking building low impact functionality (= Extra Features; also a form of feature creep).

    It is no exception for stakeholders to request and hold on to early defined plans and roadmaps only to end up missing the boat either on what is needed and how long it would take to achieve the desired goal or outcome. Even though this behaviour is understandable from a psychological point of view, seeking to control risks through waterfall project management instead of evolutionary product design and development does pose a threat to the success of the product or project.

    Instead, continuously poll for the next most important step to take using market research, product analytics and data, test or beta users, team insights, or simply by conversing with your client after delivering your latest iterations and work in small steps. Of course, you may still define a long term strategy and goals (with deadlines if you must); ensure they focus on outcomes rather than outputs.

  • Our dramatically simple team structure avoided some other forms of waste: Handoffs and Delays (also called "waiting").

    Our mini team was self-managing: in coordination with the client, I defined the pace, wrote user stories and defined technical approaches without relying or waiting on people outside the team.

    With bigger teams, you want just that: as a company owner, CTO, VP/Head or manager, build up mutual trust, provide a psychologically safe environment where it is okay to speak up, and allow the team to work autonomously. Ensure teams comprise of all the skills they need to fulfil their goals: T-shaped people having at least some notion of a wide range of skills with more profound knowledge on a few specialist skills.

    Attempt not to limit this mindset to traditional development skills; introduce UX and UI expertise, design, QA and testing, product management, operations, product and data analytics, and any other skills required within the same team as much as possible.

    As the names of the wastes give away, this helps minimise handoffs of tasks to people outside the team, focusing on working together as often as possible and avoiding delays in execution. In the next section, I will dive a little deeper into these matters and show how we can prevent handoffs inside the team.

  • And last but not least, focusing on solving known bugs first helps to mitigate the obviously named Defects waste.

Minimising these wastes as good as we can, we limit excess costs on activities that do not add value for the customer, keep team morale high, and improve the overall return on investment (ROI) of development.

Pair and Ensemble programming

I remember what I thought when I first heard about pair programming many years ago: "How is sitting with two at one computer going to make the work go better or faster? Just leave me alone and I will do fine." Some years later, I had to admit I was wrong.

Many -- if not most -- software development teams are managed to maximise resource utilisation. Concretely, this means individual contributors are expected to be busy and productive as much as possible. When everyone is productive, a lot of work is getting done, so a lot of value (and money) is generated. Right?

Unfortunately, the practice of keeping everyone busy all the time kills flow because it keeps our previously mentioned handoffs and delays in place, and it does not spread knowledge across the team that well either.

Think about how frequently typical teams are indulged in planning and dividing work, waiting for absent or busy people, regaining focus after task switching, etc. In other words, trying to deliver more work units in the same timespan yields the opposite effect.

Ensemble programming (also known as "mob programming") is a valuable practice to increase flow by avoiding context switching and minimising handoffs and delays while facilitating knowledge sharing among team members.

Popularised by many agilists and podcasts, the essence of ensembling is an entire team working together in a so-called mob or ensemble, doing a single task (remember mono-focusing?), taking turns in being the "driver" (which is the person typing), while the rest of the team navigates, brainstorms and contributes.

Running ensembles, the T-shaped team focuses on one-piece flow, just as I did in the story's agile project. As a result, their cycle time, a metric for the time required for an item to move from "in progress" to "done", decreases drastically.

Doing this with a team ensures that whenever someone takes a break, moves to a private meeting, has a sick day off, etc., the remainder of the group retains focus and keeps the flow going. This format is hence also an ideal setting for onboarding new people; they can join the ensemble, ask questions and make minor contributions at any time right from the start.

Pull requests vs flow

A perfect example of an accepted practice killing flow that ensemble programming fixes is the cycle of code reviews.

Many of us have been there. As an individual contributor, you wrap up your task, create a pull or merge request and eventually request reviews from your mentors or team members. Then the waiting game begins.

  • Said reviewers are busy with other tasks, helping others, sitting in meetings, or (worse 😉) having a day off.
  • Luckily, soon enough, your code change is being reviewed, but you're not getting approvals yet! Questions pop up, potential problems arise, and missing tests unveil themselves.
  • Time to get those fixed! At least, as soon as you wrap up or abandon the task you started in the meanwhile.
  • When you've finished processing feedback, it's time to push those changes (hopefully without a lot of conflicts against your base branch) and let the cycle begin anew until everyone is satisfied and you're allowed to merge.

Sounds great, doesn't it? This unproductive cycle kills people's sense of accomplishment, focus, and in the end, the throughput of the team. Over time, people might put less effort into code reviews because they want to get their work done as quick as possible, with adverse effects on quality. In other words, this team is suffering from the handoffs and delays wastes within the group.

The good news is that this entire cycle of gathering ideas and technical approaches, writing tests and code, and approving and deploying the changes is part of the normal flow during ensemble programming. As a result, delays and waiting are reduced to the minimum, and development speed increases, especially when we already avoid many other wasteful activities.

All in all, having this steady flow of creating value in a supportive and lean environment, people become happier and more motivated.

Getting started with pair programming

Now, logging into work the following day and inviting your entire team in an ensemble is likely going to feel off, scary, unproductive or a combination of those. Ensemble programming is a practice that takes persistence, rehearsal and guidance, especially since it is radically different from how most people are used to perform their day to day job.

My advice would be to start with pair programming first, limiting the "mob" to two people, and allow people to get accommodated to working together more frequently. Many of the benefits will already be there: less waiting and focus switching, and more knowledge sharing.

Don't stop here, though! There are likely still handoffs and delays between pairs and individuals, and hence wasteful activities are still present!

Summary

In this article, we took a quick dive into applying the success factors of a simple, agile team to larger teams. As a result, we can learn and improve how larger teams work through concepts of lean software development while not forgetting fundamental agile values such as those of psychological safety, experimentation, and continuously delivering value.

When attempting to optimise the happiness and flow of a development team, ponder whether your team is spending too much time with wasteful activities, trying to make up for it individually in between meetings and distractions. Teach people to spot and alleviate waste in a continuous improvement cycle and help them make the company and the clients more successful.

And don't forget to think about that old project you did back in the 90s and what made that project awesome. Perhaps you may apply some practices from it as well!

Resources

If you want to read more about lean, I recommend Poppendieck's book linked above, as well as the (free) book 2 Second Lean by Paul Akers (thanks Ashley and Joshua of Industrial Logic for the recommendation!).

For more information on ensemble programming, check out the Mob Mentality Show, offering videos with common patterns, insights, tips, etc.

Elisabeth Hocke (@lisihocke) also compiled an extensive list of resources on Working as an Ensemble and created a talk on the practice.

21