Tech Leaders: Low-Performing Teams Are A Gift, Not A Curse

It’s an age-old story. You’re parachuted in to lead a software development organisation that’s experiencing – let’s be diplomatic – challenges.

Releases are far apart and full of drama. Lead times are long, and unless it’s super, super necessary – and they’re prepared to dig deep into their pockets and wait – the business has just stopped asking for changes. It saves times. They know the answer will probably be “too expensive”.

The only respite comes with code freezes and release embargos – never on a Friday, never over the holidays. But is a break really a break when you know what you’ll be coming back to?

Morale is low, the best people keep leaving, and they can almost smell the chaos on you when you’re trying to hire them.

The finger-pointing is never-ending. And soon enough, those fingers will be pointing at you. Honeymoon periods don’t last long, and the clock is ticking to effect noticeable positive change. They lit the fuse the moment you said “yes”.

I know, right! Nightmare!

Except it isn’t. For a leader new in the chair, it’s actually a golden ticket.

The mistake most tech leaders make is to go strategic – bring in the big guns, make the big changes. It’s a big song and dance number, often with the words “Agile” and/or “transformation” above the door.

This creates highly-visible activity at management and process level. But not meaningful change. Agility Theatre is first and foremost still theatre. You’re focusing on trying to speed up the outer feedback loops of software and systems development – at high cost – without recognising where the real leverage is.

Where I work as a teacher and advisor is at the level of small, almost invisible changes to the way software developers work day-to-day, hour-to-hour, minute-to-minute.

The biggest leverage in a system of feedback loops within feedback loops is in the innermost loops.

Think about it in programming terms: you have nested loops in a function that’s really slow, and you need to speed it up. Which loop do you focus your attention on – the outer loop, or the inner loop? Which one would optimising give you the most leverage for the least change?

I worked with a FinTech company in London who called me in because they’d been going round in circles trying to stabilise a release. Every time they deployed, the system exploded on contact with users – costing a lot of money in fines and compensation, and doing much damage to their reputation.

“Agile coaches” had been engaging with management and, to a lesser extent, teams to try to “fix the process”.

I took one look, saw their total reliance on manual testing, and recognised the “doom loop” immediately. Testing the complete system took a big old QA team several weeks, during which time the developers were busy fixing the bugs reported from the last test cycle, while – of course – introducing all-new bugs (and reintroducing a few old favourites).

They’d been stuck in this loop for 9 months, at a cost running into millions of pounds – plus whatever they’d been paying for the “Agile coaching” that had made no discernible difference. You can’t fix this problem with “stand-ups”, “cadences” and “epics”.

I took the developers into a meeting room and taught them to write NUnit tests. Prioritising the most unstable features, the problem was gone within 6 months, never to return.

And something else happened – something quite magical. Not only did the software become much more reliable, but release cycles got shorter. Better software, sooner.

That’s quite the notch on the belt for a new CTO or head of engineering, dontcha think?

After decades of helping organisations build software development capability, I know from wide experience that taking a team from bad to okay is way easier than taking them from okay to good, which is way easier than from good to excellent.

Having helped teams climb that ladder all the way to the top, I can attest that the first rung is a real gift. Your CEO or investors probably can’t distinguish excellent from good, but the difference between bad and okay is very noticeable to businesses.

Unit testing is table stakes in that journey, but the difference it makes is often huge. Low-visibility, but very high-leverage.

Here’s the 101: the inner loops of software development – coding, testing, reviewing, refactoring, merging – are where the highest-leverage changes can be made at surprisingly low cost.

90% of the time, nobody but the developers themselves need get involved. No extra budget’s required (you might even save money). No management permission need be sought. No buy-in from other parts of the organisation is necessary.

High-leverage changes that can slip under the radar, but that can also have quite profound impact.

And results are much easier to sell than promises. Imagine, when your honeymoon period’s up, being able to point to a graph showing how lead times have shrunk, and how fires in production have become rare.

I’ve seen that buy tech leaders the higher trust and autonomy they need to make those strategic changes that the infamous organisational antibodies may well have attacked before. They were immunised by results.

Now for the really good news. In all those cases I’ve been involved in – many over the years – tech leaders only did one thing.

I am not an “Agile coach” or a “transformation lead”. I do not sit in meetings with management. I do not address strategic matters or matters of high-level process.

