NDepend

Improve your .NET code quality with NDepend

Top 10 Visual Studio Refactoring Tips

With the version 2019 Visual Studio is now mature when it comes to refactoring. This post proposes a tour of the top 10 most used refactoring actions in my opinion.

Short GIF is an excellent way to help get started with those Visual Studio tips. See others related posts based also on short GIFs here:

1) Renaming an Identifier

With Ctrl+R,R you can rename any code identifier: a variable, a field, a class… The renaming experience is pretty clean when only one source file is concerned since all references in file get updated live while typing the new name:

Renaming a variable in Visual Studio
Renaming a variable in Visual Studio

When renaming an identifier impacts several source files, like when renaming a class, several UI details improve the user experience:

  • In the top-right panel we see: Renaming X references in Y files
  • In the top-right panel we get the checkbox: Rename file, this is quite useful since often the file name and the class name are in-sync.
  • We get the possibility to preview all changes in all files in a Preview Change window.
Renaming a class in Visual Studio
Renaming a class in Visual Studio

2) Extract Method

The hotkey Ctrl+. triggers the Quick Actions and Refactorings menu. If you are not used yet to Ctrl+. I’d advise training especially this one because it is a powerful shortcut. You’ll see that most other refactoring presented here rely on the Ctrl+. hotkey.

If one or several instructions are actually selected in a method, the Extract method and Extract local function menus are proposed. A large tooltip is immediately shown to preview the changes. Then just click Enter and terminate the refactoring action by naming the NewMethod identifier.

Extract Method with Visual Studio
Extract Method with Visual Studio

3) Remove and Sort Usings

To make your code cleaner it is recommended to maintain for each source file the list of using ordered alphabetically with unnecessary usings removed. Both actions can be done automatically with Visual Studio top menu > Edit > Intellisense > Remove and Sort Usings. I wish a default shortcut was assigned to this common refactoring (of course you can still assign a shortcut to this action from Visual Studio top menu > Tools > Options > Keyboards.).

Remove and Sort Usings with Visual Studio
Remove and Sort Usings with Visual Studio

Actually it is possible to remove all unnecessary usings at once in a Visual Studio project or solution thanks to the bulb that appears in the code editor gutter when selecting an unnecessary using faded away.

Remove unnecessary usings with Visual Studio
Remove unnecessary usings with Visual Studio

4) Add Missing Usings when Pasting

When pasting some code it is quite irritating to get some errors because of some missing usings. Once the code has been pasted, you can click Ctrl+. to ask Visual Studio to add missing usings for you:

Add missing usings after pasting with Visual Studio
Add missing usings after pasting with Visual Studio

5) Generate Property from Constructor and Generate Constructor from Properties

Once again the magical Ctrl+. hotkey can be used when selecting a parameter into a constructor signature, to generate the corresponding property.

However I haven’t found a way to generate several properties in a row. I’d expect that selecting several parameters and then Ctrl+. would propose to generate several properties in a row but it is not the case, and there is no Create properties for all parameters menu.

Generate property from constructor with Visual Studio
Generate property from constructor with Visual Studio

The same way you can generate a constructor from the selected properties.

Generate constructor from selected properties with Visual Studio
Generate constructor from selected properties with Visual Studio

Both quick actions work with fields also.

6) foreach to LINQ

When the editor carret is over a foreach loop, the hotkey Ctrl+. proposes to convert the foreach loop to a LINQ query. This conversion is not always possible but it is smart enough. For example it can convert a if(condition){continue} within the loop into a where condition LINQ clause.

Notice that typically loops are faster than LINQ queries because the compiler can optimize loops while LINQ queries extensively rely on method calls. But in non-performance-critical code region LINQ queries is often a more readable, concise and maintainable way of writing code.

Converting a foreach loop into a LINQ query with Visual Studio
Converting a foreach loop into a LINQ query with Visual Studio

7) Extract Interface

When the editor carret is over a class name the hotkey Ctrl+. proposes a quick-actions list that includes: extract an interface from the class members. Ctrl+R,I can be used instead to directly show the Extract Interface dialog. The Extract Interface dialog proposes to define the interface name (per defaut set to “I{class name}”) and the member list to include in the interface.

Extracting an interface from a class with Visual Studio
Extracting an interface from a class with Visual Studio

8) Move Type to Namespace

When the editor carret is over a type name, the hotkey Ctrl+. proposes the quick-actions list that includes: move to namespace. The Move to namespace dialog is smart enough to propose intellisense and auto-completion based on existing namespaces. However the type’s source file is not moved automatically to the folder corresponding to the namespace chosen, this must be done manually in the Solution Explorer. I hope this move will be done automatically in the future.

Move class to namespace with Visual Studio
Move class to namespace with Visual Studio

9) Add Parameter to a Method

You can add a named parameter to a method call location. Then the hotkey Ctrl+. proposes the refactoring Add parameters to the method called. The method signature is then refactored with the extra parameter but other calls of the method are left untouched. It means that now these other calls provoke a syntax error and must be fixed with the extra parameter.

Add parameter to a method with Visual Studio
Add parameter to a method with Visual Studio

10) Convert to interpolated string and simplify interpolation

When the carret is over a call to string.Format() call the hotkey Ctrl+. proposes the refactoring Convert to interpolated string. String interpolation with the syntax $”{parameter}” has been introduced with C#6 in 2015. Then if possible some elements like call to PadLeft() are grayed in code. This is a sign that the string interpolation can be simplified once again with the hotkey  Ctrl+. over those grayed elements.

Convert to interpolated string with Visual Studio
Convert to interpolated string with Visual Studio

Conclusion

Over the years thanks to massive effort put in Roslyn, Visual Studio got better and better when it comes to refactoring actions proposed out-of-the-box. Many more refactoring than those 10 are proposed: read the list of refactoring and list of quick-actions.

When we talk about Visual Studio and refactoring the case of Resharper immediately comes in the discussion. For more than a decade Resharper has been the tool of choice to improve the productivity with many refactoring actions and more great features. My independent opinion in the VS vs. R# debate (in 2020) is that R# is still a bit more powerful despite VS being now quite mature. However it seems to me that the fact that VS is now quite mature with refactoring is not popular enough, hence I hope this post can help spread the word. And if you ask, yes I still code with R# in VS despite R# slowing down a bit the IDE, but I find myself using it less often. Within the next years we can expect both VS improvements in terms of refactoring and R# improvements especially in terms of performance.


Actually the word refactoring has really two meanings:

  • Short and quick productivity refactoring actions as presented here.
  • Large scale refactoring that are necessary when the architecture of a legacy doesn’t fit anymore the planned evolution and maintainability requirements.

Large scale refactoring must be discussed extensively. The number one prerequisite for a successful large scale refactoring is a solid understanding of the legacy code architecture. This is where the tool NDepend with its new dependency graph and dependency matrix can really help. Here are two short videos that explain how:

Identify .NET Code Structure Patterns with no Effort

The two pillars of code maintainability are automatic testing and clean code structure.

  • Testing is used to regularly challenge code correctness and detect regression early. Testing can be easily assessed with numbers like code coverage ratio and the amount of assertions tested.
  • A clean code structure prevents the phenomenon of spaghetti code, entangled code that is hard to understand and hard to maintain. However assessing the code structure cannot be achieved through numbers like for testing. Moreover the structure emerges from a myriad of details buried in many source files and thus appropriate tooling is needed.

For most engineers, code dependency graph is the tool of choice to explore code structure. Boxes and arrows graph is intuitive and well adapted to visualize a small amount of dependencies. However to visualize complex portion of code the Dependency Structure Matrix (DSM) is more adapted. See below the same set of 34 namespaces visualized with the NDepend Dependency Graph and the NDepend Dependency Matrix.

NDepend dependency graph
NDepend dependency graph

 

NDepend Dependency Matrix
NDepend Dependency Matrix

If the concept of dependency matrix is something new to you, it is important to note that:

  • The Matrix headers’ elements represent graph boxes
  • The Matrix non-empty cells correspond to graph arrows. Numbers on the cells represents a measure of the coupling in terms of numbers of methods and fields involved. In a symmetric matrix a pair of blue and green cell is symmetric because both cells represents the same thing: the blue cell represents A uses B and the green cells represents B is used by A.

Here is a 5 minutes introduction video if you are not familiar with the dependency matrix:

Clearly the graph is more intuitive, but apart the two red arrows that represent two pairs of namespaces mutually dependent this graph tells few things about the overall structure.

On the other hand the matrix algorithm naturally attempts to layer code elements, exhibit dependency cycles, shows which element is used a lot or not… Let’s enumerate some structural patterns that can be visualized at a glance with the dependency matrix:

Layers

One pattern that is made obvious by a DSM is layered structure (i.e acyclic structure). When the matrix is triangular, with all blue cells in the lower-left triangle and all green cells in the upper-right triangle, then it shows that the structure is perfectly layered. In other words, the structure doesn’t contain any dependency cycle.

On the right part of the snapshot, the same layered structure is represented with a graph. All arrows have the same left to right direction. The problem with graph, is that the graph layout doesn’t scale. Here, we can barely see the big picture of the structure. If the number of boxes would be multiplied by 2, the graph would be completely unreadable. On the other side, the DSM representation wouldn’t be affected; we say that the DSM scales better than graph.

Notice that NDepend proposes 2 rules out of the box to control layering by preventing dependency cycles to appear: ND1400 Avoid namespaces mutually dependent and ND1401 Avoid namespaces dependency cycles.

Interestingly enough, most of graph layout algorithms rely on the fact that a graph is acyclic. To compute layout of a graph with cycles, these algorithms temporarily discard some dependencies to deal with a layered graph, and then append the discarded dependencies at the last step of the computation.

Cycles

If a structure contains a cycle, the cycle is displayed by a red square on the DSM. We can see that inside the red square, green and blue cells are mixed across the diagonal. There are also some black cells that represent mutual direct usage (i.e A is using B and B is using A).

The NDepend’s DSM comes with the option Indirect Dependency. An indirect dependency between A and B means that A is using something, that is using something, that is using something … that is using B. Below is shown the same DSM with a cycle but in indirect mode. We can see that the red square is filled up with only black cells. It just means that given any element A and B in the cycle, A and B are indirectly and mutually dependent.

Here is the same structure represented with a graph. The red arrow shows that several elements are mutually dependent. But the graph is not of any help to highlight all elements involved in the parent cycle.

Notice that in NDepend, we provided a button to highlight cycles in the DSM (if any). If the structure is layered, then this button has for effect to triangularize the matrix and to keep non-empty cells as closed as possible to the diagonal.

High Cohesion / Low-Coupling

The idea of high-cohesion (inside a component) / low-coupling (between components) is popular nowadays. But if one cannot measure and visualize dependencies, it is hard to get a concrete evaluation of cohesion and coupling. DSM is good at showing high cohesion. In the DSM below, an obvious squared aggregate around the diagonal is displayed. It means that elements involved in the square have a high cohesion: they are strongly dependent on each other although. Moreover, we can see that they are layered since there is no cycle. They are certainly candidate to be grouped into a parent artifact (such as a namespace or an assembly).

On the other hand, the fact that most cells around the square are empty advocate for low-coupling between elements of the square and other elements.

In the DSM below, we can see 2 components with high cohesion (upper and lower square) and a pretty low coupling between them.

While refactoring, having such an indicator can be pretty useful to know if there are opportunities to split coarse components into several more fine-grained components.

Too many responsibilities

The popular Single Responsibility Principle (SRP) states that: a class shouldn’t have more than one reason to change. Another way to interpret the SRP is that a class shouldn’t use too many different other types. If we extend the idea at other level (assemblies, namespaces and method), certainly, if a code element is using dozens of other different code elements (at same level), it has too many responsibilities. Often the term God class or God component is used to qualify such piece of code.

DSM can help pinpoint code elements with too many responsibilities. Such code element is represented by columns with many blue cells and by rows with many green cells. The DSM below exposes this phenomenon.

Popular Code Elements

A popular code element is used by many other code elements. Popular code elements are unavoidable (think of the String class for example).

A popular code element is not a flaw. However it is advised that popular elements are interfaces and enumerations. This way consumers rely on abstractions and not on implementations details. The benefit is that consumers are less often broken because abstraction are less subject to change than implementations.

A popular code element is represented by columns with many green cells and by rows with many blue cells. The DSM below highlights a popular code element.

Something to notice is that when one is keeping its code structure perfectly layered, popular components are naturally kept at low-level. Indeed, a popular component cannot de-facto use many things, because popular component are low-level, they cannot use something at a higher level. This would create a dependency from low-level to high-level and this would break the acyclic property of the structure.

Mutual dependencies

You can see the coupling between 2 components by right clicking a non-empty cell, and select the menu Open this dependency.

If the opened cell was black as in the snapshot above (i.e if A and B are mutually dependent) then the resulting rectangular matrix will contains both green and blue cells (and eventually black cells as well) as in the snapshot below.

