Using NDepend on Linux
Disclaimer: Like the last time I was offered a 1 year NDepend pro license by Patrick Smacchia (NDepend creator) so I could use it and share my experience if I wanted to.
Since then I switched to Linux and was working on a little dotnet console backup utiliy which copies files and folders using rsync
and cp
and using source generator to handle DBus notifications, so I was curious about how NDepend will handle it.
Installation
Download the NDepend zip redistributable 14 days free trial at the price of an email or if you already have a license you can get the pro edition.
You will have a zip file to place wherever you want, I chose the recommended folder /home/$USER/ndepend/
. The dotnet SDK is a prerequisite and can be downloaded here, I already have dotnet 9 installed and will use it for running NDepend.
Registration
You can then register for the 14 days trial with this command:
dotnet ~/ndepend/net9.0/NDepend.Console.MultiOS.dll --RegEval
Or if you have a license key:
dotnet ~/ndepend/net9.0/NDepend.Console.MultiOS.dll --RegLic [License key]
Analysis
First let's create an ndepend projet:
dotnet ~/ndepend/net9.0/NDepend.Console.MultiOS.dll --CreateProject ./bafifo.ndproj ./bafifo/bafifo.csproj
And run the first analysis:
dotnet ~/ndepend/net9.0/NDepend.Console.MultiOS.dll ./bafifo.ndproj
With a direct result:
ERROR: 2 quality gates fail:
- 'Critical Rules Violated' value 3 rules greater than fail threshold 0 rules
- 'Debt Rating per Namespace' value 2 namespaces greater than fail threshold 0 namespaces
Luckily NDepend generates a complete report in HTML file NDependOut/NDependReport.html
so here are a better view at the quality gates:
Which are also integrated in source files:
Besides the report, NDepend generates an interactive component dependencies matrix on NDependOut/NDependReportFiles/ComponentDependenciesMatrix.html
(ouch, I have work to do):
And an interactive component dependencies diagram on NDependOut/NDependReportFiles/ComponentDependenciesDiagram.html
:
Fixes
ND1400 - Avoid namespaces mutually dependent and ND1401 - Avoid namespaces dependency cycles
It was a utility class in the wrong namespace, a quick move of the file, fix its namespace and it was good.
ND1901 - Avoid non-readonly static fields
Forgot a readonly
on a static field.
ND1807 - Avoid public methods not publicly visible
Nice one to catch over exposed methods and properties. It also picked up a public init
on a property setter in a class which has only one private constructor with a parameter to initialize that property, so the init can only be used by that constructor.
In my opinion it can be seen as a bit much but at least it forces the consistancy throughout the code.
ND1311 - Don't use obsolete types, methods or fields
This one was caused by a dependency which used an obsolete type but a new version of the package fixed that.
ND1803 - Types that could be declared as private, nested in a parent type
This one included types generated by a source generator, a custom notmycode
rule in the JustMyCode
group inserted in the .ndproj
file fixed it:
// <Name>Discard generated code from Tmds.DBus.SourceGenerator from JustMyCode</Name>
notmycode
from t in Application.Types where
t.ParentNamespace.Name.Equals("Tmds.DBus.SourceGenerator")
select t
ND1208 - Methods should be declared static if possible
Amongst the methods listed was get_EqualityContract()
which is generated by the record
keyword, it can be discarded by excluding methods marked with System.Runtime.CompilerServices.CompilerGeneratedAttribute
:
// <Name>Discard generated mehods marked by CompilerGenerated from JustMyCode</Name>
notmycode
from m in Application.Methods where
m.HasAttribute("System.Runtime.CompilerServices.CompilerGeneratedAttribute".AllowNoMatch())
select m
ND2208 - Do not raise reserved exception types
The only methods listed were not from my code:
System.Collections.IList.get_Item(Int32)
System.Collections.Generic.IReadOnlyList<T>.get_Item(Int32)
System.Collections.Generic.IList<T>.get_Item(Int32)
It seems that they are generated because there are all in namespace<>z__ReadOnlySingleElementList<T>.System.Collections.*
.
I haven't found a way to exclude them with anotmycode
rule because the ND2208 rule doesn't useJustMyCode
.
ND2103 - Namespace name should correspond to file location
Got this issue for the files containing the declarations of the namespace bafifo.Configuration
which are located in the directory /repos/bafifo/bafifo/Configuration
. After having checkd for typos but found nothing and compared to other files in other namespaces/folders I don't know what is bugging here.
Conclusion
I am glad to see it working well on linux, including the generation of all the reports and graphs.
There are just 3 things that can be improved :
- like Nadir Badnjevic I believe that the installation and usage can be simplified on Linux/MacOS
JustMyCode
rules needs to be updated to include the newCompilerGenerated
attribute- tools are missing to help creates rules on Linux since a lot of NDepend tools are available only on Windows (Visual Studio extension or VisualNDepend standalone app)
Sources:
- https://www.ndepend.com/docs/getting-started-with-ndepend-linux-macos
- https://www.ndepend.com/docs/ndepend-console
- https://nadirbad.dev/how-to-setup-and-use-ndepend-on-macos-for-net-development
- https://www.ndepend.com/docs/get-rid-of-false-positives-issues
- https://www.ndepend.com/default-rules/NDepend-Rules-Explorer.html
- https://github.com/TerribleDev/Varanus/blob/master/NOCQ.ndproj