Showing posts with label .NET. Show all posts
Showing posts with label .NET. Show all posts

Improve code quality in .Net applications

Writing source code for any requirement is always a head-scratching activity. But when it comes to improving the quality of code, it seems to be a different world.

Though maintaining code quality looks like overhead at the beginning of the project, but as code grows and the development team expands, the initial effort on focusing on setup quality gateways looks fruitful.

Few tools and techniques are summarised here which should become an integral part of each .Net project.


Improve Code Quality in .Net

Find unused code:

ReSharper is one of the best code analysis tools that can be integrated with Visual Studio

To find unused code in your solution right-click on the solution > Select "Find Code Issues" > One of the results is "Unused Symbols". This will show you classes, methods, etc. that aren't used.

Reference - https://stackoverflow.com/questions/245963/find-unused-code

Discover dead code using Visual Studio Code Analysis:

Visual Studio provides this feature out-of-the-box. Right-click on the solution > Analyze > Run Code Analysis on Solution.

Reference - https://blogs.msdn.microsoft.com/habibh/2009/07/31/discover-dead-code-in-your-application-using-code-analysis/

Static code analysis tool:

StyleCop and FxCop are the most popular tools that can be included in the project to maintain coding standards defined by the organisation. 

They are available as a NuGet package and gets auto-configured when added. These tools follow basic coding standards defined by Microsoft but can be customised further as per the need.

It can be configured to fail the build if any of its code quality checks fail. It can also be configured to fail the build if any warnings are identified. This ensures the code delivered is of optimum quality.

Enable Gated check-in using VSTS Build Definition:

Gated check-in builds ensures that the checked-in code is always free from compilation errors. This can be enabled in Visual Studio using TVFS projects using VSTS Build Definition, though this feature is still not available in Git team projects.

Reference - https://www.codeproject.com/Tips/1168853/Enabling-Gated-Check-in-using-Visual-Studio-Team-S

Code coverage analysis:

Code coverage analysis is available out-of-the-box in Visual Studio. This analysis indicates the percentage of unit tests written for the project.

The attribute [ExcludeFromCodeCoverage] can be applied to the class files that need to be excluded from code coverage. Make sure not to apply this attribute on the application code, as it will produce over-inflated coverage metrics.

Class files created automatically by adding service references must be excluded from code coverage. The CodeCoverage.runsettings file can be used to accomplish this.

Include automation scripts:

When development is in progress, there are several instances where fixing one issue or developing a new story would unexpectedly break existing functionality. 

QA team can only focus on testing the specific feature or user story in a sprint. But as the system scales, it becomes practically impossible for the QA team to perform integration testing in each sprint.

Automation scripts are proven to be a boon in such cases which can be executed either manually or scheduled after each deployment. This can also be added into the Continuous Integration pipeline to automatically run after each deployment.

Selenium scripts are recommended for automated testing in .Net applications. Selenium is powerful enough to execute scripts on the server even in absence of any browser. This is made possible by adding a specific browser driver as a NuGet package. Some browsers like chrome can be run in headless mode to execute the scripts faster as this will run chrome in the background.

Though surprising it is not recommended to use Internet Explorer anymore but focuses your application to fully functional on Chrome or Firefox.

Use mocking framework:

Mocking frameworks like NSubstitute or MOQ helps to write unit tests by mocking the reference layer. This means while writing unit tests for the web layer you can mock the business layer; similarly while writing unit tests for the business layer you can mock the service layer.

Design patterns:

Few design patterns are a must-have for any development. They include dependency injection, factory pattern, service pattern and repository pattern.

Dependency injection with Unity framework can be easily integrated with a NuGet package. It is highly recommended to use the DI pattern as it also helps in writing effective unit tests with a mocking framework.

Exclude NuGet packages from code check-in:

TFS or VSTS can be configured to download the NuGet package from nuget.org during the Build process.

