Monolith to Modular — Part 3: Managing Violations
Learn how to manage dependencies that cause violations when extracting your monolithic codebase to microservices architecture.
Join the DZone community and get the full member experience.Join For Free
Dependencies that violate your target module structure need to be resolved before code can be extracted from the monolith into the new module.
This is the third post in a series that will explore the challenges of migrating a monolithic code base to a modular architecture
Post 1 – Migrating from Monolith to Modular
Post 3 – Monolith to Modular – Managing Violations – (this post)
Post 4 – Monolith to Modular – Sizing and Estimating Scope
In our previous post, we described the simplest “Extract Module” scenario, in which the new module has no dependencies on the remaining monolith. This post describes the scenario where the proposed new module and remaining monolith are mutually dependent. The Levelized Structure Diagram below illustrates this.
There is a circular dependency between the monolith and the new module that has to be resolved before code can be moved into the new module (build systems don’t like module cycles).
Resolving the cycle requires identification of the dependencies that violate the target architecture. More specifically identifying the code that causes the violations and then refactoring to remove it.
Identifying the violating dependencies requires
An Action List that captures the steps to create the new module and move its content.
A Structure Specification that shows the new module in the target architecture.
A Dependency Breakout that lists the code causing the violations.
The Action List identifies the classes that are being extracted. In this example, there are just four actions in the list:
The violations will either be dependencies from the monolith into the code being moved or the other way around. It depends on how the target architecture positions the new module.
Which is why we need the Structure Specification. It specifies the relationship between the monolith and the new module. We can't use the Levelized Structure Diagram because it layers the modules based on the current dependencies and that might not be what we want as a target architecture.
If the monolith is dependent on the new module then any dependencies on the monolith from the code being extracted are the violations. These are shown as a dotted arrow in the Structure Specification diagrams below.
If the new module is to be dependent on the monolith, the violations are reversed.
The Dependency Breakout is a detailed list of all the contributing code constructs that cause the violations. The breakout for the new-module dependency on the monolith is shown below.
This breakout is a list of the code that needs refactoring to resolve the violations. Unlike the class moves in the Action List, the violating dependencies can be resolved incrementally.
When all the violations have been removed, the last task is to create the module and move the code into it from the monolith. The developer making these final changes can follow the Action List step by step to implement the module creation and class moves.
In the next post, we will describe how the violating dependencies can be used to build a backlog of work for planning and estimation.
You can see a worked example of Extract Module in this blog post. If you are interested in seeing how your software project looks in Structure101 Studio or Workspace, download a free trial.
Opinions expressed by DZone contributors are their own.