Favour learning over fixing.
Most software projects encounter lots of “problems”. Bugs, production issues, team members not getting on, external dependencies failing – it can often feel like a constant stream. In my first team lead role, I insisted on “fixing” all those problems. I jumped from one crisis to the next – and in some weird way, I enjoyed it. Being “busy” meant I was adding value, protecting the team, moving the project forward! But it became clear that I was becoming the bottleneck. I was training the team to push all the “problems” to me, and they were just getting on with their day job.
I had this epiphany one afternoon, when I was trying to figure out a particularly complicated database design problem, and one of the team members told me she needed to take a few days off work to deal with a family problem and asked me when she could do that; at the same time a new member of the team messaged me to say he was blocked because he couldn’t get into the source code repository. It felt like I had somehow become the only person who could solve problems.
So, instead of “solving” all the problems, I started to spend time with the developer who had the database design problem, and helped him think through the options; once he had a clear idea, he validated it with the rest of the team, and implemented it. I worked with the developer who wanted time off to figure out how her work fit with the next milestone, and what would need to be done before she could take time off. I reminded the new developer of the “readme” files we’d gone through.
Since that epiphany, I’ve resisted the urge to “fix” problems. Nev does not scale.
Fix the right problems.
Once I found a way of extricating myself from the low-level problems, life got more interesting. I soon realized that I’d been so focused on fixing the team’s problems and shielding them from disruption that I’d missed the bigger challenges. The team was making progress, improving output, gradually building trust with our business stakeholders – but some of the pressures I’d tried to keep away from the team reflected serious business problems. In simple terms, we’d overspent our budget, and the board was not inclined to give us more money. This meant the project was likely to have to reduce in size, and that would mean half the team losing their job.
This was a much bigger risk than a suboptimal database design – and I’d been ignoring it. Worse, I may have made it worse by trying to deflect the budget questions from the team. As a result, I made a checklist.
- Where is the money for the project coming from?
- How much confirmed budget is left?
- How long will it take to renew the budget, and how does that work?
- Does the remaining budget cover the team for the expected duration?
- Would an outsider, with no vested interests, continue the spend on the project?
I look through this check list every month or so – it’s in my calendar. It’s more important that I think about these questions than that I get the right answers every time.
The right problem depends on what you want to optimize for.
So, how do you know what the right problem is for you to work on? Managing development teams is an endless series of trade-offs. Sure, everyone wants to hire the “best” developers, but also wants to pay “affordable” salaries. You want the team to “deliver value”, but you also want to keep down technical debt.
A long time ago, I was the CTO of a scrappy ecommerce start-up. Our goal was simple: we had to launch our online store, and get enough paying customers to secure our next round of funding, by a certain date or we’d be out of business. The team was small, and freelance. We optimized for a handful of goals:
– end-to-end, working code, deployed to production as quickly as possible
– make sure the solution is secure and bug-free in the checkout and payment section
– scale to hundreds of orders per day but no more
These goals were obviously limited – by focusing our QA attention on just the payment and check-out process, we were ensuring we didn’t lose customers’ money, but ideally we’d have spent time testing the basket, the product catalogue, the user interface on multiple browsers. By scaling to hundreds of orders per day, we risked having to rewite lots of features later when (hopefully) we’d have thousands of orders. There were no goals about improving team dynamics, continuous improvement, we didn’t put enough focus on many non-functional requirements.
But broadly, I think our goals were right – the things you’d do for a long-term, strategic development team didn’t really apply to a start-up with a short runway.
Similarly, I looked after a team for a more established professional service company, where our strategic success depended on keeping our team up to date with technology tools and processes – and we had to balance short-term project goals with long-term growth. Our goals were something like:
– deliver a great project for our clients, within the commercial constraints
– treat each project as a way to grow or learn
– expose team members to new opportunities
This created lots of interesting problems – the easiest way to deliver great projects is to use tried-and-tested team members, not someone who was learning. If we wanted to grow or learn from a project, it often meant taking risks – perhaps trying a new technology framework, or working with a new partner.
You can only optimize for 3 things at a time.
And that might be a stretch. It might be better to pick just one or two. You want to get everyone in the team to work towards the same goals. That’s really hard to do; typically, it takes weeks or months to get the team to buy into the goals, weeks or months to really get that into the instinctive decision making, and weeks or months for the results to come through. So, it’s easier to find a single, big, unifying thought and drive towards that than picking 3 smaller improvements.
I found this when I was looking after a development team that had run into trouble – after 6 months of development, they’d built a few standalone components, but nothing was wired together, and the client didn’t understand what we’d built or why. My boss asked me to help the team to get back on track; my first session with the key team leads went a bit like this.
Nev: so, what’s the most important thing you’re optimizing for?
Tech Lead: optimal use of this expensive CMS we’re using – it’s got lots of features, and the client expects us to use them all, even if they are overkill.
Product Lead: seamless operation once we’re live – the client really wants everything to be fully automated.
Design Lead: cutting edge visual impact, across all devices. Super smooth animations, ideally 3D.
Delivery Lead: sticking to the budget and making sure the team is working hard.
CMS Lead: scalability – some of the features we’re using could really hurt performance and scalability.
Subject Matter Expert: we’ve got lots of product catalogue detail, and we owe it to our users to show it all.
QA Lead: automated testing, there’s too much content and data to verify manually.
All those priorities were right in their own terms – but by trying to do them all, we’d lost sight of the most important goals: building and retaining trust with the customer.
My next conversations were with the customer – they worked for a business famous for quality and rigour. But their approach was incredibly pragmatic – the most important goal for them was to be able to work to a credible deadline, and a predictable budget. They were happy to trade features and polish to get to those goals, but they wanted to see regular evidence that we were moving in the right direction.
So, together with the team, we set as our goal “rebuild trust with the client”, and we optimized for (I’m becoming repetitive) frequent delivery of software with a known quality, demonstrating progress towards the overall deliverable.
The problem was that in optimizing for half a dozen different (sometimes conflicting) priorities, the team was missing them all. In my experience, the very best teams in the very best circumstances can optimize for 3 things. Most teams should focus on just one – and it’s nearly always “frequent delivery of valuable software”.
People over process, architecture or anything else.
I often joke about my role being about “people tetris”. Finding the right people to work on the right project has been the biggest leaver I’ve found. The important aspect here is that it’s not the people who are “right” or “wrong” in general – but they may not be right for a specific project.
I wish I could formulate how to find this mysterious rightness. I’ve had a fair amount of success putting teams together, but I don’t know if that was luck or judgement. A few heuristics:
- Availability is not a skillset. Don’t put people onto a team just because they happen to be available.
- The more visible the person is within the team, the more attitude matters. Having a grumpy scrum master or product owner will affect the entire team.
- Figure out the overall behaviour/culture/attitude you want to build and don’t bring people into the team who don’t fit or can’t adapt, no matter how good their skills.
- Look for balance – if you already have a perfectionist, look for a pragmatist.
Running engineering teams is hard – but the time you spend talking to the engineers and leads has huge impact. Look for opportunities to celebrate success publicly; discuss failures in private.