Team Development Series – Part 5: Leveraging Code Analytics (Ravi Eda)

Team Development Series – Part 5: Leveraging Code Analytics (Ravi Eda)

Rate This
  • Comments 1

This article demonstrates the usage of code analytic tools available for LightSwitch in Visual Studio 2013. Analytic tools that will be covered include - Code Analysis, Code Metrics, Code Maps and Remote Debugging.

Code analysis tools enable developers to improve their code. These tools help find code issues early in the development cycle, find bug patterns, and complement traditional testing techniques. These tools enable developers to follow standard design and coding practices that improve maintainability, readability and minimize complexity of the code. These tools are invaluable in a team development setting where multiple developers work on the project, and new developers who are unfamiliar with the code base are required to ramp up quickly and contribute.

To show the usefulness of these tools, let us take an example wherein a simple LightSwitch application is developed. To keep things simple, this example considers a one person team developing the application.

Scenario

A manager of a software development team, let us call him John, would like to host a morale event for his team. To keep most members on the team happy, John would like to have the employees vote for morale events. The event that gets the maximum votes will be chosen as the morale event for the team. To keep things orderly, John wants to allow each employee to cast no more than three votes. John learns that LightSwitch is the simplest way to build a ballot application that fits this need.

John quickly comes up with a ballot application that contains a table named MoraleEventVote with three properties as described below:

  • VoteFor – a choice list of morale events available for the team to vote
  • VotedBy – will be set to the name of the current employee casting the vote
  • InvalidVote – to determine if a vote is valid. If an employee had already used all three permissible votes, any new vote after that will be deemed invalid for that employee.

To implement the necessary business logic for these properties, John adds code to the _Inserting event via the Data Designer, which ends up in the ApplicationDataService class.

