Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (2024)

Essential productivity kit for .NET and game developers

Follow

  • Follow:
  • Guide Guide
  • RSS RSS

Get Tools

.NET Tools

While it may seem trivial, one of the first steps in creating a maintainable, team-friendly codebase is reaching a consensus on code style and ensuring its strict enforcement. This includes code formatting (spaces, blank lines, parentheses, and brackets), naming (casings, prefixes, suffixes, etc.), and usage of this, var and more. The ultimate goal? Make running a full automated clean-up on your codebase a routine task.

Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (3)

This blog post is a guest post by Gael Fraiteur, founder and lead developer of PostSharp Technologiesand Metalama.

In this article, I explain the practices we are following on the Metalama team. After all, since we are building tools that help C# developers write better quality code, it’s only logical that our own code is of the highest possible quality. Don’t take my words for granted: our source code is available on GitHub, so you can check for yourself if we live up to our standards.

Code Style As a Philosophy

You may be wondering, why all the fuss about code style? Let’s highlight two main reasons:

  1. A consistent style makes code easier to read. Since developers typically spend 80% of their time reading code, code quality is one of the most important factors for the long-term productivity of your team. There are tools, like ReSharper’s Virtual Formatter, that can help with reading code in a consistent style while you are in the IDE, but that doesn’t solve the issue in other places where code is read, such as your Git repository.
  2. A uniform code style simplifies pull requests and merges. Have you ever been frustrated by irrelevant changes appearing in a PR diff because a developer ran a code cleanup? This annoyance could’ve been avoided if the code style had been adhered to from the start. Consistent code style also minimizes merge conflicts. One of the objectives of the code quality pipeline is that everybody should be able to reformat the entire codebase without causing a revolution in the team – as long as it’s done in a separate PR of course. In other words, complete reformatting should be a non-event.

Achieving Consensus on Code Style

While coding style can be a matter of preference, it’s crucial that everyone on the team aligns with a chosen convention. Everyone will have their own opinion, which can easily lead to endless and heated debates. Your main objective here is to get through the consensus-building process as soon and quickly as possible.

  1. I suggest starting with Microsoft’s common coding convention for C#. It’s a solid starting point, widely accepted by the C# community, but it doesn’t cover every detail.
  2. At the beginning of the project, you might still find yourselves in lengthy discussions. Don’t dismiss these debates: it is better to have them sooner than later. Listen to all arguments swiftly, remind everyone that the emphasis is not on the chosen style itself, but on making an unambiguous decision that will be consistently applied. Ensure everyone is aware of the bikeshedding dynamics in collective decision-making. Then, let the most experienced developer make the final call.

Remember, deciding on a coding style is an iterative process. Don’t spend too much time on this step – you’ll revisit it later.

Configuring Your IDE

Next, you need to configure your coding style in the IDE.

Configuring Code Formatting

To keep everyone on the same page, store the coding style configuration in the source repository, not in the user profile. This file is typically named .editorconfig. The EditorConfig format is supported by Visual Studio, ReSharper, Rider, and many other editors.

Here’s how you can use the Code Style editor in Visual Studio:

Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (4)

Your code style configuration should be thorough and specific, leaving no room for personal interpretations. I recommend setting the severity to warning whenever practically possible. Some formatting rules are brittle because they can be easily broken if you have #if clauses in your code. On our team, we turn off any brittle rules. We only enforce code formatting in the Debug build configuration because having a zero-warning codebase for all platforms and all configurations is very cumbersome for minimal benefits.

In addition to .editorconfig, we also use JetBrains’ tools due to their superior code formatting and cleanup capabilities. Here’s the Rider settings dialog:

Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (5)

In our team, we set up the same team-shared layer in Rider in each solution to ensure the Rider configuration is stored in the source repository. So instead of the *.sln.DotSettings file, we create a different layer file that can be imported from all solutions in the repository. To access layers, click on the Managed Layers at the left bottom corner of the settings dialog.

Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (6)

When the layer is created, make sure to save your code style changes into the proper layer.

Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (7)

