And, I’m back again bragging about this awesome tool that I like. It's been almost a couple of years maybe, that I didn't write about NDepend. But this new and improved "New Dependency Graph" feature caught my eyes.
I've joined FlexFunding earlier this year leaving my previous remote job. Things have changed over the last few months due to the global pandemic situation and commuting to your workplace is a hassle. So, I'm back again working from my home office and trying to be productive. But, why am I telling you this stuff? Well, few key points I'm going to write down as bullet points now and at the end of the post, I'm going to discuss those.
⦁ I've just joined FlexFunding
⦁ Team members are all working remotely
⦁ I'm trying to be productive
Let’s shift our gear and talk about "New Dependency Graph". "What's a dependency graph?", you might ask. I talked a bit about it in this post,
To give you a heads up, Dependency Graph is just a graph made out of all the dependent modules, components, contracts, assemblies, namespaces, third-party libraries, etc. It was available in NDepend from the get-go but the new one is way more friendly and feature-heavy. In, FlexFunding we have many many micro-services. A dependency graph gives me an eagle-eyed view of all the dependencies at a glance.
A lot of things are going on there. But to make things soothing to our eyes, NDepend has intelligently grouped them into manageable clusters i.e. default application map. Automatic clusters are made out of two different grouping flags,
- Cluster Complex Assembly Sets
- Cluster Complex Element Sets
Cluster Complex Assembly Set: When set, this applies when there is more than 20 assemblies to show. An heuristic appends cluster nodes that are grapes of assemblies to simplify the assembly graph. If referenced assemblies like ASP.NET Core assemblies are shown on a graph, they get their own clusters.
Cluster Complex Element Set: When set, this applies to all sub-graphs made of namespaces, types or methods and fields, that contain more than 20 elements. Thanks to cluster nodes added such sub-graph gets simplified.
For further modification, you can set additional grouping flags, filter dependencies (e.g include/exclude third-party library dependencies and change layout of the graph (e.g based on #Lines of codes, #IL Instructions and etc.)
Selecting a node and double-clicking on it will take you straight to a more granular view of the node dependencies. The following shows all the assemblies that are connected to our core
Unable to find a node you are looking for? Try the search bar! As of now, I'm only interested in inspecting everything related to
LoanBid, so I can do a quick search with that keyword. And, Viola! All the namespaces containing that keyword are listed within a matter of milliseconds
You can also drag and drop a type/directories from the solution into the graph explorer and it will automatically create a map of everything that is connected to that type/types in a directory. Here, I've dragged and dropped the most important entity of our system,
The above example not only shows relations between different entities but also shows contextual information about them. We can immediately figure out that
LoanApplicationMaster is mutually dependent on many other entities because of the two way navigation property deceleration. We can remove those redundancy or we can keep those.
A mutual dependency exists when two code entities (for example, types or packages) depend directly on each other. Mutual dependencies are caused by unwanted dependencies in one or both directions.
Not satisfied with those couple of techniques for exploring graphs? Ok then, go to any code file and right-click on a type and select
Show on Dependency Graph
Cool! Let's talk about
Call Graph. So, I have this entity called
EmailQueue and I want to generate the call graph. Simply select a node and click on
caller and callees option from the top bar,
Different types of edges are generated and some of them also have different widths. The meaning of this edge types are listed in the help bar and hovering over the edges will show contextual information as well.
Not too shabby! By default, third party libraries are excluded, but to show every moving parts in a single unit of work, I've unchecked that flag from the filter drop down.
For critical background command scheduling, we at FlexFunding intend to go for "Store Procedures". I know there is an abstraction in place to handle such situations. The interface is named
ICommandProcedure. I can add this type to my graph explorer and click on
classes implementer option and it will take me to a
Class Inheritance Graph. I can easily get an idea of which classes are responsible for scheduling a background task. It is obvious that at the end of a day we calculate interest for a user and
UpdateDailyInterestAccount is the process to handle that.
Almost a month ago, I was assigned to convert a .net framework based micro-service to .net core. The only reason why this was in
.Net Framework because it had some dependencies on some legacy framework calls. The
FundingPilotSystem projects are all legacy code written in
.Net Framework. I can select an edge pointing to a legacy project and click on
coupling. Following shows that in order to move to
.Net Core, we have to lose the coupling of
This becomes very useful when you want to start refactoring on the legacy code base as well. I can anticipate the impact of refactoring from this.
Last, I want to talk about the change map. A baseline will be created the first time you generate a dependency graph. After that, based on each iteration on the source code, you can generate a change graph. As far as I remember I worked on the validation of our bulk loan bid feature. So, I'm searching for
ValidateLoanBid term, and seems every change I wanted to make is properly incorporated.
Exporting and importing of graph diagrams are just couple of clicks away. All the graph images I've used in this post are in
.svg format and have been exported directly from the
'Nuff said! I've pretty much discussed all the core features of the "New Dependency Graph". But that's not all you can do with NDepend. This extension can do a lot more than you can think;
Technical Debt Estimation for say,
I've added some important links at the end of this article which may come handy if you are new to NDepend and want to dig more.
Now let's get back to the story I started with. You can now imagine how NDepend has made my life easy as a new recruit. I don't have to go through all the confluence documentations to get an insight into the overall architecture of our system. At a higher level this dependency graph worked as a code base documentation for me. I don't have to poke my team mates and have a long running architectural discussion over a communication channel. And it would not be wise to do so in this current global situation either. However, it's not like I'm saying that you should not poke your team mates; I'm just saying poke them wisely. Remember, to keep your job, you also have to be productive no matter whether we are going through a hard time or not. In conclusion, with Ndpend installed, I can just take a chill pill and do my work smartly.