Whenever a NuGet package is added to any project, it not only download its assemblies but also adds an entry into packages.config file. Hence it is the best approach to eliminate any NuGet package from check-in into source control and just check-in respective packages.config file.


Build quality checks:

Add task "Build Quality Checks" in the VSTS Build process. Build can be configured to break based on quality metrics like a number of warnings or code coverage.

You can also specify a code coverage threshold that is the minimum code coverage value in percentage terms.

Technical Aspects

Exceptions add significant overhead to your application. Do not use exceptions to control logic flow, and design your code to avoid exceptions where possible. For example, validate user input, and check for known conditions that can cause exceptions. Also, design your code to fail early to avoid unnecessary processing.

Exceptions are expensive considering the performance. So it is better to use conditional checks rather using exceptions.

The @@scope_identity() is used to get the identity value of the last update. As the trigger is not in the scope of a stored procedure, hence the last update identity value for trigger can be achieved by using @@identity()

N'123' - Here "N" denotes a unicode string or nvarchar string. This is used when the argument required is of unicode format.

Resource files ".resx" are compiled to ".resources" using "resgen" utility.
DELETE TABLE is a logged operation, so the deletion of each row gets logged in the transaction log, which makes it slow. TRUNCATE TABLE also deletes all the rows in a table, but it won't log the deletion of each row, instead it logs the deallocation of the data pages of the table, which makes it faster. Of course, TRUNCATE TABLE can be rolled back.

The ASP.NET State Server is a Windows service that runs on any machine where Framework is installed.

An assembly with culture information is automatically assumed to be a satellite assembly.

Struct is similar to Class, but Struct imposes less overhead. Hence Class is intended to represent complex datatypes.

Value types impose less overhead than reference types because they’re allocated on the stack, not the heap.

CLR uses heap that's called managed heap.

Hashtables implements Idictionary and hence cannot be XMLSerialized, but they can be BinarySerialized.

Joins are faster than Sub-queries.

Clustured index is automatically applied when primary key is assigned to a table.
Clustured index information is stored in the table itself, whereas non-Clustured information is stored outside the table.
Insert can be slower on clustured indexes. When a row is to be inserted between two rows, then first the rows are to be adjusted such that the new row can be accomodated between the two rows. Whereas in clustured index, the index information is stored apart from table and hence the row can be added at the end of table and index information is stored in place other than table.
Clustured index is used when large amount or rows are returned especially using comparison operators.
Non-clustured index is used when minimum rows (1 row) is to be returned.
Clustured index can be applied on composite key.
If clustured index is increased from 3 or 4 index on a table, then it will degrade the performance.
Clustured index on table increases the performance.
There can be only one clustured index on one table whereas there can be multiple non-clustured index on one table.

Overloading means having two methods with same name but different signature.

Overriding means having two methods with same name and signature but one in base class and other in derived class.

Boxing is conversion of value type (integer, string, …) to reference type (object). And Unboxing is vise-versa.

Overloading and Overriding are types of Polymorphism.

Application_BeginRequest is called on arrival of each request whereas Application_Start is called when the first request is arrived for the application.

One assembly can have one or more namespaces. Also, one namespace can span across multiple assemblies. You can create nested namespaces. If you are using VS.NET then the project name acts as the default namespace name.

The main difference between inheritance based programming and interfaces based programming is that - interfaces just specify signatures of properties and methods for a class. Your class "implements" the interface by providing implementation for various properties and methods. Unlike inheritance there is no "code" inherited from interfaces. Your class can implement one or more interfaces.

Exceptions are unpredictable errors during runtime whereas Errors are predictable.

Metadata is the complete way of describing what is in a .NET assembly. Digging into the metadata yields the types available in that assembly, viz. classes, interfaces, enums, structs, etc., and their containing namespaces, the name of each type, its visibility/scope, its base class, the interfaces it implemented, its methods and their scope, and each method’s parameters, type’s properties, and so on.

InstallUtil.exe is a .NET utility to install Windows Service.