It’s a good practice for team members to reset their code style settings in both personal layers.

Feel free to copy our .editorconfig and CommonStyle.DotSettings.

Configuring Code Cleanup

Now that you have set up your code formatting preferences, the next step is to configure a code cleanup profile.

I suggest adding all harmless fixers, i.e., those that make minor syntax changes and, most importantly, are 100% bug-free. For example, include Apply parenthesis parameters and Add this qualifications, but not Make field readonly because this analysis sometimes makes mistakes. The ultimate goal is to be able to use your IDE’s clean up feature confidently and without any manual tweaking afterward, so I would avoid any risky fixer.

Unfortunately, Visual Studio does not allow saving cleanup profiles in source control. Ideally, all team members should use the same profile. While Visual Studio offers a cleanup on save option, I am not using it because it sometimes has bugs, and when it does, you have no way at all to fix them except by opening your file in another editor than Visual Studio.

Rider, on the other hand, allows storing the clean-up profile in the team-shared settings layer. Instead of format-on-save, Rider can automatically perform a code cleanup before each commit. I personally don’t use this feature because I always use Rider for git commits. Besides, since some of my teammates prefer Visual Studio, we need a vendor-neutral solution.

Reporting Warnings for Style Violations

Remember that our goal is to improve the team’s productivity, both in the short and long terms. If your process is too lax, your code quality will degrade, and you will hamper your long-term productivity. However, if your process is too strict, any build or pull request could become a nightmare.

Therefore, it’s essential to find a good balance. We’ve found the following compromise to work well for us:

1. We set the severity of most code style violations to warning. For instance, our coding style requires all instance members to be qualified with this, which translates to the following lines in .editorconfig. Note the warning setting:

dotnet_style_qualification_for_event = true:warningdotnet_style_qualification_for_field = true:warningdotnet_style_qualification_for_method = true:warningdotnet_style_qualification_for_property = true:warning

2. To ensure code style is enforced during the build, set the EnforceCodeStyleInBuild property in your Directory.Build.props:

<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>

3. We allow builds with warnings on development machines. Why? Because you certainly don’t want to have a perfectly formatted build every time you want to run your tests or your apps.

4. However, in CI builds, we treat warnings as errors. This way, code with style issues won’t be merged. To detect continuous integration builds, use the ContinuousIntegrationBuild property or the specific environment variable of your CI pipeline.

<PropertyGroup Condition="'$(ContinuousIntegrationBuild)' == 'true'"> <TreatWarningsAsErrors>true</TreatWarningsAsErrors></PropertyGroup>

While this article focuses on code style and conventions, you should also enable code analysis for various rulesets. Check out Overview of .NET source code analysis for more details. We on the Metalama team are also using StyleCop, which is redundant with Rider/Resharper analysis but integrates directly with the C# compiler.

Avoid being too strict about whitespace violations. Requiring an exact number of whitespaces for a merge could lead to multiple rounds of whitespace fixing commits, which can slow down productivity. Remember, your ultimate goal is to improve productivity, not to achieve a whitespace-perfect codebase.

Planning for Periodic Full Cleanups

At this point, your development and build pipeline should ensure that PRs are reasonably well-formatted before they undergo code review. While demanding perfection for each PR is impractical, formatting defects can accumulate over time, necessitating a thorough cleanup.

On the Metalama team, we perform a comprehensive cleanup immediately after the dev freeze milestone of each release, usually every 6 to 12 weeks. The goal is to periodically restore the codebase to perfect order.

Running the cleanup tool should be a non-event. It should be entirely deterministic, non-disruptive, and not cause any frustration.

You have two main options:

  • dotnet format is a .NET SDK command-line tool that reformats code to align with .editorconfig settings. However, its capabilities are currently limited. For me, “good enough” means being entirely satisfied with the tool’s output, and dotnet format isn’t quite there yet.
  • JetBrains offers two types of cleanup tools. You can use the interactive tool in ReSharper or Rider, or ReSharper’s CleanupCode command-line tool. The latter is free and doesn’t require a license for the entire team if all you need is code reformatting. This is what our team uses. You will need at least one license to set up the correct configuration.

