NDepend

Improve your .NET code quality with NDepend

10 Visual Studio Navigation Productivity Tips

A large code base is a complex asset. Visual Studio is a complex environment. In this context developers spend a significant part of their time searching and navigating across code elements and the multiple IDE tools and options.

Fortunately Visual Studio proposes many features to simplify navigation that I am going to present.  Note that this post won’t go through the Find in Files Ctrl+Shift+F feature that I guess all developers already use.

Visual Studio: Find in Files
Visual Studio: Find in Files

Short GIF is an excellent way to quickly learn Visual Studio productivity tips. See others related posts based also on short GIFs here:

1) Title Bar Search Box

The Visual Studio title bar proposes a search box. This feature is quite convenient because it let’s search through various kinds of assets: code elements, files, Visual Studio commands, Visual Studio settings… For example in the GIF below:

  • We first search for the interface IAffiliateService
  • Then we type IAS to search again for the interface IAffiliateService: this is Camel Case searching and this is quite convenient to locate large identifier
  • Then we search for Go to: many Visual Studio commands are then matched
  • Finally we search for line number: several Visual Studio settings related to line numbering are then matched.

At first glance being able to search various kinds of assets is a bit weird but once you’ll get used to it this is quite helpful. Personally I use this box to mostly search through commands and settings and use Go to all to search in code.

Visual Studio: Search Box in Title Bar
Visual Studio: Search Box in Title Bar

2) Go to All

When it comes to searching for code elements Go to All (hotkey Ctrl+t) is my preferred Visual Studio feature. Unlike the title bar search box it cannot be used to search for Visual Studio commands or settings.

Go to All offers several filters to define the kind of element to search. These filters can be listed with Ctr+t and then ?:

Visual Studio: Go to All Filters

In the GIF below:

  • We first search for all code elements that start with IAffiliateService: both source files and interfaces are matched
  • Then we prefix the same research with the filter “t ” to narrow the search on types only.
  • Then again we use the Camel Case searching on type with “t IAS”
  • Finally we list filters by typing “?”
Visual Studio Go to All Ctrl+t
Visual Studio Go to All Ctrl+t

There are also two scopes tickbox to:

  • Search only in Current Document (Ctrl+Alt+C)
  • Include contents of external items (Alt+X)

There are also 3 settings:

Visual Studio: Go to All Settings
Visual Studio: Go to All Settings

3) Peek Definition and Go To Definition

When the code editor carret is over an identifier you can use the hotkeys:

  • Alt+F12 to peek the identifier definition
  • F12 to open the source file that contains the definition

I believe those two hotkeys must be in the toolbelt of all Visual Studio developers.

Visual Studio: Peek Definition (Alt+F12) Go To Definition (F12)
Visual Studio: Peek Definition (Alt+F12) Go To Definition (F12)

Now let’s present other navigation hotkeys available when the carret is over an identifier in the source code: they are all available through the right-click menu.

Visual Studio: Navigation Hotkeys
Visual Studio: Navigation Hotkeys

4) Find All References

When the code editor carret is over an identifier you can use the hotkey Shift+F12 to find all references:

Visual Studio: Find all References
Visual Studio: Find all References

Typically the Find all references results window is a vertical windows so I like to get rid of all columns except the code one to obtain a result easier to browse.

Visual Studio: Clear columns of Find all references
Visual Studio: Clear columns of Find all references

A Group-By combo box let’s choose among various options:

Visual Studio: Find all references Group-By combo box
Visual Studio: Find all references Group-By combo box

I hope that in the future (post Visual Studio 2019) this result list will be improved this ways:

  • I’d like to group by Project, Namespace, Type, Member but this grouping option is not available.
  • On the screenshot above we see an unnecessary [Containing Member: Unknow] row that consumes space without adding any value.
  • The parent rows are in bold, I am not sure why, this makes the source code row less readable.
  • The same way the reference counting (3) (1) shouldn’t be in bold.
  • The parent rows should be prefixed with the corresponding icon (project icon, class icon, method icon…).

5) CodeLens

Visual Studio Code Lens is an intuitive an immediate way to see all references of an identifier. It is only available at the identifier declaration, not at the identifier usage locations.

Visual Studio: Find References with Code Lens
Visual Studio: Find References with Code Lens