C#:

        public int vote;        
        public int Vote_Count
        {
            get
            {
                return vote;
            }
            set
            {
                this.vote = value;
            }
        }

        partial void MoraleEventVotes_Inserting(MoraleEventVote entity)
        {
            // Get the name of the current Windows user. 
            String currentUser = this.Application.User.FullName;

            // Get the first name of the user. 
//Assumed that a space exists between first and last name.
entity.VotedBy = currentUser.Substring(0, currentUser.LastIndexOf(' ')); // Get the number of votes casted by the current user. vote = DataWorkspace.ApplicationData.MoraleEventVotes.
Where(p => p.VotedBy.Equals(currentUser)).Count();
// Invalidate the current vote if more than three votes were already casted. if (vote >= 3) { entity.InvalidVote = true; } else { entity.InvalidVote = false; } }

VB:

        Public vote As Integer
        Public Property Vote_Count() As Integer
            Get
                Return vote
            End Get
            Set(value As Integer)
                Me.vote = value
            End Set
        End Property

        Private Sub MoraleEventVotes_Inserting(entity As MoraleEventVote)
            ' Get the name of the current Windows user. 
            Dim currentUser As String = Me.Application.User.FullName

            ' Get the first name of the user. 
' Assumed that a space exists between first and last name.
entity.VotedBy = currentUser.Substring(0, currentUser.LastIndexOf(" "c)) ' Get the number of votes casted by the current user. vote = DataWorkspace.ApplicationData.MoraleEventVotes. Where(Function(p) p.VotedBy.Equals(currentUser)).Count() ' Invalidate the current vote if more than three votes were already casted. If vote >= 3 Then entity.InvalidVote = True Else entity.InvalidVote = False End If End Sub
 

A couple of screens are added to allow employees to cast their votes. John finds that Windows authentication is most appropriate for an internal team application like this one so he sets that up. Finally, he uses the LightSwitch publish wizard to deploy the application to one of the IIS machines available for the team. John launches the app and performs security administration so that ProjectManager permission is assigned to each project manager in his team.

The rest of this article will demonstrate how code analytics will enable John to produce an app that is more maintainable, less complex and readable.

Code Analysis

Code Analysis is a tool that enables developers to discover potential issues such as design problems, naming issues, globalization, maintainability, interoperability, usage violations and non-secure data access. New features were added to Code Analysis in Visual Studio 2012 and Visual Studio 2013.

LightSwitch in Visual Studio 2013 introduced a flattened project structure in the Solution Explorer. This structure enables Code Analysis tools to run successfully on LightSwitch projects. So just like any other Visual Studio solution, to run Code Analysis on a LightSwitch solution, select “Run Code Analysis on Solution” option from the context menu of root node in Solution Explorer. Code Analysis can be run for each project within the solution. Note: Code Analysis runs on projects with managed code, like the Server project. It does not apply to JavaScript-based projects, like the HTML client project.

Run Code Analysis on Solution

 

Let us see if Code Analysis can help John identify any code convention violations in the ballot application. Notice that there will be no warnings in the Code Analysis results window. The default rule set for Code Analysis is set to “Microsoft Managed Recommended Rules”. This rule set did not find any violations in the ballot application. Change the rule set to “Microsoft All Rules” and re-run Code Analysis by clicking “Run Code Analysis on Solution” as shown in the previous screenshot. Now there will be some warnings displayed. The Code Analysis results window provides the option to sort and filter these warnings. John wrote the logic in the ApplicationDataService class so let us focus on Code Analysis warnings that come from that class. There should be two warnings as shown in the screenshot below. Note that the screenshot shown here is for C# code, however, the equivalent code in VB would cause the same two warnings.

Code Analysis Results

CA1051 Do not declare visible instance fields” - This refers to the code statement where the variable “vote” has access modifier as public.

CA1707 Identifiers should not contain underscores” - This refers to the underscore in “Vote_Count”.

So let us fix these code issues.

A good coding practice is to control the set and get operations for a variable like “vote”. These operations should happen through the accessor methods. This will be possible when the access modifier for the variable is private. So to fix the first Code Analysis warning, change the access modifier for vote from public to private.

Following a naming convention improves readability and thus maintainability of the code. Naming convention in .NET does not recommend underscore characters in identifier names. So to fix the second Code Analysis warning, just remove the underscore character in “Vote_Count”.

After these two fixes, select Solution from Analyze dropdown located in Code Analysis results window. This will re-run Code Analysis on the solution. This time there should be no warnings in the results. John’s ballot application complies with .NET code conventions.

Code Metrics

Code Metrics enables developers to understand the current state of project, evaluate design, and follow best software development practices.

To run Code Metrics on a LightSwitch solution, select “Calculate Code Metrics” option from context menu of the root node in the Solution Explorer. Code Metrics can be generated at the project level as well. Similar to Code Analysis, JavaScript projects, like the HTML client project, do not support Code Metrics.

Run Code Metrics for the ballot application as shown in the screenshot below:

Calculate Code Metrics

The Code Metrics Results window will display the metrics generated for the ballot application as shown in the screenshot below:

C#:

Code Metrics Results for CSharp Solution

 

VB:

Code Metrics Results for VB Solution

Notice the values of Maintainability Index, Cyclomatic Complexity and Lines of Code for MoraleEventVotes_Inserting method. These values will change if the code were to be refactored. For example, the code that checks for the number of votes the current user casted can be refactored as shown below.

C#:

// Get the number of votes casted by the current user. 
// Invalidate the current vote if more than three votes were already casted. 
entity.InvalidVote = (DataWorkspace.ApplicationData.MoraleEventVotes.
            Where(p => p.VotedBy.Equals(currentUser)).Count() >= 3); 
 

VB:

' Get the number of votes casted by the current user. 
' Invalidate the current vote if more than three votes were already casted. 
entity.InvalidVote = (DataWorkspace.ApplicationData.MoraleEventVotes.
            Where(Function(p) p.VotedBy.Equals(currentUser)).Count() >= 3)
 

This refactoring makes “vote” and “VoteCount” unnecessary. So let us delete those members and re-run Code Metrics. Observe that in both C# and VB projects Maintainability Index increased, Cyclomatic Complexity and Lines of Code decreased, which generally indicates the new code is better.

C#:

Code Metrics Results for CSharp Solution after Refactor

VB:

Code Metrics Results for VB Solution after Refactor

 

Code Analysis, Code Metrics and other analysis tools can also be accessed through “ANALYZE” menu in Visual Studio menu bar.

Code Maps

Code Maps is a more user-friendly approach to creating and viewing a Dependency Graph of the code under development. This visualization is very helpful when the code base is large or unfamiliar.

Thanks to the new project structure in LightSwitch, this also allows generation of Code Maps. To generate a Code Map, select “Show on Code Map”, from context menu of a code file in Solution Explorer.

Show on Code Map

The Code Map for ApplicationDataService class is shown below. Notice that this visualization clearly shows the relationships between MoraleEventVotes_Inserting method and the member variables “VoteCount” and “vote”.

Code Map

Remote Debugging

Static code analysis tools cannot find errors that can happen while the app is running. For example, in the ballot application John assumed that all users will have a space separating their first and last names as shown in the following code:

C#

// Get the name of the current Windows user. 
String currentUser = this.Application.User.FullName;
// Get the first name of the user. Assumed that a space exists between first and last name. 
entity.VotedBy = currentUser.Substring(0, currentUser.LastIndexOf(' '));
 

VB:

' Get the name of the current Windows user. 
Dim currentUser As String = Me.Application.User.FullName
' Get the first name of the user. Assumed that a space exists between first and last name.
entity.VotedBy = currentUser.Substring(0, currentUser.LastIndexOf(" "c))

However, if an employee does not have a space between his/her first and last name then that employee will not be able to vote. The app would throw a runtime error as shown in the screenshot below:

Runtime Error

While developing the app, it is quite difficult for John to think of an edge case scenario where a user’s first and last name is not space separated. Static tools such as Code Analysis, Code Metrics and Code Maps will not identify this error since the flaw is in implementation of the logic and not in the code syntax. Manual code inspection such as code reviews from an expert may identify this flaw and produce better code that can handle such edge cases. Otherwise, this type of error can be found only when the app is live.

Say Bob is a user of John’s app and does not enter a last name. Bob launches the ballot application and attempts to vote. Bob runs into the error message shown above and is blocked from adding his vote. Neither does Bob have access to source code of the ballot app nor does he have access to the IIS machine that hosts the app. So Bob reports the error message to John. So to investigate this error, John enables diagnostics for the ballot application. Trace data shows that the error was caused due to a System.ArgumentOutOfRangeException “at System.String.Substring(Int32 startIndex, Int32 length)” in MoraleEventVotes_Inserting. In this simple example, it is easy to locate the line where the Substring method in invoked. Beyond this John does not have other debug information such as local variable values when this error happened. In such situations, Remote Debug option in Visual Studio is invaluable. Here is how John can use Remote Debug option to investigate the issue Bob is facing:

  1. On IIS machine:
    1. Install and configure remote debug
    2. Launch msvsmon.exe process to run as administrator. Note down the port number that will be listening to remote debug connections.
  2. On Bob’s machine:
    1. Launch the ballot app. This will start w3wp process on IIS machine.
  3. On John’s machine:
    1. Open the ballot app in Visual Studio
    2. Set breakpoint in MoraleEventVotes_Inserting at the statement that calls Substring method.
    3. Launch Visual Studio’s Attach to Process window.
      1. Set Transport to Default
      2. In the textbox against Qualifier, enter IIS machine name, a colon and the port number from step 1.2. For example, “MyIIS:4018”. If the remote debug connection is successful then the list of processes available for debug are displayed.
      3. Select w3wp process from the above list
  4. Ask Bob to enter a vote in the running app (step 2.1). Now the breakpoint set in step 3.2 will be hit.

Standard Visual Studio debug information such as Locals, Watch, Threads, Modules and Call Stack will be available for the developer. Now John can diagnose exactly what is happening in the running application and easily fix it.

One may wonder if Code Map can be used to visualize call stack. Yes it is possible in Visual Studio 2013. To get this visualization, select “Show Call Stack on Code Map” from context menu of Call Stack window as shown in the screenshot below:

Show Call Stack on Code Map

This will generate the Code Map for the call stack as shown in the screenshot below:

Call Stack on Code Map

Conclusion

The changes we made in the Solution Explorer enables a lot more capabilities in Visual Studio to be applied to LightSwitch solutions. This includes Code Analysis, Code Metrics and Code Map features. Please let us know what you think by downloading Visual Studio 2013 RC today and adding a comment below, or starting a conversation in the forums!

 

Ravi Eda, SDET, LightSwitch Team

Leave a Comment
  • Please add 6 and 3 and type the answer here:
  • Post
  • Thank You Ravi

    Nice article and very helpful.

    It looks like LightSwitch slowly covering all the gaps of master LOB application development.

    Thanks

Page 1 of 1 (1 items)