To ensure all runs produce the same predictable output, create a script that runs the tool with the exact parameters. This output, termed the canonically formatted code, should be your gold standard.

From this point forward, no one should be blamed for reformatting code to its canonical form. Instead, the blame should be placed on the developer merging non-canonical code.

Taking Code Validation to the Next Level

If you’ve successfully implemented all the above steps, congratulations! Your processes now ensure consistent adherence to the code style, making team members more confident in reformatting and refactoring code.

To further enhance codebase maintainability and readability, consider validating your codebase with more complex rules. For instance, enforcing that all classes implementing IFactory end with the *Factory suffix, or checking that no one uses the double type in the Billing namespace (you should use int or decimal for any money!). Consider writing architectural unit tests or using our tool Metalama to enforce naming conventions and verify dependencies.

For example, here is how you could enforce a naming convention using Metalama:

[DerivedTypesMustRespectNamingConvention( "*Factory" )]public interface IFactory<T>{ T Create();}

And here is how you could prohibit internal members of a namespace from being used from a different namespace:

namespace TheNamespace{ internal class Fabric : NamespaceFabric { public override void AmendNamespace( INamespaceAmender amender ) { amender.Verify().InternalsCanOnlyBeUsedFrom( r => r.CurrentNamespace() ); } }}

Conclusion

Code formatting is a crucial step towards creating a maintainable, team-friendly codebase. Adhering to and enforcing a particular style creates an environment that improves code-reading productivity, a critical factor considering that developers spend a whopping 80% of their time reading code. Consistent style also reduces merge issues and simplifies pull requests. A clean, well-maintained codebase is a pleasure to work with and the pride of every team member.

What is the code style strategy your team is using? Let us know in the comments!

code style ReSharper Rider

  • Share
  • Facebook
  • Twitter
  • Linkedin

Prev post Rider 2024.2 EAP 3 Is Out!dotCover Command Line Tools for Automation Testing Code Coverage Next post

Subscribe to a monthly digest curated from the .NET Tools blog:

Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (8)

Discover more

dotCover Command Line Tools for Automation Testing Code Coverage Learn how to use the dotCover command line tools to run coverage analysis on any .NET process that has available PDB files. Khalid Abuhakmeh
The ReSharper 2024.2 Early Access Program begins! We are excited to announce the launch of the Early Access Program (EAP) for ReSharper 2024.2! This initial EAP build is now available for download and offers a preview of the upcoming features and enhancements. Your feedback is crucial in helping us refine these updates, so we encourage you to try o… Sasha Ivanova
Rider Starts Its Early Access Program for Version 2024.2 The Early Access Program for Rider 2024.2 has just begun! There are several ways for you to get your hands on the first preview build:Download and install them from our website.Use the Toolbox App.Install this snap package from the SnapCraft store if you’re using a compatible Linux dist… Sasha Ivanova
Rider 2024.1.3 and ReSharper 2024.1.3 Updates Are Out! Another set of updates to the latest major releases of Rider and ReSharper have just been released. Just like the previous update, this one contains more than just fixes. Let’s take a look!ReSharper 2024.1.3New inspection for unawaited calls to PartialAsync in RazorWhen develop… Sasha Ivanova
Code Style for Better Productivity - Tips and Tools from the Metalama Team | The .NET Tools Blog (2024)
Top Articles
Latest Posts
Article information

Author: Delena Feil

Last Updated:

Views: 5912

Rating: 4.4 / 5 (45 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Delena Feil

Birthday: 1998-08-29

Address: 747 Lubowitz Run, Sidmouth, HI 90646-5543

Phone: +99513241752844

Job: Design Supervisor

Hobby: Digital arts, Lacemaking, Air sports, Running, Scouting, Shooting, Puzzles

Introduction: My name is Delena Feil, I am a clean, splendid, calm, fancy, jolly, bright, faithful person who loves writing and wants to share my knowledge and understanding with you.