Editor’s Note: This blog post is the second in a series of articles about design patterns in continuous everything. These design patterns are modeled after the Gang of Four object-oriented design patterns, which follow a format for easy reference. Our first post focused on value stream management and what developers should consider for delivering DevOps performance.
Organizations often choose to integrate legacy systems with their replacements, either for the short term or indefinitely. But there’s a risk: connecting the old to the new can drag unwanted problems into what is a clean design. Legacy systems suffer from outdated protocols, data models, schemas and/or obsolete APIs. To interface with legacy systems, new(er) pipeline applications may need to support legacy features that don’t align with modern architectural techniques.
An anti-corruption layer (ACL) is a separate, compartmentalized point of integration between old and new systems. It translates requests between the legacy system and the new one, such that there is no need to tinker with the new system’s internals in ways that may undermine its newer design or cause unexpected problems.
Let’s review a few scenarios explaining the need for anti-corruption layers, however thin, in the realm of continuous everything (integration | testing | delivery | deployment | analytics | governance).
If your source control repository migrates from an on-premise installation to a cloud solution like Microsoft GitHub or AWS CodeCommit, pipelines should not be impacted during the time it takes to complete the migration.
Data from pipelines contribute towards key performance indicators (KPI) that enable teams to make informed decisions. While teams migrate their dashboard from an on-premise Elastic, LogStash, Kibana (ELK) installation to *aaS providers like Sumo Logic or AWS CloudWatch, pipelines should function normally.
Pipelines interact with an artifact repository to publish and retain versioned artifacts. While migrations can happen between artifact repositories like Sonatype Nexus Repository, JFrog Artifactory and Amazon S3, ACLs help pipelines to perform as expected without disruption.
In each of these scenarios, continuous everything pipelines are better served with the institution of ACLs that help teams release quality and secure software frequently and predictably.
ACLs are valuable in several types of business cases. Let’s look at the major types.
Legacy systems cannot be (cleanly) retired
Retiring legacy systems, even the most despised ones, can cause deep separation anxiety and loss of tribal knowledge. Big bang re-architecture initiatives have often sadly resulted in a BIG bang and nothing else. It may make sense for the business to decide to extend a legacy system’s life rather than risk a decision they might regret later.
Integration with legacy systems cannot be avoided
Let’s say that you did decide to live with legacy systems.
Try to avoid intense and risky integrations with them, unless of course there are technical or political use cases that require you to do so. There will always be some artificial requirements - keep digging till the real compelling reasons surface!
Conforming to legacy systems is not an option
Keep in mind that teams typically are reluctant to address (let alone debug or enhance) any piece of software that has been unceremoniously labeled as “legacy.” There is a legitimate fear behind this -- legacy systems are often riddled with lack of support, ridiculous documentation, preposterous quality issues and messed-up interfaces.
Assess the legacy system with fresh eyes. Be unbiased. There is an outside possibility that the system is perfectly acceptable and in their zeal to modernize, many teams tend to overlook the possibility.
However, if you do decide in favor of modernization, then the modern applications will need to integrate with legacy systems. The integration, along with a total or even partial migration, could take time. This is where an ACL holds things in place between the old and the new until the whole system cuts over to the new design and implementation.
Semantic differences between modern and legacy systems are significant
If you do decide to live with legacy systems and commission integrations of newer applications with them, you may find that the newer applications have major semantic differences with the legacy systems.
An ACL makes sense here, when the newer pipeline applications and the interfacing legacy systems have major differences. It may be overkill for minor semantics differences, but evaluate those differences thoroughly to prevent corruption from creeping into the new system’s design.
ACLs, however strategic, have their share of disadvantages.
An ACL is a key piece of the system and will need to be configured, released and monitored like the rest of the applications. This adds to the total cost of ownership of the entire system due to maintenance overhead.
An ACL, being an extra cushion, can add network latency to calls made between the participating subsystems.
An ACL is meant to exist temporarily during a migration, preventing a legacy system from corrupting a new design which will entirely replace it. It’s unlikely (albeit not impossible) that the business will decide to keep the old system and the ACL that connects it. Teams sometimes fall prey to over-investing in the ACL only to throw it away at the end. So, keep a hawk eye on the ROI (return on investment) during the ACL’s tenure.
A continuous everything pipeline doesn’t live on an island of its own. It must interact with external systems. This is where ACLs can translate its interfaces, while also protecting them. To release software from source code repository to production, modern pipelines might need to interact with legacy systems that are:
Internal: Owned-and-operated by the organization.
External: SaaS (software as a service), IaaS (infrastructure as a service) and PaaS (platform as a service) vendors, who are collectively referred to as *aaS. You may have little or no control over external systems that you didn't create.
As we said (and you surely know), legacy systems suffer from outdated protocols, data models, schemas and/or obsolete APIs. To interface with legacy systems, new pipeline applications may need to support legacy features that don’t align with modern techniques. Supporting the legacy features might corrupt the notion of a well-designed modern pipeline and ACLs help solve this problem nicely.
Here are a few case studies detailing the implementation of ACLs that will help you design better ACLs for continuous everything:
There are some patterns that are conceptually related to ACL. They are:
This pattern was described by Eric Evans in his book “Domain-Driven Design: Tackling Complexity in the Heart of Software.” Imagine the ACL to be a layer of padding that prevents the changing subsystem from leaking into the other. The intermediary padding in between subsystems translates the requests.
Additionally, these articles shed light on ACLs and can be used as references: