Friday, October 5, 2012

Analyze code in Sharepoint projects with NDepend

In this post I will show how you may use NDepend tool for analyzing the code in your Sharepoint projects. When refer to Sharepoint I will mean Sharepoint 2010 mostly, but of course NDepend can be used with any version of Sharepoint, because it can analyze .Net assemblies v1.0 v1.1 v2.0 v3.0 v3.5 v4.0 v4.5 and Silverlight. I wanted to try it on some real task for a long time and recently had a chance to do that. Especially it is worth to mention that authors of NDepend give free license if you are MVP awarded, so I had everything I needed for starting using it :).

NDepend is very powerful tool, it contains many nice looking graphic reports and analysis statistics, and one article is not enough for showing all its features. I won’t describe all features here, instead I will show one particular use case in this article which however shows how useful it can be. There is one great feature called CQLinq (Code Query LINQ) which allows you to write LINQ queries to the codebase by the same way as you do when write LINQ query to objects, Sql or other data. The only difference is that codebase plays role of database.

Returning to the use case. On one of my projects I needed to analyze the code and find all custom classes which inherit standard Page and Control classes from System.Web.UI namespace and which contains static fields (no matter public or private). Static variables in codebehind class of the pages or controls may lead to potential problems with concurrent access, because they are shared across all instances of the class. Especially it will be hard to catch such errors in Sharepoint web applications where we often have several WFEs and code may be executed on different servers (it may hide problem even deeper). But of course it is just a warning. It is not necessary that static variables will cause such errors. Anyway we needed to review all of them, so I decided to use NDepend for that.

Let’s start with launching NDepend and creating new project:

image

It shows Project properties window where we can select VS project, solution or separate assembly which we want to analyze. For example if we want to analyze whole solution we should select “Add assemblies of VS solutions” button:

image

Convenient thing that NDepend will show you list of recently used solution in VS, so you don’t have to browse for them if you worked with them recently. It supports the following VS versions: 2005, 2008, 2010 and 2012.

After that all found assemblies are shown in the Project properties window (so solution should be compiled first). Important thing: by default NDepend uses target framework set to 4.0 or 4.5 versions. It means that if e.g. you are opening solution for Sharepoint 2010 (which is built on top of .Net 3.5), standard Microsoft assemblies like Microsoft.SharePoint.dll won’t be loaded and analyzed. You will see the following error:

image

In turn it means that when you will use CQLinq, types defined in this assemblies won’t be shown. E.g. if you have custom application layouts page which class inherits LayoutsPageBase class from Microsoft.SharePoint.ApplicationPages.dll, then its base class will be shown as null in NDepend.

In order to fix it at first you need to change target framework to 3.5. You can do it if will click “View folders that contain .Net assemblies to analyze” button:

image

Unfortunately after that Microsoft.SharePoint.* assemblies are still remain unresolved. I used the following workaround: copy necessary assemblies from C:\Windows\Assembly\GAC_MSIL to temp folder, and then select it in “Add .net assemblies in folder” window which is opened from the same Project properties window. After I specified my temp folder all Sharepoint assemblies became resolved. The last step was selecting necessary Microsoft.SharePoint.* assemblies for analysis by clicking “Move selected to application assemblies” on each of them.

At this point you have everything ready for analysis. Click “Run analysis on current project” button on top of Project properties window or press F5. NDepend will analyze codebase and will show you a lot of statistics. For us it is important that after analysis it will allow you to write CQLinq queries to the codebase. When analysis will be done it will show you the following window where you can choose the next steps:

image

In our case we need to select “Browse NDepend interactive code rules”. After that in the left doc window choose “Queries and rules edit” and write the following query:

   1: let page = ThirdParty.Types.WithFullName("System.Web.UI.Page").FirstOrDefault()
   2: let control = ThirdParty.Types.WithFullName("System.Web.UI.Control").FirstOrDefault()
   3:  
   4: from t in JustMyCode.Types
   5: where (t.DeriveFrom(page) || t.DeriveFrom(control)) &&
   6:     t.FullNameLike("MyNamespace") &&
   7:     t.StaticFields.Any(f => !f.IsGeneratedByCompiler)
   8: orderby t.Name
   9: select new { t, t.FullName, StaticFields =
  10:     string.Join(";", t.StaticFields.Where(f => !f.IsGeneratedByCompiler)
  11:         .Select(f => f.Name).ToArray()) }

Syntax of CQLinq expressions is described here. On lines 1 and 2 we define variables for page and control types which we will use in query. Then on lines 4-9 we write actual query to the codebase. So we select all custom types (from t in JustMyCode.Types) which inherit Page or Control class from specified namespace (t.FullNameLike("MyNamespace")) which has at least one non-compiler generated static field (t.StaticFields.Any(f => !f.IsGeneratedByCompiler)). Then we just select new anonymous object with convenient properties representation: we join names of all static properties using semicolon (select new { t, t.FullName, StaticFields = string.Join(";", t.StaticFields.Where(f => !f.IsGeneratedByCompiler).Select(f => f.Name).ToArray()) }). As result we will have list of all classes which inherit Page or Control with list of static variables for each class. It will show you also classes which have const strings because it is treated as static field, I didn’t find a quick way to get rid of it, because it was not crucial. Already this report contained almost everything I needed. Report can be exported to html, excel, text or even graphics representation.

As you can see NDepend may be very helpful in such task where you need to analyze codebase for some specific usages. It uses LINQ queries familiar to most .Net developers, so you won’t have big problems with writing them if you worked with LINQ before. Hope this post will help you if you will want to use NDepend with Sharepoint and will be good starting point for using NDepend in your work.

No comments:

Post a Comment