The acyclic dependency principle states that dependencies between packages must be a directed acyclic graph (DAG)—that is, the dependency graph must have no cycle. If we do see a cycle in the graph, then it is a sign of a design problem.
When we encounter such a problem, we must refactor the code so that the specific dependent function is moved to a separate package. In this example, suppose that there's some code in package A that is used by the package internally and also used by package E. This dependency is basically E -> A.
We can then take this code and move it to a new package F. After this change, packages A and E would both depend on package F, effectively removing the cyclic dependency:
After this refactoring, when we make changes to C, we can just test the package with its dependencies, which would be D, E, and F only. Packages A and B can both be excluded.
In this section, we learned how to leverage semantic versioning to clearly communicate the impact of new versions of a package. We can use the Project.toml file to specify the compatibility of the current package with its dependent packages. We also reviewed a technique for resolving circular dependencies.
Now we know this, we will look into how to design and develop data types in Julia.