I remember when Code Lens was introduced a few years ago I didn’t like the extra vertical space between lines and that some extra info were added in the middle of source code. So I used to disable it. However with time I got used to it and learnt to like it because it also displays more information than just references (code changes, branch… see the details here).

6) Go to Base and Go to Implementation

When the code editor carret is over an identifier representing a class name or an interface name:

  • The shortcut Alt+Home (Go to Base) can be used to go to the base class(es) or implemented interfaces.
  • The shortcut Ctrl+F12 (Go to Implementation) can be used to go to derived classes or classes that implement the interface.
Visual Studio: Go to Base, Go to Implementation
Visual Studio: Go to Base, Go to Implementation

7) Call Hierarchy

When the code editor carret is over an identifier representing a member, the shortcut Ctrl+K Ctrl+T opens the Call Hierarchy Window. With this window you can browse callers and also callers of callers (recursive).

Visual Studio: Call Hierarchy
Visual Studio: Call Hierarchy

When it comes to call hierarchy I prefer to have a dependency graph view. The NDepend dependency graph is well suited for that. The GIF below illustrates this list of action:

  • Right click the definition of a method, a field, a type or a namespace.
  • Then click Show on Dependency Graph
  • Then click callers in the graph navigation bar
  • Then, if needed, adjust Group-By and Layout Horizontal / Vertical.
NDepend Call Graph
NDepend Call Graph

8) Navigate TODO comments in Task List

The Visual Studio Task List Window can display all comment lines starting with the predefined token TODO (case sensitive).

Visual Studio: TODO Task List
Visual Studio: TODO Task List

You can define your own set of tokens in Options > Environment > Task List:

Visual Studio Task List Settings
Visual Studio Task List Settings

9) Shortcut on a line of code

A shortcut can be placed to any line of code with the hotkey Ctrl+K-H. The same hotkey can be used to remove the shortcut.

These shortcuts are listed in the Task List Window. Notice that shortcuts are persisted and if you close and restart Visual Studio they will still be there.

Visual Studio: Shortcut on line of code
Visual Studio: Shortcut on line of code

Notice that this feature is different that the Bookmark feature already presented in 10 Visual Studio Ninja Code Editor Productivity Tips (item 10).

10) Go to Matching Brace

When the carret is over an opening brace or a closing brace { }, the hotkey Ctrl+} goes to the matching brace. This also work for these pairs: ( )  [ ] <>

Visual Studio: Go to Matching Brace
Visual Studio: Go to Matching Brace

Conclusion

I hope that you’ve learnt some tricks to improve your productivity.

It is important to train a bit and get used to all these features and which one to favor for which scenario.

  • Title Bar Search box is well suited to search across Visual Studio menus and options
  • Ctrl+t Go to All is well suited to search files and code element identifiers.
  • Then it is important to get used to all navigation features around the F12 key: F12 Go to Definition, Alt+F12 Peek Definition, Shift+F12 Find all References, Alt+Home Go to Base, Ctrl+F12 Go to Implementation

I mentioned the NDepend dependency graph in the Call Hierarchy tips. This tool can help a lot when it comes to navigating and understanding a large code base. Here is a short introduction video:

 

Mythical man month : 10 lines per developer day

The mythical book, Mythical man month quotes that no matter the programming language chosen, a professional developer will write on average 10 lines of code (LoC) day.

After 14 years of full-time development on the tool NDepend I’d like to elaborate a bit here.

Let’s start with the definition of logical Line of Code. Basically, a logical LoC is a PDB sequence point except sequence points corresponding to opening and closing method brace. So here we have a 5 logical lines of code method for example:

I already hear readers complaining that LoC has nothing to do with productivity. Bill Gates once said “Measuring software productivity by lines of code is like measuring progress on an airplane by how much it weighs.“.

And indeed, measured on a few days or a few weeks range, LoC has nothing to do with productivity. As a full-time developer some days I write 200 LoC in a row, some days I spend 8 hours fixing a pesky bug by not even adding a LoC. Some day I clean dead code and remove some LoC. Some other days I refactor existing code without, all in all, adding a single LoC. Some days I create a large and complex UI control and the editor generates automatically 300 additional LoC. Some days are dedicated solely to performance enhancement or writing tests…