I work directly with developers, helping them to make those high-leverage, mostly invisible changes to their innermost workflows. Your CEO will likely never meet me, or even hear my name.

The first rule of Code Craft is that we do not talk about Code Craft.

Right now, you may be thinking, “But Jason, we’ve got AI. Developers can produce 2x the code in the same time.”

Do you think 2x the code hitting that FinTech company’s testing bottleneck would have made things better? Or would that just have been more bugs hitting QA in bigger batches?

Attaching a code-generating firehose to your dev process is very likely to overwhelm bottlenecks like testing, code review and merging – making the system as a whole slower and leakier. I call it “LGTM-speed”.

Tightening up those inner loops is even more essential when we’re using “AI” code generators. If we don’t, lead times get longer, releases get less stable, and the cost of change goes up. Worse software, later.

Good luck presenting that graph to the C-suite!

If you need help tightening up the inner feedback loops in your software development processes – with or without “AI” – that’s right up my street.

Visit https://codemanship.co.uk/ for details of training and coaching in the technical practices that enable rapid, reliable and sustainable evolution of software to meet changing needs.

Are You Training Your Junior Developers, Or Hazing Them?

One of the ways I feel lucky in my software development career is in how I got started.

I learned programming by building – well, trying to build – programs. Complete working programs – mostly simple games – on computers I had total control over.

I designed the games (remember graph paper?) I composed the music. I wrote the code. I tested the programs – perhaps not as thoroughly or as often as I should have. I copied the C30 cassettes. And I swapped them for other home-produced games on the playground. I even sold a couple.

I was the CEO, CTO, head of sales and marketing, product manager and lead developer, head of distribution, and QA manager of my own micro-tech company… that just happened not to make any real money, but that’s a minor detail.

I did it all, hands-on.

Then, after I stumbled out of university and needed money, I freelanced for a while, working directly with customers to understand their requirements, designing user interfaces, writing code, designing databases, testing the software – perhaps not as thoroughly or as often as I should have – packaging and deploying finished products, and answering the phone when users encountered a problem. Which they did. Often.

So I started my career as a full lifecycle software developer: requirements, design, programming, databases, testing, releases and operations.

Did I screw it up at times? Oh boy, yeah! But I learned fast. I had to to get paid. And, importantly, I got to see the whole process, work with a range of technologies, and wear a bunch of different hats.

And these were only mini projects. The world didn’t burn down when my SQL corrupted some data. The work was relatively low on risk, but high on learning. It built my competence and my confidence quickly.

When I got my first salaried job as a “software engineer”, I was then given what I would describe as a 2-year apprenticeship where I learned a lot of foundational stuff that would have been damned useful to know when I was freelancing.

And I was encouraged to try my hand at a wide range of things. My many screw-ups just never made it into any releases. The guardrails were very effective.

Importantly, while I was given a fairly free reign, I was closely supervised and mentored by developers with many years more experience. And I was given a lot of training.

Sadly, this is very different to how most developers start their careers these days. Instead of creating a wide range of learning opportunities on low-risk work, entry-level devs are confined to narrow, menial tasks – typically the ones “senior” developers would prefer not to do. “Training”, for too many, looks more like hazing.

It’s not at all uncommon for a junior dev to spend 6-12 months doing little else but fixing bugs on production systems, or working through SonarQube issues, or manning the support hotline. “It’s all they’re good for.”

New features? Product strategy? Talking to customers? Architecture? UX? Process improvement? The interesting stuff? That’s senior work.

Most often, it’s the risk that they’ll make mistakes that deters managers from giving junior developers too much freedom. But that’s a fundamental misjudgment. Mistakes and failure are integral to the learning process. The real risk is that you’ll grow developers who are afraid to try.

And while they’re painting the proverbial fences, it’s rare that they get much structured training or mentoring, either. Most organisations view senior developers as too valuable to “waste” on such things.

I see it differently. I think there comes a point in a developer’s career where the real waste is not letting them share their experience.

In this sense, there are “three ages” of a software developer, as their focus shifts from mostly learning, to mostly doing, to mostly teaching.

The job of a junior developer is to grow into a productive and well-rounded practitioner. And the productivity of a junior developer should be measured not by how much they deliver, but by how fast they grow. Month-on-month, year-on-year, what difference do we see in their capability and their confidence?

