Dependencies – often underestimated thing in software development. When you are building the projects you build them from components, classes, routines etc. And each of such a components are always dependent on a certain other things (the root ones usually are just dependent on the system units/classes/components). When you have a completed project it is always a good thing to check out the dependencies of your things. In this topic I will only talk about one of the ways how you can analyze the module dependencies for Delphi projects.
Maybe you already tried to guess that you can do that with tools like GExperts or CnPack uses cleaner. While these tools allows you to analyze the things (GExperts) and remove unneeded uses items (CnPack) they actually does not give the overview of your project as a whole!
So the way of analyzing the project for the dependencies is the following:
- Decide which project you want to analyze;
- Use Delphi Dependency Scanner to parse the dependencies;
- Export the Gephi CSV formatted graph edges;
- Open the exported file in Gephi and apply required visualization;
- Inspect your graph!
Let’s take the Spring4D as an example for the analysis. I used the release 1.2 branch for this example. So first what we need to do is adding the spring units to the Delphi Dependency Scanner and then scanning them. After we have done that we will get the following result:
Sure we see there is a lot of circular dependencies between implementation and interface units, but that’s acceptable for a library like Spring4d. There are arguments to have these thing like that (probably). But what I can say about normal projects is that you should avoid the circular references in your sources in any way!
Once we have the result we can save this to the Gephi CSV (upper right corner, button in toolbar) and then we open it using the Gephi tool. After confirming the import dialog you will get such a nice picture of the Graph (at least with my defaults and version of the Gephi tool). You can consider also using the yEd option.
Holy crap you will think! But wait. We can improve the graph by doing the following:
- In Layout window select Force Atlas and enter 25000 for the Repulsion Strength. Run the layout process, wait a bit and then stop it;
- Turn on the unit names and selection coloring (it will highlight the edges in different color depending on the direction of the dependency) as its shown below:
- You can use the Label Adjust in layout window to fix the label overlapping and perform any appearance changes;
- You can export the result as PDF if you like (probably you will need to adjust the preview settings before). The example of mine can be found there: Spring4D Graph.pdf.
So now you can browse the graph, click on a interesting nodes and see the links between modules and see which modules have too many dependencies etc. You can analyze your graph statistics to make certain conclusions about your project dependency state. It can be not that useful/easy to do such thing for the whole project but it is certainly very good for a features/components used in the project – you can just analyze any part of the project – it is not mandatory that it even should compile.
After you get some experience with these tools you will easily see a difference between well built and decoupled projects and tightly coupled ones.
So there is the “persistence” wing of the Spring4D framework:
And you can actually see the decoupling in action here 😉
You can also use the “Save to GraphML” option from DDS tool and then use the yEd to analyze the diagram:
This tool can be more user friendly and intuitive than Gephi for you, but that’s your choice.
Thank you for reading this. I hope you enjoyed and it was useful for you.
I guess the units in the middle are Spring, Spring.Collections and Spring.Reflection because they are used in many other units.
Delphi unfortunately does not have real namespaces which means it would often require adding multiple units to the uses if you want to use some core type or function so we are always trying to keep a balance between putting things into their own unit and putting things that belong into the same “namespace” or area into one unit.
But as you saw correctly when moving into the parts of the library that are not core it branches more out with often having the implementations of classes in the leafs.
LikeLiked by 1 person
This is fantastic thanks, I’ll investigate the Gephi format, maybe its easy to import it in TeeTree diagramming tool (native Delphi)
LikeLiked by 2 people
I find exporting into GraphML and opening/layouting it in yEd to produce much nicer results.
Sure. I just explained the idea. I was actually the one who asked the developer of DDS to add the possibility to export in these formats.
Just extended the page with yEd.
Thank you very much for this tutorial about Delphi units cleaner tool. At a finer granularity level (classes), tools like “dependency structure matrix” (DSM) are also very useful. This wide subject is probably (after units cleaning step) the next reverse engineering method available in order to analysis in details an application structure. It’s very useful to be able to quickly inspect application during refinement steps or when auditing. In the past, with Delphi, ModelMaker included a tools to produce such a dependencies matrix. I was wondering if in the last Delphi Berlin edition, these DSM (advanced) features are included ?
Few years ago, i began a personal project to generate DSM “neutral” XML format from data imported from Modelmaker (.ldp), Lattix or other source code analysis tools… My goal was to provide an architecture control rules editor to check dependency layers with rules like “layer (A) must use layer (C) but never use layer (B)” (where layer is one or many units or class/classes). It provides an automatic source project code analysis (invoked during continue integration process) and uses graph-coupled solving “classic” methods (low coupling) for generating warnings and tips… Finally i gave up because (not enough time) and also many tools already exists in order to visualize, analyse and resolve dependencies graph problems : Modelmaker, Lattix, yEd, Gephi, … and even some Excel macros ! Building a bridge between the analyser of Delphi project source code (the lexer) and DSM/graph tools is probably the right way to go to implement these architecture “ultimate” controls.
Thanks again for presenting this tools chain to clean-up Delphi units and to produce units dependency graph in order to visualize and analyse project. This portal is very user friendly and very interesting, thanks !