What is interesting is the average number of LoC obtained from the long term. And if I do the simple math our average is around 80 LoC per day. Let’s precise that we are strict on high code quality standard both in terms of code structure and formatting, and in terms of testing and code coverage ratio (see the last picture of this post that shows the NDepend code coverage map). For a code quality tool for developers, being strict on code quality means dogfooding☺.

So this average score of 80 LoC produced per day doesn’t sacrifice to code quality, and is a sustainable rhythm. Things get interesting with LoC after calibration: caring about counting LoC becomes an accurate estimation tool. After coding and measuring dozens of features achieved in this particular context of development, the size of any feature can be estimated accurately in terms of LoC. Hence with simple math, the time it’ll take to deliver a feature to production can be accurately estimated. To illustrate this fact, here is a decorated treemap view of the NDepend code base, K means 1.000 LoC. This view is obtained from the NDepend metric view panel with handmade coloring to illustrate my point. The small rectangles are methods grouped by parent classes, parent namespaces and parent assemblies. A rectangle area is proportional to the corresponding method #LoC.

treemap code-metric

Thanks to this map, I can compare the size in terms of LoC of most components. Coupling this information with the fact that the average coding score if 80 LoC per day, and looking back on cost in times for each component, we have an accurate method to tune our way of coding and estimate future schedules.

Of course not all components are equals. Most of them are the result of a long evolutive coding process. For example, the code model had undergone much more refactoring since the beginning than say, the dependency matrix for example that had been delivered out-of-the-box after a few months of development.

This picture reveals something else interesting. We can see that all these years spent polishing the tool to meet high professional standards in terms of ergonomy and performance, consumed actually quite a few LoC. Obviously building a performant code query engine based of C# LINQ that is now the backbone of the product took years. This feature alone now weights 34K LoC. More surprisingly just having a clean Project Properties UI management and model takes (model + UI) =(4K + 7K) = 11K LoC. While a flagship feature such as the interactive Dependency Graph only consumes 8K LoC, not as much as the Project Properties implementation. Of course the interactive Dependency Graph capitalizes a lot on the existing infrastructure developed for other features including the Dependency Model. But as a matter of fact, it took the same amount of effort to develop  the Dependency Graph than to develop a polished Project Properties model and UI.

All this confirms an essential lesson for everyone in charge of an ISV. It is lightweight and easy to develop a nice and flashy prototype application that’ll bring enthusiast users. What is really costly is to transform it into something usable, stable, clean, fast with all possible ergonomy candy to make the life of the user easier. And these are all these non-functional requirements that will make the difference between a product used by a few dozens of enthusiast users only, and a product used by the mass.

To finish, it is also interesting to visualize the code base through the prism of code coverage ratio. The NDepend code base being 86% covered, by comparing both pictures we can easily see which part is almost 100% covered and which part need more testing effort.

The continuous adaptation of Visual Studio extensions

One could think that developing an extension for a two-decades+ product as mature as Visual Studio is headache-less.

Not really. Visual Studio is a big big beast used by millions of professional developers daily. Versions after versions Microsoft is spending an astounding amount of effort to improve it and make sure it respects the latest standard in terms of dev platforms, IDE features, usability and performance.

This implies a lot of deep changes and all VS extensions must adapt to these changes … or die. Most of this adaptation efforts come from the support of new platforms (.NET Core, Xamarin, upcoming .NET 5…) but here I’d like to focus on VS integration recent changes.

Deferred extensions loading

On Monday 11th December 2017 all VS partners received an mail announcing VS package deferred loading, also referred to extension asynchronous initialization. In this mode VS extensions are loaded after VS startup and initialization. As a consequence VS startup is not slowed down by extensions.

Implementing this scenario required serious changes described here but this deferred loading scenario became mandatory only with VS 2019.1 (16.1) released this spring 2019, around 18 months later after the initial announcement. VS extension ISVs got plenty of time (and plenty of high quality support from Microsoft engineers) to implement and test this async loading scheme.

VS2019 Extensions Menu

In February 2019, we were developing the support of NDepend for VS 2019 and were downloading the latest VS2019 preview, installed our NDepend extension and immediately noticed there were no more NDepend global menu? After investigation we saw our NDepend main menu, and other extensions menus, under a new Extensions menu –with no possibility to get back extensions menu in the main bar–.

Visual Studio 2019 Extensions Menu