Businesses are so obsessed with cooking with the green tomatoes, they forget that with more time and more watering, they’ll grow into far more versatile red tomatoes.

Keeping them in a narrow lane, blinkered to the wider development process, stunts their growth. I’ve met many devs with decades of experience who were to all intents and purposes still junior developers.

When we frame it in those terms, the emphasis shifts from “What value can we extract from this junior dev today?” to “What potential can we add?”

In that light, it makes sense to structure their work around providing the most valuable learning opportunities. If they create tangible business value along the way, all the better. But that’s not the primary aim. The primary aim is to produce better software developers, and their work is a vehicle for that.

And if they somehow manage to burn the house down, that’s a you problem. How did their mistake make it into production?

The A-Z of Code Craft – F is for Freedom

Image

An anti-pattern I see often in software development is an organisation taking an A team – highly skilled, highly motivated – and somehow managing to squeeze a D performance out of them.

The problem is almost always that they won’t let the A team bring their A game. The team are micromanaged, often with dysfunctional processes and practices and other constraints imposed on them by management.

As a trainer and mentor of dev teams, I sadly often hear complaints like “We want to write more unit tests, but our manager won’t let us” or “We’re not allowed to push directly to the trunk” or “They don’t let us talk to the end users”.

Now, I would say “Why did you ask for permission?”, because I’m that kind of a developer. I will assume I was hired because they thought I’d do a good job (although I have been hired specifically not to do a good job, but that’s office politics for you). So I’m going to try to do the best job I can, the best way I know how.

And that means I’m going to continuously test the code. I’m going to continuously integrate my changes. I’m going to talk to end users. A lot.

One common characteristic of high-performing development teams is they have a considerable amount of autonomy to do what needs to be done to get good results for their customers. And here’s where it gets a little tricky.

Most people in positions of authority don’t willingly give away decision-making power. They find autonomy threatening. For all the talk of “servant-leaders”, they’re rare in reality.

Most often, when dev teams have high autonomy, it’s not because it was given, it’s because it was TAKEN.

But there are two sides to this bargain. If we get to work the way we think we should work, we have to deliver the goods. Teams who don’t deliver – perhaps because they’re being micromanaged – tend to get micromanaged even more closely. It’s a paradox. We have to earn the trust to be given the trust to do what needs to be done to earn that trust.

Our confidence – now there’s a word! – that we can deliver, and our ability to assert ourselves within the process, is a key enabler of achieving necessary levels of autonomy. It’s a quality A teams need to play an A game. Sorry folks. That’s the reality.

The mirror universe version of all this is those developers who insist on doing things badly. The thing about D developers is they can often genuinely believe they’re playing an A game (when I was new to the industry, I was inexperienced enough to believe this, too – I just didn’t know what an A game looked like).

Skills and education are pivotal here, as is a more democratic approach to setting the direction within the team. As much as I’d love to believe that my strong leadership was what delivered, I have to remind myself that – in reality – it’s the TEAM who deliver, and they do it the best way they can agree on.


If you’re serious about building your team’s capability to rapidly, reliably and sustainably evolve software to meet rapidly changing business needs, my Code Craft and Test-Driven Development live remote training workshops are HALF PRICE until March 31st 2025.

What Is ‘Leadership’ Anyway?

If you spend any time on LinkedIn you’re likely to bump into content about this thing called “leadership”. Many posters fancy themselves as experts in this mysterious quality. Many promote themselves as professional “leaders”.

I’m sure you won’t be surprised to learn that I think this is nonsense. And now I’m going to tell you why.

Leading Is Not What You Think It Is?

Let’s think of what that word means: “Lead the way”, “Follow my lead”, “Tonight’s leading news story”, “Mo Farah is in the lead”.

When you lead, it usually means that you go first.

Leading is distinctly different from commanding or inspiring, but that’s what many professional “leaders” mistake it for.

Leaders don’t tell people where to go. They show people the way by going first.

I don’t tell people to write their tests first. I write my tests first and show them how. I lead by example.

‘Leader’ Is Not A Job Title

Organisations appoint what they believe to be good leaders into roles where leading by example is difficult, if not impossible. They give them titles like “Head of” and “Director of” and “Chief” and then promote them away from any activity where they would have the time to show rather than tell.

