Taking over a .NET project to modernize it
Last modified: 2018/11/08 | Approximate reading time 5 mins
Whether it's your own project that you want to update or a project from another programmer or another team that you are taking over for maintenance, you probably want to take advantage of the latest technical advances by integrating them into your project, while not compromising its stability.
Version control system
Let's assume that your code is kept on a version control system, which allows you to keep the different versions of your code. There are several on the market, free and paid. They all offer the same basic functionalities, so no need to compare them for the purpose we set here. If there is a difference, it is mainly in the tools related to the management of the source, especially the management of teamwork, as well as the integration of tools for continuous integration.
You will also be able to experiment with the various techniques proposed, in parallel with the urgent work that needs to be done through a branch or branches of development, a function which is offered by most source managers. Therefore, you can test the viability of a modification without hindering the progress of the project. The techniques offered here are also a good way to learn more about the code. Without applying these changes immediately in production, they can help you familiarize yourself with the code without going through requests for corrections or additions.
Is it used?
One of the first steps is to evaluate which code is still used. As a project lives on, some parts of the code may no longer be used. Either because the associated UI is no longer accessible, or because the operation has changed, and the part of the code in question is no longer used. But how to detect this dead code? Different techniques are possible and can be used depending on the type and structure of your project. For a monolithic project, and the compilation of which results in a user-executed assembly (such as a WinForms application, or WPF), it is possible to make most classes private.
Beware of certain types of serialization, and of the reflection whose operation can be influenced by the visibility of the classes. Once the visibility of the classes is reduced, you can use static code analysis provided by Visual Studio to detect parts of the code that are not used. Since this code is useless, you will avoid applying the next techniques and spending time on code that is no longer in use.
Compile warnings and static code analysis tools
For this step, make sure that the maximum warning level is enabled. Also check that if some warnings are ignored, the documentation is present to explain why, and if they are ignored only where it is justified to do so. The .NET compiler gives some hints of code problems. In addition to these basic warnings, you can use static analysis tools. Visual Studio has a basic one, but since the introduction of Roslyn, many scanners are available in different formats (Visual Studio extensions, NuGet packages), and can be used to detect problematic parts of the code.
Some extensions specialize in the good practices of some specific modules such as asynchrony, others are more general. It's up to you to experiment with the ones that suit you best, most of which also allows to enable or disable certain rules. Also prefer extensions that provide examples of patches, in order to be guided. Some warnings may require significant changes in the structure of the code, especially those related to the concept of Disposable.
It can be better to wait for integration tests and unit tests to be introduced before making these changes. However other warnings can be adjusted with more assurance, depending on your experience. The warnings leading to a possible improvement in performance are the most interesting to fix because they give visibility to the improvement work that has been completed.
Unit Testing and integration tests
Some warnings will not be able to be fixed without wider and more complex code changes. It is better, in this case, to set up tests before making the changes. These tests can take several forms. In the case of calculations, it may be interesting to have unit tests that validate that for some entries, one has the expected result. These tests cover a well-defined code unit. Further tests will require the use of several parts of the software; one speaks in this case of integration tests.
The tests will give you a guarantee when the code changes and you will avoid having to manually test your application. A manual test step may be necessary to discover the tests to be performed, and you should also consult your end users, to make sure you test the most frequent use cases. Once the cases are determined, it is necessary to maximize the automation of these tests, to execute them as frequently as possible, and to document them.
Compartmentalization of the Code
Once these steps are done, you should have gained a better understanding of your code. You may realize that to facilitate your testing, you will have to review how your code is organized. Indeed some treatments that need to be tested may have a problem functioning without a dependency that cannot be automated (specific computer hardware, or a Web service for example). You will have to compartmentalize these dependencies so that they can be simulated at the time of testing.
Converting the VB.NET code
This point is a bit more controversial, but the VB.NET language was primarily thought of as a transitional language between the VB6 platform and the .NET platform. Microsoft training and certifications are almost always provided in C#, as are almost all the .net open-source projects. So, it can be interesting to facilitate the integration of new programmers to convert the project from VB.NET to C#. This is, however, a tricky step that will create a certain break in the history of the code, so it is up to you to decide the best time, and whether this conversion should really take place.
As a first step, set yourself the goal of exploring these different points in a time limit, and not necessarily keeping the result. You will learn what changes seem to pay the most, and which can wait. You will also learn a lot about your code, and this will bring you to question its general structure. At this point, you will need to look for resources that will allow you to strive for stronger software architecture if the need arises, to best guide your next changes, whether regarding fixes or adding features.