Mixing Agile and Waterfall Development


The Scaled Agile Framework is being adopted extensively throughout the industry. In most large enterprises, however, there is a transition period wherein many existing programs or teams will continue to apply the waterfall model, while others are moving quickly to agile delivery. Moreover, these programs are not independent and some degree of organizational and code level dependencies exist. This can lead to conflicting methods and expectations and can even put common delivery objectives into jeopardy. This article provides guidance as to effective practices to enable productive interactions between these two approaches.


To establish effective collaboration between such diverse groups, the primary goal is to validate all assumptions as early —fail-and-fix early and often—rather than discovering significant problems near the end, which could dramatically affect the expected outcome. There are four suggested mechanisms that teams can use to address this mixed mode of operation.

Joint Requirements and Design Workshops

Even though waterfall is largely based on Big Upfront Requirements and Design [1], there is no reason why these activities cannot be conducted in a highly collaborative manner. It is much easier to identify and resolve dependencies when representatives of both Agile and waterfall groups meet together in front of the whiteboard. Here are few tips for running such workshops effectively:

  • Each team should prepare for the meeting. Don’t necessarily pursue all dependencies, but first, try to build a holistic view of the entire initiative. The dependencies will emerge. The result is understanding and context for effective joint meetings.
  • Use whiteboards, walls, and flipcharts extensively [2].
  • Use Specification by Example [3] to derive concrete system behaviors and eliminate ambiguities whenever possible.  Focus on example system behaviors and the system interactions necessary to realize them.  Use a “Demo-driven” approach asking, how would one demonstrate the integrated, working system. Those examples are captured and then used by both groups during development.
  • Identify dependencies and plan for integration points and mechanisms.

Test Doubles and Designing to Interfaces

Test Doubles (e.g., proxy, mock) are simplified versions of depended-upon components.  Doubles enable developers to test integration points early before real solutions exist, provided the components communicate across a well-defined interface. With this approach, all development teams are responsible for providing both their ultimate end solution and a corresponding test double.  Teams can mature test doubles over time providing more behavior and better fidelity.

Since doubles simulate interfaces, the interfaces should be defined at the design workshop (see above). Ideally, the slower, waterfall teams create test doubles for the Agile teams. If this is not possible, the Agile teams can create them, but their result should be reviewed by their waterfall counterparts to ensure they are testing valid assumptions.

Frequent Integration

Frequent integration tests the solution and the assumptions. As Figure 1 illustrates, “frequent,” means far more frequently than once near the end of the project. Test doubles grow in maturity and fidelity over time, gradually replacing the mocked behavior with the real solution.

Figure 1. Physical integration via interfaces. Notice that this is not constrained to iteration boundaries.

Integration can be full or partial, but in either case what’s important is that teams integrate without fear. If there are integration failures, teams should be driven by innate desire to fix the integration errors first, and only then return to their own agenda.

Design Patterns and Refactoring

Most system architects who operate in non-Agile environments use design patterns in their systems. However Agile has a slightly different goal for usage, which is to make the system more easily accommodate changing requirements. Certain system behaviors (both internal and external) will inevitably change over the time of implementation. Patterns provide design approaches that are more immune to change and lend themselves better to refactoring. For example, the Open-Closed Principle [4] suggests that variability be encapsulated and can be changed in relative isolation from the rest of the functionality.

Figure 2. Adapter between the interfaces gives agile teams a degree of freedom in evolving functionality and extending a design

Other patterns such as Bridge, Adapter, Decorator, and Chain of Responsibility [5] are also helpful as they encourage good separation of concerns. Factories [6] foster the use of test doubles, testability, and early integration as an instantiation of the entities can be separated from their use. Facade pattern fosters early validation of integration with legacy systems, etc. In this way, Design Patterns help isolate variability, which will likely be higher when coupled with the delayed integration and learning with waterfall teams.

Learn More

[1] Big Design Up Front.

[2] Larman, Craig, and Bas Vodde. Practices for Scaling Lean & Agile Development: Large, Multisite, and Offshore Product Development with Large-Scale Scrum. Addison Wesley, 2010.

[3] Adzic, Gojko. Bridging the Communication Gap: Specification by Example and Agile Acceptance Testing. Neuri Limited, 2009.

[4] Open-Closed Principle.

[5] Shalloway, Alan, and James Trott. Design Patterns Explained: A New Perspective on Object-Oriented Design.Addison Wesley, 2004.

[6] Bain, Scott. Emergent Design: The Evolutionary Nature of Professional Software Development. Addison Wesley, 2008.


Last update: 12 October 2018