The real leaders are still on the shop floor. It’s the only place they can lead from.

And, as we’ve probably all experienced, promoting the people who could set the best example into roles where they can’t show instead of tell is a very common anti-pattern.

We Are Not Your Flock

Another common mistake is to see leadership as some kind of pastoral care. Now, I’m not going to suggest that organisations shouldn’t take an interest in the welfare of their people. Not just because happy workers make better workers, but because they are people, and therefore it’s the right thing to do.

And executives could set examples – like work-life balance, like the way they treat people at all levels of the corporate ladder, and like how much they pay people (yeah, I’m looking at you, gig economy) – but that’s different to the way many of them perceive that role.

Often, they’re more like religious leaders, espousing principles for their followers to live by, while indulging in drug-fuelled orgies and embezzling the church’s coffers.

And the care that most people need at work is simply to not make their lives worse. If you let them, grown-ups will grown-up. They can buy their own massage chair if they want one. Nothing more disheartening than watching managers impose their ideas about well-being on to actual adults who are allowed to drink and drive and vote.

If people are having problems, and need help and understanding, then be there for that. Don’t make me go to paintball. I don’t need it, thanks.

The Big Bucks

Most developers I know who moved into those “leadership” roles knew it was a mistake at the time – for the organisation and for themselves – but they took the promotion anyway. Because “leadership” is where the big bucks are.

The average UK salary for a CTO is £85,000. For a senior developer, it’s £60,000 (source: itjobswatch.co.uk). But how senior is “senior”? I’m quite a senior developer. Most CTOs are junior by comparison.

And in most cases, CTO is a strategic command – not a leadership – role (something I freely admit I suck at). A CTO cannot lead in the way I can, because I set an example for a living. For all I know, there are teams out there I’ve never even met who’ve been influenced more by me than by their CTO.

‘Leader’ Is A Relative Term

When I’ve been put in charge of development teams, I make a point of not asking developers to do anything I’m not prepared to at least try myself, and this means I’m having to learn new things all the time. Often I’m out of my comfort zone, and in those instances I need leadership. I need someone to show me the way.

Leadership is a relationship, not a role. It’s relative. When I follow you, and do as you do, then you are the leader. When you do as I do, I’m the leader.

In the course of our working day, we may lead, and we may follow. When we’re inexperienced, we may follow more than we lead. But every time you’ve shown someone how you do something and they’ve started to do it too, you’re a leader.

Yes, I know. That sounds like teaching. Funny, that.

But it doesn’t have to be an explicit teacher-student relationship. Every time you read someone’s code and think “Oh, that’s cool. I’m going to try that”, you have been led.

It’s lonely at the top

For sure, there are many ways a CxO could lead by example – by working reasonable hours, by not answering emails or taking calls on holidays, by putting their trust in their people, or by treating everyone with respect. That’s a rare (and beautiful) thing. But it’s the nature of heirarchies that those kinds of people tend not to get ahead. And it’s very difficult to lead by example from a higher strata. If a CTO leaves the office at 5:30pm, but none of her 5,000 employees actually sees it, does it make a sound?

Show, Don’t Tell

So, leadership is a very distinct thing from command. When you tell someone to do something, you’re commanding. When you show them how you do it – when you go first – that’s leading.

“Show, don’t tell” would be – if it had one – Codemanship’s mission statement. Right from the start, I’ve made a point of demonstrating – and not presenting – ideas. The PowerPoint content of Codemanship training courses has diminished to the point of almost non-existent over the last 12 years.

And in that sense, I started Codemanship to provide a kind of leadership: the kind a CTO or VP of Engineering can’t.

Set Your Leaders Free

I come across so many organisations who lack technical leadership. Usually this happens because of the first mistake – the original sin, if you like – of promoting the people who could be setting a good example into roles where they no longer can, and then compounding that mistake by stripping authority and autonomy from people below that pay grade – because “Well, that’s leadership taken care of”.

I provide a surrogate technical leadership service that shouldn’t need to exist. I’m the CTO who never took that promotion and has time – and up-to-date skills – to show you how to refactor a switch statement. I know people who market themselves as an “Interim CTO”. Well, I’m the Interim Old Programmer Who’s Been Around Forever.