In this situation, you’ll often notice a deficit of green or blue cells (3 blue cells for 1 green cell here). It is because even if 2 code elements are mutually dependent, there often exists a natural level order between them. For example, consider the System.Threading namespaces and the System.String class. They are mutually dependent; they both rely on each other. But the matrix shows that Threading is much more dependent on String than the opposite (there are much more blue cells than green cells). This confirms the intuition that Threading is upper level than String.

Static analysis of .NET Core 2.0 applications

NDepend v2017.3 has just been released with major improvements. One of the most requested features, now available, is the support for analyzing .NET Core 2.0 and .NET Standard 2.0 projects. .NET Core and its main flavor, ASP.NET Core, represents a major evolution for the .NET platform. Let’s have a look at how NDepend is analyzing .NET Core code.

Resolving .NET Core third party assemblies

In this post I’ll analyze the OSS application ASP.NET Core / EntityFramework MusicStore hosted on github. From the Visual Studio solution file, NDepend is resolving the application assembly MusicStore.dll and also two test assemblies that we won’t analyze here. In the screenshot below, we can see that:

  • NDepend recognizes the .NET profile, .NET Core 2.0, for this application.
  • It resolves several folders on the machine that are related to .NET Core, especially NuGet package folders.
  • It resolves all 77 third-party assemblies referenced by MusicStore.dll. This is important since many code rules and other NDepend features take into account what the application code is using.

It is worth noticing that the .NET Core platform assemblies have high granularity. A simple website like MusicStore references no fewer than 77 assemblies. This is because the .NET Core framework is implemented through a few NuGet packages that each contain many assemblies. The idea is to release the application only with needed assemblies, in order to reduce the memory footprint.

.NET Core 2.0 third party assemblies granularity

NDepend v2017.3 has a new heuristic to resolve .NET Core assemblies. This heuristic is based on .deps.json files that contain the names of the NuGet packages referenced. Here we can see that 3 NuGet packages are referenced by MusicStore. From these package names, the heuristic will resolve third-party assemblies (in the NuGet store) referenced by the application assemblies (MusicStore.dll in our case).

NuGet packages referenced in .deps.json file

Analyzing .NET Standard assemblies

Let’s be clear that NDepend v2017.3 can also analyze .NET Standard assemblies. Interestingly enough, since .NET Standard 2.0, .NET Standard assemblies reference a unique assembly named netstandard.dll and found in C:\Users\[user]\.nuget\packages\NETStandard.Library\2.0.0\build\netstandard2.0\ref\netstandard.dll.

By decompiling this assembly, we can see that it doesn’t contain any implementation, but it does contain all types that are part of .NET Standard 2.0. This makes sense if we remember that .NET Standard is not an implementation, but is a set of APIs implemented by various .NET profiles, including .NET Core 2.0, the .NET Framework v4.6.1, Mono 5.4 and more.

Browsing how the application is using .NET Core

Let’s come back to the MusicStore application that references 77 assemblies. This assembly granularity makes it impractical to browse dependencies with the dependency graph, since this generates dozens of items. We can see that NDepend suggests viewing this graph as a dependency matrix instead.

NDepend Dependency Graph on an ASP.NET Core 2.0 project

The NDepend dependency matrix can scale seamlessly on a large number of items. The numbers in the cells also provide a good hint about the represented coupling. For example, here we can see that  22 members of the assembly Microsoft.EntityFrameworkCore.dll are used by 32 methods of the assembly MusicStore.dll, and a menu lets us dig into this coupling.

NDepend Dependency Matrix on an ASP.NET Core 2.0 project

Clicking the menu item Open this dependency shows a new dependency matrix where only members involved are kept (the 32 elements in column are using the 22 elements in rows). This way you can easily dig into which part of the application is using what.

NDepend Dependency Matrix on an ASP.NET Core 2.0 project

All NDepend features now work when analyzing .NET Core

We saw how to browse the structure of a .NET Core application, but let’s underline that all NDepend features now work when analyzing .NET Core applications. On the Dashboard we can see code quality metrics related to Quality Gates, Code Rules, Issues and Technical Debt.

NDepend Dashboard on an ASP.NET Core 2.0 project

Also, most of the default code rules have been improved to avoid reporting false positives on .NET Core projects.

NDepend code rules on an ASP.NET Core 2.0 project

We hope you’ll enjoy using all your favorite NDepend features on your .NET Core projects!