Agile
Agile is often presented as a sharp break with what came before.
Looking back, it seems more accurate to say that it refined a set of practices that were already emerging: RAD, iterative development, evolutionary design, and prototype-led delivery.
The question was not how to build software quickly. Developers had already shown that they could do that. The real question was how to do it without letting exploratory code harden into fragile products.
In this post, I am using Agile in the older software-development sense: a developer-led attempt to make iterative development disciplined and sustainable, rather than the later corporate or ceremonial use of the term that many original signatories came to reject.
The Silver Bullet
Software development has a habit of rediscovering the silver bullet.
Every few years, a new language, framework, process, or tool is presented as the breakthrough that will finally make software development fast, reliable, and manageable. Businesses invest in it. Developers adopt it. For a while, the results can look impressive. Progress becomes more visible, feedback becomes faster, and certain old frustrations begin to fall away.
But the apparent breakthrough is often narrower than it first appears. What has usually been reduced is accidental complexity: awkward tooling, slow feedback loops, mismatched processes, or friction in implementation. Those are real improvements, but they are not the same as solving the essential complexity of the problem itself.
Essential complexity belongs to the domain. It lies in the rules, constraints, exceptions, policies, language, and interactions that make the software worth building in the first place. No methodology or tool can remove that entirely. At best, it can help us see it more clearly and respond to it more effectively.
You cannot solve essential complexity by merely reducing accidental complexity, and that includes changes in methodology.
This is why so many silver bullets disappoint. Early progress is mistaken for mastery of the problem. The accidental difficulty has been lowered, and that feels like genuine transformation. But once the deeper complexity of the domain begins to assert itself, the limits of the new approach become obvious. What looked like a solution turns out to have been a useful tool, but not a miracle.
RAD was one such moment.
RAD and the Rise of Visible Software
One of the clearest examples of this pattern was Rapid Application Development.
RAD emerged as a response to long, rigid, plan-driven lifecycles and put much more emphasis on short cycles, adaptation, prototypes, and continuous user involvement. That shift mattered because it changed what stakeholders could see. Instead of waiting months for documents, specifications, and distant milestones, they could see screens, reports, and partial systems much earlier. Working software began to drive the conversation. That was a real improvement.
Once users can interact with something concrete, feedback improves. Ambiguities surface earlier. Misunderstandings become visible sooner. Requirements become less theoretical and more grounded in use. In that sense, RAD solved real problems.
But it also created a new risk. The same visibility that made rapid prototyping so effective made it easier for stakeholders to mistake movement for maturity. Once something looks like software, and behaves enough like software, people begin to treat it as software. The prototype starts to carry expectations that belong properly to a product.
This was the double edge of RAD. It reduced friction and improved feedback, but it did not remove the deeper complexity of the problem. If that distinction was lost, the rapid early gains could become the beginning of later structural failure.
Same-Language Prototyping
This is where the idea of same-language prototyping becomes important.
Instead of building a disposable mock-up in one environment and then rebuilding the product properly in another, teams often built the prototype in the same language as the intended product. That made practical sense. One language, one toolchain, one path from experiment to delivery.
But it also created a temptation. If the prototype already runs, already demonstrates business value, and already satisfies some stakeholder requests, why not keep extending it? The answer, of course, is that a prototype and a product are not the same thing. A prototype exists to answer questions quickly. A product must remain understandable, testable, and changeable under long-term pressure.
RAD's weaknesses were often described in exactly these terms: speed and visibility could come at the expense of design quality.
In a very real sense, the tension still exists today. Story points are meant to be local planning tools for developers, not proxies for hours. Yet they are often repurposed as management metrics. The same pressure returns: progress is visible, but quality gradually declines.
Incidentally, that may be one reason Agile initiatives so often fall short in practice. Businesses understandably want predictability around budget, schedule, and functionality, while iterative development assumes that understanding and priorities will change. Something therefore has to remain flexible. Ideally that is scope, rather than allowing quality to become the hidden variable.
When the Prototype Becomes the Product
This is the point where technical debt enters the story.
Once feature development gathers momentum around code that was written for exploration rather than durability, the system begins to resist change. Early wins conceal deeper structural weakness. The team keeps moving, but it is moving on poor foundations.
That pattern now feels familiar because the industry has seen it many times. Stakeholders mistake progress in demonstration for progress in design. Developers keep layering features on top of something that was never properly shaped to carry them.
The result is software that appears responsive in the short term, but grows brittle over time.
The Disciplinary Response
The answer was not to abandon iteration. The answer was to discipline it.
That is why later lightweight methods placed much more emphasis on practices such as refactoring, short feedback cycles, automated testing, and evolutionary design. The goal was to preserve the benefits of rapid delivery without accepting prototype-level quality forever.
Martin Fowler's work from this period consistently ties agility to refactoring and evolutionary design, not to the passive acceptance of design decay.
Extreme Programming is especially important here. XP assumed that requirements would change, but paired that assumption with technical practices intended to keep the codebase malleable: small releases, testing, refactoring, and close collaboration. That was a meaningful step beyond crude prototype-led evolution. It was an attempt to keep the speed while avoiding the chaos.
The Agile Manifesto
Seen in that light, the Agile Manifesto looks less like a sudden invention and more like a convergence.
The 2001 Snowbird meeting brought together practitioners from XP, Scrum, DSDM, Crystal, Adaptive Software Development, Feature-Driven Development, and related lightweight approaches.
Agile did not invent iteration. It gave a clearer voice to methods that were already trying to retain adaptability without surrendering design integrity.
Agile was an attempt to make fast-moving development sustainable.
Conclusion
Many modern practices emerged from that earlier period of experimentation: iterative delivery, visible progress, rapid feedback, refactoring, and automated testing.
Agile can be understood as part of a broader effort to keep what was valuable in prototype-driven development while reducing the damage caused when rough code was allowed to become permanent.
That is the real historical link. Agile was not the beginning of iteration. It was part of the long attempt to make iteration disciplined enough to trust.
It was a methodology shaped by developers, for developers.