I set myself free by taking an alternative career path – starting my own company. I provide the workshops and the brown bag sessions and the mobbing sessions and the screencasts and the blog posts that you could be creating and sharing within your organisation, if only they’d let you.

If only they’d trust you: trust you to manage your own time and organise things the way you think will work best – not just for getting things done, but for learning how to do them better.

People working in silos, keeping their heads down, is antithetical to effective leadership. Good ideas tend to stay in their silos. And my long experience has taught me that broadcasting these ideas from on-high simply changes nothing.

Oh, The Irony

I believe this is a pretty fundamental dysfunction in organisational life. We don’t just have this problem in tech: we see it repeated in pretty much every industry.

Is there a cure? I believe so, and I’ve seen and been involved with companies who’ve managed to open up the idea of leadership and give their people the trust and the autonomy (and the resources) to eventually provide their own internal technical leadership that is self-sustaining.

But they are – if I’m being honest – in the minority. Training and mentoring from someone like me is more likely to lead to your newly inspired, more highly skilled people moving on to a company where they do get trust and autonomy.

This is why I warn clients that “If you water the plant, eventually it’ll need a bigger pot”. And if pushed to describe what I do, I tell them “I train developers for their next job”. Would that it were not so, but I have no control over that.

Because I’m not in charge.

Pull Requests & Defensive Programming – It’s All About Trust

A very common thing I see on development teams is reliance on code reviews for every check-in (in this age of Git-Everything, often referred to as “Pull Requests”). This can create bottlenecks in the delivery process, as our peers are pulled away from their own work and we have to wait for their feedback. And, often, the end result is that these reviews are superficial at best, missing a tonne of problems while still holding up delivery.

Image
Pull Request code reviews on a busy team

But why do we do these reviews in the first place?

I think of it in programming terms. Imagine a web service. It has a number of external clients that send it requests via the Web.

Image
Some clients can be trusted, others not

These client apps were not written by us. We have no control over their code, and therefore can’t guarantee that the requests they’re sending will be valid. There’s a need, therefore, to validate these requests before acting on them.

This is what we call defensive programming, and in these situations where we cannot trust the client to call us right, it’s advisable.

Inside our firewall, our web service calls a microservice. Both services are controlled by us – that is, we’re writing both client and server code in this interaction.

Does the microservice need to validate those requests? Not if we can be trusted to write client code that obeys the contract.

In that case, a more appropriate style of programming might be Design By Contract. Clients are trusted to satisfy the preconditions of service calls before they call them: in short, if it ain’t valid, they don’t call, and the supplier doesn’t need to waste time – and code – checking the requests. That’s the client’s job.

Now let’s project these ideas on to code reviews. If a precondition of merging to the main branch is that your code satisfies certain code quality preconditions – test coverage, naming, simplicity etc – then we have two distinct potential situations:

  • The developer checking in can be trusted not to break those preconditions (e.g., they never check in code that doesn’t have passing tests)
  • The developer can’t be trusted not to break them

In an open source code base, we have a situation where potentially anyone can attempt to contribute. The originators of that code base – e.g., Linus – have no control over who tries to push changes to the main branch. So he defends the code base – somewhat over-enthusiastically, perhaps – from bad inputs like our web service defends our system from bad requests.

In a closed-source situation, where the contributors have been chosen and we can exercise some control over who can attempt to check in changes, a different situation may arise. Theoretically, we hired these developers because we believe we can trust them.

I personally do not check in code that doesn’t have good, fast-running, passing automated tests. I personally do not check in spaghetti code (unless it’s for a workshop on refactoring spaghetti code). If we agree what the standards are for our code, I will endeavour not to break them. I may also use tools to help me keep my code clean pre-check-in. I’m the web service talking to the microservice in that diagram. I’m a trusted client.

But not all developers can be trusted not to break the team’s coding standards. And that’s the problem we need to be addressing here. Ask not so much “How do we do Pull Requests?”, but rather “Why do we need to do Pull Requests?” There are some underlying issues about skills and about trust.

Pull Requests are a symptom, not a solution.

Leading By Example

We’re used to the idea of leaders saying “Do as I say, not as I do”. Politicians, for example, are notorious for their double standards.

