How to Modernize an Enterprise Application to .NET 8 and Lose 75% of the Code 👑

The current software development challenge for Microsoft developers, is getting large .NET projects into .NET 8 (soon to be .NET 9).

Modernizing the codebase is crucial as developers need efficient code, maintainable code, and a scalable app. At SSW we have been on this migration journey, migrating a bunch of client’s large enterprise applications for the last two years.

This blog post dives into our internal journey of TimePro’s migration to .NET 8, highlighting the metrics, and what the more organized codebase ends up looking like.

The Challenge


TimePro, is an application with a codebase that has grown organically over the years from .NET Framework 1.0 to .NET Framework 4.8. We faced the typical challenges of legacy systems. The need to transition to .NET 8 presented an opportunity to not only upgrade the technology stack, but also to streamline and enhance the code structure.

Codebase Comparison: Before and After Migration

When working on software projects, it’s important to keep track of your codebase’s size and structure. Code line metrics help you understand the scope of the code, identify potential areas for refactoring, and maintain a healthy balance between files, blank line comments, and code.

With these metrics, you get a sense of the size of your project, compared with other projects you’ve dealt with.

The tool cloc is a straightforward yet powerful way to count the number of files, blank lines, comment lines, and physical lines of source code across various programming languages. Check out this SSW Rule: https://www.ssw.com.au/rules/get-code-line-metrics/

After collecting raw data using the cloc tool, you can use ChatGPT to generate insightful charts that visualize your codebase’s metrics. These charts make it easier to understand trends and compare different parts of your code. Check out the SSW Rule:
https://www.ssw.com.au/rules/use-chatgpt-to-generate-charts.

Let’s look at the stats for SSWTimepro.com

1. File Count Reduction

– Before Migration (.NET 4.8): The codebase had a ton of files, obviously contributing to complexity.

– ✅ After Migration (.NET 8.0): The file count was reduced by a whopping 22%. We landed with a simplified structure, and it was easier to navigate.

2. Code Lines Reduction

 – Before: The original codebase had many lines of code that were redundant (or could be optimized).

– ✅ After: The code lines were reduced by 75%. We trimmed a lot of unnecessary code and leveraged many .NET 8 native features as much as possible.

3. Blank Lines Reduction

 – Before: TimePro had a significant number of blank lines – the problem was more the inconsistency than the number of blank lines.

– ✅ After: The blank lines were reduced by 62%… however if correlated to code lines, it would have been 75% – so it appears more blank lines were added, aiding consistent readability.

4. Comment Lines Reduction

 – Before: A high number of comment lines, is often not needed if the code is self-explanatory. A lot of comments can indicate complicated code that needs explanations. Or redundancy which is clutter.

– ✅ After: The comment lines were reduced by a massive 95%, indicating better self-documenting code practices.

After the migration, we now have 43k blank lines vs 185k code, which is 23% or roughly 1:4 ratio. This means that we have a new line after 4 lines of code. It’s like having a book that has reasonably sized paragraphs for people to read. We achieve that by making a code block that can be read as a single unit, for instance, updating the timesheet’s total and tax amounts.

ValuesPre-MigrationPost-MigrationDiff (reduced)
Sum of files3,5752,796-22%
Sum of blank142,08953,359-62%
Sum of comment400,15318,608-95%
Sum of code1,316,353327,399-75%
Figure: Code metrics before and after .NET 8 migration
Figure: TimePro lost 75% of it’s code 👑 – Before (.NET 4.8) vs Migrated (.NET 8) – see data at the end of the blog

Efficiency and Maintainability

The migration to .NET 8 and EF Core 8 (aka EF8) was not just about adopting new technology, but also about making the codebase more efficient and maintainable.

The new codebase is designed with a Modular Monolith architecture (thanks to Daniel Mackay who leads the SSW Software Architects team), enhancing the quality and maintainability of the code. This architecture allows for easier introduction of microservices when needed, ensuring that TimePro can scale and adapt to future requirements.

Insights from the Migration

  1. App Modernization: The team focused on modernization to .NET and trimming any fat that was remnants from prior versions. This meant that the final.NET 8 looked completely new.
  2. Code Removal: At least 50k lines of code were removed as part of the migration to EF Core 8 and leveraging existing .NET features that weren’t available in the .NET Framework.
  3. Dependency Removal (NuGet): There was one commit that removed 1 million lines of code – because a new Dynamics library meant a lot of code could be killed.
Video: TimePro – Moving to .NET 8 and removing 1 million lines of legacy code
Our team replaced some legacy CRM NuGet packages, to new Power Platform NuGet Packages and that meant we had a commit that reduced the codebase by over 1 millions lines of code. Can you beat that?

A comparison of TimePro vs other .NET enterprise projects

Figure: (graph generated by ChatGPT) – The stats give TimePro context to other enterprise .NET projects

The chart above represents the comparison with:

  • BlueShift One (an enterprise planning system for fast-moving consumer goods suppliers, managing their volume and financial forecast in the context of highly elastic in-store promotions)
  • SSWEagleEye.com (an email and GitHub AI-based reporting tool)
  • SSWTimePro.com (a timesheet and billing system with integration with Dynamics, Azure DevOps, and GitHub)
  • SugarLearning.com (a learning management and induction system)

Conclusion

I encourage you to start with a well-planned migration process. The TimePro migration to .NET 8 was a substantial task – but it is important to continuously modernize any project, if the software is going forward for the business. While doing the migration we made sure that there was a focus on code quality and code organization, so the application was in a nice maintainable state.

The migration team did it over a bunch of 1- week Sprints. I was impressed with the TimePro team’s journey, and as the Product Owner I learned many valuable things that will help me with similar challenges when migrating other legacy systems. I am sure there are a lot of old important .NET applications out there!!!

When do you plan to migrate to .NET 8? Let me know in the comments 🥳

More Info:

 Sum of filesSum of blankSum of commentSum of code
 Pre-MigrationPost-MigrationPre-MigrationPost-MigrationPre-MigrationPost-MigrationPre-MigrationPost-Migration
ASP.NET413000391
C#1,8891,83485,98543,088165,3099,040821,420184,213
C# Generated127217,79023188,47513221,23391
Cake Build Script1126352222210269
Diff44443434108108
DOS Batch331015052029
F# Script1188003636
HTML1301425435391461089,3239,284
INI2445458001751,151
JavaScript4144015023334
JSON3835430015,8711,923
Markdown36614811,0760151,3222,606
MSBuild script353818814039149,6711,247
PowerShell2122257253911091,0551,095
Razor8681,2465132,3731,1458,7042,956
SCSS841041,2581,3881,0911,0954,3784,988
SQL3001420,4322,33132,1605,979198,96080,801
SVG16300313,10138
Text28111334003,1791,855
TypeScript4154417,9323,3226,84655744,12724,379
Visual Studio Solution231222509527
XML129581,6241071,121292113,8539,417
YAML2535501058200351
Grand Total3,3572,796138,04953,359397,73718,6081,257,727327,399
Figure: Breakdown by Language