Chapter One: Perspective
Monolithic apps aka legacy applications evolve into a mess of of spaghetti code and features that support production workloads that run from airline systems to nuclear reactors to angrybird servers.
With the evolution of the cloud and the death of traditional enterprise vendors there is a huge wave of transformation sweeping across the entire industry neutering all the traditional heavyweight enterprise vendors unhinging apps from their app servers and running them on lighter weight runtimes or even serverless platforms.
This wave has unleashed a rethinking of application bundling, packaging and deployment constructs at the logical and physical level in terms of domain modeling and immutable deployments, all leading to microservices based architectures that provide the ability to rapidly innovate with people and code.
From a software perspective a monolith is a combination of business capabilities or bounded contexts all enmeshed with a core context. The process of transforming an app to a microservices based architecture entails separation of each of these bounded contexts into their own contexts.
1. Identify the seams of the application
2. Get started along a seam i.e. with a particular business capability. Ideally this should be something that must be isolated and adds business value.
3. Put fences around the existing feature function by writing tests and exposing an API
API Fencing and Contracts |
5. Ensure that both old and new services are talking to the mothership. Validate that the microservice satisfies all the parent dependencies via canary testing. Optionally the Microservice communicates with the parent through an anti-corruption layer. An anti-corruption layer allows for the refactored microservice domain to remain pure. Think of it as a translator that speaks the languages of both the parent and the child.
6. Route traffic to both the monolith and the microservice with Blue/Green deployment.
7. Wrap the older feature code within the monolith with a feature flag disabled by default.
8. Once the microservice is functioning as expected then disable the same feature in the monolith.
9. Delete the Feature Flag and the code associated with the feature in the monolith.
10. You have now successfully decomposed the business capability from the parent.
11. Scrub and repeat for all bounded contexts.
Refactoring Legacy code with an Anti-Corruption Layer https://leanpub.com/Practicing-DDD |
Chapter Three: Identify the seams
One of the most difficult aspect of transformation of an app is figuring out where the seams lie.
The best way to do this is to talk to maintainers and users of the application. Users will describe difficulties in interacting with the application giving hints into which portions of the app need to be rewritten. The app maintainer has intimate details about the sections of code that are stable and those that change very frequently.
Static code analysis with code coverage tools will provide insight into code complexity, external dependencies and coupling. Runtime code analysis with logs and sequence diagrams will provide a map of data of event flows through the application.
Exercises like event storming will map out all the epics and user flows through the monolith. Event Storming is a useful way to do rapid "outside-in" domain modeling: starting with the events that occur in the domain rather than a static data model. Run as a facilitated workshop, it focuses on discovering key domain events, placing them along a timeline, identifying their triggers and then exploring their relationships. Event Storming provides a way to discover the big picture, with the goal of collectively understanding the domain in all of its complexity, before diving into solutions.
The onus is not to do a lot of upfront analysis; rather do just enough to get started. It is important to pick one and get started. Let the process of doing fuel the discovery. In many ways this is similar to hill climbing algorithms.
Chapter Four: People and Process Aspects of Transformation
It is critical NOT to ignore the softer side of app transformation. The 12 tenets of lean app transformation as laid out in An Agile Approach To A Legacy System are1. Don't reproduce legacy
2. Always ask the user what the problem is
3. Refactor a legacy application by delivering business value
4. Incrementally build trust - prove that you can do the hardest part of the problem
5. Build a small, self-selected team
6. Don't get hungup on process
7. Involve the whole team with larger refactorings so the team can move on as quickly as possible
8. Effective Teams need breakpoints
9. Don't sat no, say later. Treat politics as a user requirement
10. A System that connects to a legacy system must be tested using live feeds
11. Engage users and they not only won't they turn it off, they will fight some of your battles for you
12. Keep giving a good team motivated by giving them new hard problems - don't waste a good team
Risk Profile with the Pivotal Way |