But the long-term effect of leaders not being seen to “eat their own dog food” is that it undermines the faith of those being led in their leaders and in their policies.

When we see public servants avoiding tax, we assume “Well, if it’s good enough for them…”, and before you know it you’ve got industrial-scale tax avoidance going on.

When we see government advisors breaking their own lockdown rules, we think “Actually, I quite fancy a trip to Barnard’s Castle”, and before you know it, lockdown has broken down.

When we see self-proclaimed socialists sending their children to private schools, we think “Obviously, state schools must be a bit crap” and start ordering prospectuses for Eton and Harrow.

And when we see lead developers who don’t follow their own advice, we naturally assume that the advice doesn’t apply to any of us.

If you want your team to write tests first, write your tests first. If you want your team to merge to trunk frequently, merge to trunk frequently. If you want your team to be kind in code reviews, be kind in your code reviews.

As Gandhi once put it: be the change you want to see in the world. Be the developer you want to see on your team.

This means that, among the many qualities that make a good lead developer, the willingness to roll up your sleeves and lead from the front is essential. Teams can see when the rules you impose on them don’t seem to apply to you, and it undermines those rules and your authority. That authority has to be earned.

This is why I’ve made damn sure that every single idea people learn on a Codemanship course – even the more “out there” ideas – is something I’ve applied successfully on real teams, and why I demonstrate rather than just present those ideas whenever possible. You can make any old nonsense seem viable on a PowerPoint slide.

As a trainer and mentor – and mentoring is a large part of leading a development team – I choose to lead by example because, after 3 decades working with developers, I’ve found that to be most effective. Don’t tell them. Show them.

This puts an onus on lead developers to do the legwork when new ideas and unfamiliar technologies need to be explored. If you need to get your legacy COBOL programmers writing unit tests, then it’s time to learn some COBOL and write some COBOL unit tests. This is another kind of leading by example. Getting out of your comfort zone can serve as an example for teams who are maybe just a little too comfortable in theirs.

And this extends beyond programming languages and technical practices. If you believe your team need a better work-life balance, don’t mandate a better work-life balances and then stay at your desk until 8pm every day. Go home at 5:30pm. Show them it’s fine to do that. Show them it’s fine to learn new skills during office hours. Show them it’s fine to switch your phone off and not check your emails when you’re on holiday. Show them that you don’t marginalise people on your team because of, say, their gender or ethnic background. Show them that you don’t act inappropriately at the Christmas party. Show them that you actively consider questions of ethics in your work.

Whatever it is you want the team to be, that’s what you need to be, because there are far too many people saying and not doing in this world.

Are Only 1 in 4 Developers Trusted?

Following on from my previous post about Trust & Agility, I ran a straw poll on the @codemanship Twitter account as a sort of litmus test of how much trust organisations put in their developers.

A new monitor is a decision of the same order of magnitude of risk of the proverbial “$100 decision” that I’ve used for many years now when assessing the capacity for trust – and therefore for decentralised decision-making – that agility requires.

If I wanted a new monitor for my home office, that would be entirely my decision. There was, of course, a time when it would not have been. That was when I was a child. If 13-year-old me wanted a new monitor, I would have had to refer that decision up to my parents.

When I got jobs, I made my own money and bought my own monitors. That’s called “being a grown-up”.

I’ve worked in organisations where even junior developers were handed corporate credit cards – with monthly limits – so they could “just go get it”, and not bother management with insignificant details. Smaller decisions get made when they need to be made, and they don’t get caught in a bottleneck. It really works.

So why are 3 out of 4 developers still not trusted to be grown-ups?

UPDATE:

A few people have got in touch giving me the impression that they took this to be literally about buying monitors or about company credit cards. These are just simple examples. They indicate a wider problem often. Developers who I’ve seen wait weeks for a monitor, or a laptop, or a software license, have tended to be the ones who “wanted to do TDD but weren’t allowed”, or who “wanted 20% but the boss said ‘no’ “, or who wanted to go to a conference but it was denied. These tend to be the teams that can’t self-organise to get things done. In my 20 years’ experience of Agile Software Development, the correlation has been very close between teams of developers who have to ask permission for a new monitor – just as an example (IT’S NOT ABOUT BUYING MONITORS!) – and teams who have to ask for permission to automate deployments or to talk to the end users directly.