This change impacts millions of extensions users and hundreds of partners ISVs but has never been announced publicly ahead nor debated. As an immediate consequence someone asked to get rid of this new Extensions menu and this generated a long list of complains.

I guess this major (and blunt) change was provoked initially by the VS2019 compact menu look, but I am not sure: even on a 1920 pixel wide monitor (DPI 100%) there is still plenty of width space to show extension menus.

Visual Studio 2019 Compact Menu

Sometime in April 2019 someone anonymously published on the discussion the link to a new extension to put back extensions main menus in the main bar.

Getting back Extensions in Main Menu

I guess the VS APIs used to achieve this magic are not well documented, hence we can wonder if this initiative comes from MS or not? At least now users can get back their extensions menus in the main bar. But the Extensions in Main Menus extension has been downloaded only 800 times in around 3 months. It means only a tiny subset of VS extension users are aware of it and are actually using it.

Personally I still have hope Microsoft will reconsider this move and will embed a similar option in a future VS version to let the users chose which features (out-of-the-box VS feature or extension feature) deserves a no-brainer/main bar access or not.

VS2019 Optimize rendering for screens with different pixel densities

We published NDepend v2019.2.0 on 14th March 2019 with proud support for VS2019 and .NET Core 3. Two weeks later a user reported severe UI bugs we’ve never observed. The repro scheme was easy:

  • install .NET Fx 4.8,
  • enable the new VS2019 option Optimize rendering for screens with different pixel densities
  • run VS2019 with the NDepend extension in a multi-monitors environment with various DPI scale for each monitor
Optimize rendering for screens with different pixel densities
Optimize rendering for screens with different pixel densities

We then discussed with VS engineers. They pointed us to this documentation and kindly offered quite a few custom advices: Per-Monitor Awareness support for Visual Studio extenders

Actually this change is pretty deep for (the tons of) WPF and Winforms controls rendered in the Visual studio UI. This took us time but we just released on July 3rd 2019 NDepend v2019.2.5 with full support for this Optimize rendering for screens with different pixel densities option. This required quite tricky fixes and we’d wish we have had a few months to adapt to this major breaking changes as we had for deferred loading explained above. As far as I know extensions ISVs were not informed in advance. On the other hand I’d like to underline the awesome support we got from Visual Studio engineers (as always actually) thanks again to all of them.

I noticed that Resharper pops up a dialog at VS2019 starting time (not sure if they got all fixed at the time of writing).

Resharper Message related to Optimize rendering for screens with different pixel densities

I also noticed that up to VS2019 16.1.3 there were still some bugs in the VS UI, see the Project Properties and Diagnostics Tool windows below. I just tried with 16.1.5 and it seems fixed.

VS 2019 16.1.3 UI issues (now fixed)

My point is that this great improvement (Optimize rendering for screens with different pixel densities) should have been highlighted ahead during VS2019 preview time to avoid a wide range of UI bugs experienced by users during the early months of VS2019 RTM.

What can we expect next?

With .NET 5 public announcement on May 6th 2019 the .NET community now knows that sooner or later most of .NET Core or .NET Fx applications will have to be migrated to benefit from latest innovations and improvements.

Hopefully .NET Core apps migration will be quite straightforward since .NET 5 is .NET Core vNext. But .NET Fx apps migration will be (more or less) painful. Although WPF and Winforms desktop APIs are already supported by .NET Core 3, some others major APIs are not – and won’t be – supported (ASP.NET Web Forms, WCF, Windows Workflow, .NET Remoting, AppDomain…).

For too complex migration plans here is the Microsoft recommendation: What do you do with your older applications that you are not spending much engineering time on? We recommend leaving these on .NET Framework. (…) .NET Framework will continue to be supported and will receive minor updates. Even here at Microsoft, many large products will remain on .NET Framework. There are absolutely no changes to support and that will not change in the future. .NET Framework 4.8 is the latest version of .NET Framework and will continue to be distributed with future releases of Windows. If it is installed on a supported version of Windows, .NET Framework 4.8 will continue to be supported too.

Visual Studio 2019 is still running in a 32 bits process upon the .NET Fx 4 CLR with a massive WPF based UI and some COM usage.

Can we expect VS2019 to run on .NET 5 sometime in 2021? or in a later version? or never?

