Introducción de las estrategias de migración
Si hay algo por lo que todos pasamos alguna vez, es por heredar y mantener un proyecto. Puede ser un proyecto antiguo de nuestra empresa, un proyecto que ha llegado de un cliente descontento con su anterior proveedor… etc. El mayor problema que esto supone es que habitualmente nos encontramos con proyectos desarrollados en tecnologías antiguas o desactualizadas, poco mantenidos, con un estilo o unas prácticas que no nos acaban de gustar (los programadores somos todos un poco especialitos en esto) y lo peor de todo: sin tests.
The word that always comes to mind when dealing with these legacy projects is “legacy code”, which as Michael Feathers rightly said:
Legacy code is code without tests
Michael Feathers - Working effectively with legacy code
In reality it is much more than that (which is not little), since they are usually poorly or poorly documented projects (tests are always the best documentation), with outdated or obsolete versions of languages, frameworks and libraries, and often difficult to get back on track, since they are based on unfriendly practices for testing or refactoring. In a nutshell: accumulate a large technical debt.
Another important factor is that the project is usually the source of income for a company that cannot afford to stop machines indefinitely (as Evernote once did) to clean up all technical debt and rethink the foundations of its revenue stream.
If large refactors are often discarded, rewriting is something that is usually only considered by the technical team (sometimes from a point of view that is not very empathetic towards the client).
Other times the problem is not so much the code but that we have to build a software on a data source that may not fit in the best way with our project. Or with a poor design that can be improved, but requires a lot of effort and dedication and only after demonstrating that the new approach is better, the customer would be willing to accept the change.

Faced with these situations, what options do we have?
In my experience, many times it has been decided to maintain the legacy project and either because of pressure from the development team, the difficulty to hire people to take over the project in the current state or because of growth problems due to the state of the project, it has been decided to take on a new project. progressive migration.
This is nothing more than starting to develop new parts of the project on a modern, best-practice stack, but still relying on the old project. These migrations can take forever, but they often breathe new life into a project that was dying, and with good planning it is possible to stop relying on the old project in the medium term.
Today I would like to talk about two progressive migration strategies that I have relied on when I have had to tackle this type of task: Strangle Fig y Anticorruption Layer.
Strangler Fig Application (Ficus Estrangulador)
This strategy was proposed by Martin Fowler in 2004. Although it was initially called Strangler Application, was later renamed to StranglerFigApplication in 2009 in order to avoid the negative connotation of the word Strangler (choke):
bliki: StranglerFigApplication
When Cindy and I went to Australia, we spent some time in the rain forests on the Queensland coast. One of the natural…
This migration technique consists of interposing a facade between the client and the system to be migrated. From the inside, we will progressively start to migrate parts of the project legacy to the new system, and it will be the front end that will redirect the client to the new or old system as needed.

This will allow us to perform a migration without the pressure of having to “stop machines” and leave the project on stand-by, allowing us to prioritize the migration of the most critical parts regardless of their dependencies, since we will be able to satisfy them against the legacy system.
It's not all advantages, of course. The use of this strategy may increase response times during the migration, as well as infrastructure costs, since we will at least need to separate the legacy system from the new one, in addition to having a layer in charge of distribution. Still, this is preferable to leaving our project stagnant.
This strategy is being adopted by frameworks such as Symfony to facilitate the migrations from other frameworks. In addition, there are numerous documented success stories who have followed this practice.
Anticorruption Layer
The next strategy or pattern that we are going to look at is the Anticorruption Layer (abbreviated as ACL) proposed by Eric Evans in his book Domain-Driven Design: Tackling complexity in the heart of software.
Basically, the ACL is a layer that will be responsible for translate between the legacy data model and the new data model. It is very similar in mission to the adapter pattern, which we have already talked about in the past, but applied to data in this case.
But not only that, this layer can also implement some security checks, return default values in case they don't exist in the original system, throw more specific exceptions for error cases or even implement a circuit-breaker if the problem is due to service availability.

When to use Anticorruption Layer?
We can see the answer in the words of Eric Evans himself:
If your application needs to deal with a database or another application whose model is undesirable or inapplicable to the model you want within your own application, use an Anticorruption Layer to translate to/from that model and yours.
Eric Evans - Domain-Driven Design: Tackling complexity in the heart of software
Or in the words of Vaughn Vernon, author of Implementing Domain-Driven Design:
Even if you are able to avoid creating a Big Ball of Mud by employing DDD techniques, you may still need to integrate with one or more. If you must integrate with one or more, try to create an Anticorruption Layer against each legacy system in order to protect your own model from the cruft that would otherwise pollute your model with the incomprehensible morass.
Vaughn Vernon - Domain-Driven Design Distilled
That is, whenever we need our system to speak to with another system whose data model is not the desired one, or even if we are inheriting a database on which to build a new project, we can use an ACL for translate from the old model to the new one, avoiding legacy contaminate our project.
ACL use cases
This technique is widely used in microservice architectures where there are different versions of the communication APIs and even of the data models (remember that each microservice has its own database with its own schema).
One problem that can result from the practice of migration by means of StranglerFigApplication is that sometimes it will be necessary for there to be communication between the legacy project and the new one, so the use of this technique combined with the previous one is more than recommendable.
Another use case for which I have personally applied this strategy has been to deal with NoSQL databases that have in the same collection documents with different schema. It is especially useful to use an ACL that homogenizes the schema of all the documents so that they fit properly with the domain objects.
Conclusion
Although it may be tempting to propose an entire rewrite of an outdated project, it is important to assess our options first. It will not always be possible to tackle this type of project, but we must know what other alternatives we have.
This is just a sample of a couple of strategies that I personally have found useful in the past, but they are not the only ones, we will talk about others in the future.
Saludos!

