Evolving Architectures: Part VII
Parallel design and simplification are the yin and yang of architecture evolution. Simplification, as I've mentioned previously, is about having foresight, thus enabling evolution (i.e., architectural additions rather than changes). Parallel design is about reacting to changes in requirements as they come (no foresight) and making architectural changes.
Architectural changes are difficult by definition* — if we make a change to the architecture, things are going to break, starting with the build (or the continuous deployment if you have one), and will just deteriorate from there. An architectural change takes considerable time and involves risks when trying to put everything back together, which is exactly why we need parallel design.
As its name implies, this technique is about building the new via the old: routing old stuff to use in the new, and then removing the old. An analogy to help visualize this is the building of a new roadway interchange. In most cases, when a new interchange is built, the traffic isn't completely stopped. Instead, detours are used and old lanes are temporarily reassigned. Then the new lanes, bridges, etc. are built. Once complete, the traffic is routed to the new infrastructure, while the old infrastructure is renovated/removed/changed. Finally, the new interchange is complete. Sure, things slow down while the work is in progress, but it doesn't stop. The same is true for businesses — nobody would be willing to halt business while you get organized to make unforeseen architectural changes.
Parallel design is essential because no matter how good our initial designs are, business requirements change and with them, the architecture that supports them. Additionally, in many cases, solving the ultimate problem from the onset isn't worthwhile; it would just cost too much (time and money) to do so. Parallel design eases the pain of making significant architectural changes. Remember, software is there to serve the business, not the other way around.
Is parallel design just a technique without architectural implications? Well, yes and no. It can be used as a general technique regardless of the architecture. However, you can design with evolution in mind. SOA, REST, and EDA (or a combination of them) are all architectural approaches that support architectural evolution. If you invest in an architectural style that makes integration easy, it helps immensely when things change. It also localizes changes within defined boundaries (e.g., within the scope of a single service) and helps in the interim stage as you keep the old integration boundaries (events, contracts, etc.) intact while adding the new ones.
For instance, in one project I worked on, we made significant changes using parallel design. The company adopted a business model that required increasing the scale of the database that the solution had to handle from hundreds to millions of items. To do this, we had to change the back-end database (from files to Cassandra), and the way we distribute the work (from centralized to distributed). The product architecture was built on event-based SOA using context-based routing**. Expanding the database was a localized change within the components that had to work while keeping the rest of the system intact. The distribution was handled in the infrastructure by changing the distribution policy of events, again without affecting the existing event stream. Adding new events and components wasn't a problem, either. Routing events to new subscribers is a built-in feature of event-driven architectures, and the same goes for removing old subscribers when they are no longer needed. We did wait on deploying the interim results into production — as with the interchange analogy mentioned above, the interim product had performance problems while the work was in progress. Still, we kept everything connected and working while we gradually made a significant change.
In the real world, you probably use a mix of simplification, parallel design, and even leaps. We need to have several tools in our toolset. We can't afford to just have a hammer because, after all, not every problem is a nail.
*As I noted in the first post of the series: "Software architecture is the collection of decisions affecting the system's quality attributes, which have global effects and are hardest to change. Software architecture provides the frame within which the design (code) is built."
** The context-based routing was added as part of a previous architectural change. I mention this here as it is an example of simplification — an architectural element that was not part of the original architecture but was added later when the actual need arrived (when we had to support both internal operations as well as third-party integration).

