T*D
Three practices for high-performing teams
Over the years, working with many software teams, I've often stumbled into ways of working long before I knew they had a name. At the end of the 1990s, I was already doing what I would later learn was called agile software development. I’d run what looked a lot like Scrum without knowing the framework existed. I’d worked with teammates on the same machine before discovering that pairing or mobbing were recognised practices.
Later, when I found the literature, I was almost relieved — the things we’d discovered through experience and necessity had been seen before, named, and refined. We weren’t just making it up. This isn’t rare. When we remove friction, seek quality, and want to deliver value quickly, certain patterns tend to emerge. Teams gravitate towards them because they work.
Today, I call the union of three of those patterns T*D: test-driven development, trunk-based development, and team-focused development (pairing or mobbing). Not as a set of rules to start with, but as the natural result of striving for high performance.
Test-Driven Development
Test-driven development (TDD) didn’t start as an abstract theory. Its roots are in the early XP (Extreme Programming) movement in the late 1990s, where Kent Beck emphasised writing tests first to guide design. But the idea of tests shaping code goes back even further — to NASA’s on-board Shuttle software work in the 1980s, and to hardware engineers who’d often create test harnesses before building circuits.
In a 2001 interview, Kent Beck mentioned:
“TDD is something I rediscovered by studying the literature and watching what good programmers do. It’s not a new invention, but a natural pattern that emerged in effective development.”
Later, Beck gave more context on TDD’s origins, linking it to very early programming practices:
“The original description of TDD was in an ancient book about programming. It said you take the input tape, manually type in the output tape you expect, then program until the actual output tape matches the expected output. After I'd written the first xUnit framework in Smalltalk I remembered reading this and tried it out. That was the origin of TDD for me. When describing TDD to older programmers, I often hear, 'Of course. How else could you program?'
But the idea goes far deeper, with roots in the 1960s and beyond. The 1968 NATO Software Engineering Conference report included this perspective:
“A software system can best be designed if the testing is interlaced with the designing instead of being used after the design. Through successive repetitions of this process of interlaced testing and design the model ultimately becomes the software system itself. I think that it is the key of the approach that has been suggested, that there is no such question as testing things after the fact with simulation models, but that in effect the testing and the replacement of simulations with modules that are deeper and more detailed goes on with the simulation model controlling, as it were, the place and order in which these things are done.”
Edsger W. Dijkstra famously argued for this integrated approach in The Humble Programmer (1972):
“Today a usual technique is to make a program and then to test it. [...] The only effective way to raise the confidence level of a program significantly is to give a convincing proof of its correctness. But one should not first make the program and then prove its correctness, because then the requirement of providing the proof would only increase the poor programmer’s burden. On the contrary: the programmer should let correctness proof and program grow hand in hand. [...] If one first asks oneself what the structure of a convincing proof would be and, having found this, then constructs a program satisfying this proof’s requirements, then these correctness concerns turn out to be a very effective heuristic guidance.”
Even earlier, in 1957, D.D. McCracken highlighted the importance of involving customers early in defining tests:
“[...] it is highly desirable that the ‘customer’ prepare the check case, largely because logical errors and misunderstandings between the programmer and customer may be pointed out by such procedure. If the customer is to prepare the test solution it is best for him to start well in advance of actual checkout, since for any sizeable problem it will take several days or weeks to prepare and calculate the test.”
When teams push for reliability, maintainability, and the ability to change code without fear, TDD emerges almost naturally. Without it, changes get riskier over time and delivery slows. High-performing teams can’t afford that.
Resistance often comes from the belief that it’s slower, from a lack of skill in writing good tests, or from organisational pressure to ‘just get the feature out’. Ironically, the longer-term cost of skipping it is exactly the slowdown people fear.
I see TDD as a natural outcome of working in an agile way. The very first principle of the Agile Manifesto states, “Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.” Continuous Delivery relies on Continuous Integration — which means frequently integrating small changes into the main development branch (more on that below). To do this effectively, changes need to be small, well-tested, and high quality. TDD, with its steady cycle of red-green-refactor, creates a natural rhythm that supports this approach perfectly.
Trunk-Based Development
Before it had a name, trunk-based development was just… how people worked. Grady Booch was advocating frequent integration back in the late 1980s. In the 1990s and early 2000s, most teams used a single branch (often literally called ‘trunk’ or ‘main’) and committed directly to it.
Martin Fowler and others in the XP community crystallised CI as a practice: integrate into the mainline at least daily, with an automated build verifying each change. Jez Humble and Dave Farley’s Continuous Delivery then pushed the idea further, tying it to deployment pipelines and small, safe changes.
Fowler wrote in 2006:
"Continuous Integration doesn’t get rid of bugs, but it does make them dramatically easier to find and remove."
Long-lived feature branches became common later, encouraged by tools like Git, but also brought painful merges, integration hell, and delayed feedback. Leave code isolated for days and the merge will be messy. Leave it for weeks and it becomes a gamble. Frequent integration keeps the system cohesive, the build healthy and the product always in a releasable state.
When teams aim for rapid delivery, early detection of problems, and reduced merge risk, they inevitably move towards trunk-based development. It’s hard to maintain high performance if integration is painful and infrequent.
The common pushback is fear – fear of breaking the build, fear of losing the “safety” of a long-lived branch. But that safety is illusory. Merging two weeks of work all at once is far riskier than integrating ten minutes after writing a change. The practice only works when supported by strong automated tests and deployment automation, which is why it naturally appears in teams that already value fast, safe feedback loops.
Industry data supports this. DORA’s annual State of DevOps reports consistently find TBD as a key differentiator for elite performers. Google, Facebook and Amazon all use TBD-like workflows to sustain rapid delivery. Where testing and automation are strong, TBD isn’t an extra burden – it’s the default.
Unfortunately, many teams of younger developers, brought up on GitFlow-style workflows, see trunk-based development as heresy. They think it’s a reckless plunge into production without any safeguards. It’s hard for them to imagine working this way because they’ve never experienced it.
More often than not, they point to regulated industries where auditors and regulators demand strict sign-offs and audit trails, assuming that makes trunk-based development impossible. In reality, it’s quite the opposite — TBD is actually the perfect partner in those environments, helping teams deliver safely with tight controls and rapid feedback.
Team-Focused Development
Pair programming has a history going back decades. In the 1960s, NASA engineers often worked in close, real-time collaboration on mission-critical code. Fred Brooks described something akin to it in The Mythical Man-Month (1975), where he observed that code inspections and close collaboration were more effective than solo work for catching defects.
In the 1990s, XP formalised pairing as a core practice. Later, mob programming (aka ensemble programming or software teaming) emerged, where the entire team works together on one task at a time. Woody Zuill, who coined the term, said:
"All the brilliant minds working on the same thing, at the same time, in the same space, and at the same computer."
When teams aim for high quality, shared understanding, and resilience against knowledge silos, they tend to adopt more collaborative forms of working. High-performing teams can’t afford for knowledge to be trapped in one person’s head, or for code to be built in isolation and then ‘thrown over the wall’.
The objections sound familiar: it looks expensive, it feels socially intense, managers worry about “efficiency” in the narrow sense of people typing more lines. But those measures miss the bigger picture. Social programming reduces rework, improves bus factor, and raises quality before defects ever exist.
Pair and mob programming have strong backing from both research and industry experience. Studies like Laurie Williams and Robert Kessler’s work in 2000 found that paired programmers produce between 15% and 50% fewer defects than solo developers, resulting in higher-quality code and less rework.
Microsoft research also shows that paired developers write cleaner, more maintainable code thanks to continuous design discussion. Beyond code quality, these practices accelerate onboarding and spread knowledge quickly across teams — something mob programming pioneer Woody Zuill highlights as key to building resilient teams without knowledge silos.
On top of that, paired programmers often report higher job satisfaction and motivation, fostering a collaborative culture rather than isolation. Companies like ThoughtWorks and Pivotal Labs have embraced these approaches, crediting them with better team alignment, faster problem-solving, and consistently higher delivery quality.
The natural landing point
T*D isn’t a checklist to impose from the start. It’s the set of practices we almost can’t help adopting when we’re serious about high performance. The history of each shows that they didn’t begin as theoretical ideals. They came from teams solving real problems at the sharp end of delivery.
When we care equally about speed, quality and shared ownership, test-driven development, trunk-based development and team-focused development don’t feel like extra work. They feel like the only sensible way to work.
References
Test-Driven Development
Kent Beck, Test Driven Development: By Example (2002)
Steve Freeman and Nat Pryce, Growing Object-Oriented Software, Guided by Tests (2009)
David Astels, Test Driven Development: A Practical Guide (2003)
Roy Osherove, The Art of Unit Testing: With Examples in .NET (2009)
Robert C. Myers, Essential Test-Driven Development (2024)
Continuous Integration & Trunk-Based Development
Peter Duvall, Continuous Integration: Improving Software Quality and Reducing Risk (2007)
Jez Humble and David Farley, Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation (2010)
Paul Hammant and others, Trunk-Based Development - trunkbaseddevelopment.com
Pair Programming & Mobbing
Laurie Williams and Robert Kessler, Pair Programming Illuminated (2002)
Woody Zuill, Mob Programming: A Whole Team Approach (2020)
Llewellyn Falco and Woody Zuill, Mob Programming Guidebook (2019)
The Mob Mentality Show - https://www.mobmentalityshow.com/
Software Craftsmanship & Design
Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship (2008)
Martin Fowler, Refactoring: Improving the Design of Existing Code (1999, 2nd ed. 2018)
Michael Feathers, Working Effectively with Legacy Code (2004)
DevOps & Organizational Change
Gene Kim, Jez Humble, Patrick Debois, and John Willis, The DevOps Handbook (2016)
Forsgren, Jez Humble, and Nicole Forsgren, Accelerate: The Science of Lean Software and DevOps (2018)
Gene Kim, The Phoenix Project: A Novel about IT, DevOps, and Helping Your Business Win (2013)
Foundational Essays & Papers
Edsger W. Dijkstra, The Humble Programmer (1972, essay)
Kent Beck, Extreme Programming Explained: Embrace Change (1999, 2nd ed. 2004)
Lean Software Development
Mary and Tom Poppendieck, Lean Software Development: An Agile Toolkit (2003)
Mary Poppendieck and Tom Poppendieck, Implementing Lean Software Development (2006)
Key Blog Posts & Online Articles
Robert C. Martin ("Uncle Bob") - Clean Coder Blog (blog.cleancoder.com)
"The Cycles of TDD" (2014) - https://blog.cleancoder.com/uncle-bob/2014/12/17/TheCyclesOfTDD.html
"Is TDD Dead? Final Thoughts about Teams" (2014) - https://blog.cleancoder.com/uncle-bob/2014/06/17/IsTddDeadFinalThoughts.html
"Giving Up on TDD" (2016) - https://blog.cleancoder.com/uncle-bob/2016/03/19/GivingUpOnTDD.html
Minimum Viable Continuous Delivery
MinimumCD.org
Martin Fowler
martinfowler.com
Dave Farley (Modern Software Engineering YouTube channel)
Regular videos on continuous delivery, TDD, and modern software engineering practices - https://www.youtube.com/@ModernSoftwareEngineeringYT


Ciao Andrea, there's a subtle typo at the bottom: "Engieneering". Thanks :)