Only the future will tell but I hope extension VS ISVs will be advised ahead to anticipate the migration and continue to offer a seamless integration experience to users.

Simplifying a Visual Studio extension menu: A Case Study

NDepend version 2019.2.1 has just been released. This new version proposes a simplified menu for the NDepend Visual Studio extension.

Before going further I underline that we didn’t get rid of the standard menu, the user can switch back and forth simplified and standard menu within a single click. There is something in UI that all users worldwide dislike: don’t force a new UI just for the sake of it.

The simplified menu is shown per default on machines that never ran NDepend, else the standard menu is shown. Here is a view of the simplified/beginner menu vs. the standard/advanced menu.

NDepend simplified/beginner menu vs. standard/advanced menu

We introduced a simplified menu because we think that trial users and beginner users will benefit from it. Having most features available through a single level menu certainly makes the product features more discoverable.

More and Tools popup menus

A More… popup menu is here to show features and actions that are typically used less often. It is a UI trade off to force an extra-click to access these actions:

More Actions Menu

The Tools popup menu is an opportunity to switch to the advanced menu, and see the NDepend Start Page. It is also good to discover NDepend tooling outside Visual Studio, the standalone VisualNDepend.exe, NDepend API and OSS Power Tools, Azure DevOps extension and others Continuous Integration possibilities:

Tools Menu Actions

Opportunities to lean up the user experience

Having a simplified menu is also an opportunity to encourage the user to do some configuration steps. For example in the first screenshot we have the Explore Code Coverage button. With NDepend the code coverage by tests of a code base can be harnessed in multiple ways as explained here. But to harness code coverage data the user has to import it first. Hence, per default an Import Code Coverage button is shown to the user and the Explore Code Coverage button is shown only upon data imported.

Another important NDepend feature is comparing against a baseline. As far as I know NDepend is the only Visual Studio tool that lets the user diff the actual code base against a baseline. The user can then focus on new issues since baseline, or diff-related issues like API Breaking Changes or Code Smells Regression. The baseline can also be used to review code changes since the baseline. When NDepend analyzes a large legacy code base, letting the user focuses on new issues since the baseline is a very important facility to avoid letting the users lost in the prioritization of thousands of issues.

Per default the baseline is set to the first analysis result obtained. It means that the first time the user runs an analysis on a code base, this first analysis result is used both for the actual snapshot and the baseline snapshot. In this situation, when the user clicks the buttons New Issues since Baseline or Diff since Baseline, there is nothing to show. Thus we take a chance to show an informational message box that explains this no-diff situation. Doing so avoids the user being stuck with a no-result action or even worse, a button disabled with no obvious reason. We also hope these explanations will motivate the user to work on changes and then re-analyze to see what NDepend has to say about the new changes.

Having a single level menu just became mandatory

Another point to underline is that having a single level VS extension menu just became mandatory. Visual Studio 2019 just introduced the Extensions top level menu and extensions cannot have their top level menus anymore.

Visual Studio 2019 Extensions Menus

This move adds an extra click for accessing each extension feature. This extra click represents a UI regression for the millions of VS extensions users and de-facto discards features accessible only through a nested sub-menu. This move was unexpected because it solves a UI problem we (as a VS extension provider) have never heard of: having so many extensions menus that it becomes a cluttering problem. The only right way to solve such problem would be to let the user choose which extension have their top-level menu and which extension lies under the Extensions menu. An extension menu should be top-leveled by default upon installation: when a user installs an extension the goal is to spend the next minutes or hours trying it and using it. In this context it doesn’t make sense to put the extension menus in a second-zone, doing so degrades the so precious and fragile FTUE First-Time User Experience. A VS extension doesn’t get a second chance to offer a first impression to a trial user.

Several big names in the VS extension industry have already complained about this move here. You can vote and comment now because apparently Microsoft will monitor this thread only till mid May 2019.


 

We hope this simplified menu will help trial and beginner users getting started with all the NDepend goodies. Certainly some seasoned users will also prefer this less cluttered menu style. If you have comment or ideas to improve more let us know.

On forced UI change you can read further this 2012’s Scott Hanselman post Who moved my cheese?

People don’t like it when you move their cheese. They are just trying to get through the maze, they have it all under control and then, poof, someone moved their cheese. Now it’s a huge hassle to find it again. Change a hotkey or the case of the menus and all heck breaks loose.