Incorrect Use Of Partial Classes

Incorrect Use Of Partial Classes

Photo by Rob Necciai on Unsplash

 

Today’s tip deals with a feature of .NET: Partial classes. 

Is see partial classes abused from time to time. If you are not aware, .NET allows us to split a class definition across multiple source files. We decorate each of the class fragment definitions with the ‘partial’ keyword. At build time, the compiler takes the various partials and fuses them back into a single class. 

Why is this useful? 

Generally, this is a framework feature that is handy when we are working with autogenerated code. I’ll get into the details of that next time.

Today I would like to point out a misuse of partial classes.

For example, imagine an enormous AccountController class split across five files:

          AccountController.cs

          AdminAccountController.cs

          UserAccountController.cs

          SuperAdminAccountController.cs

          OrganisationAccountController.cs

In each of these files, AccountController is defined as a partial class:

  public partial class AccountController

With about 2,000 lines per file, AccountController contains approximately 10,000 lines of code. Each of the partials is already bloated, but the whole AccountController class is enormous. Huge classes like this can be a real challenge to work with. 

Unfortunately, breaking AccountController up over multiple source code files obscures the actual size of the class. Programming is communication with other developers. We do not want to disguise problems – we want to highlight them, so everyone’s aware of them.

A developer who is aware that a class is already 10,000 lines long may avoid adding more behaviour to it. However, if a class appears to be only 2,000 lines long, they may not be quite so hesitant. 

Splitting up a huge class by breaking it up over several files is an anti-pattern. It does not shrink the size of the class – it only appears to reduce it.

A better way is to break a large class into several smaller ones. If necessary, we can use patterns like Aggregation or Composition to reassemble the functionality into a larger whole again. 

In our example, the names of the AccountController files already indicate a breakdown by responsibilities. AdminAccountController.cs is probably the place where Admin-related AccountController behaviour resides. Similarly for OrganisationAccountController.cs and the other files. 

The fix might be as simple as renaming the AccountController class fragments to align with the file names. In the AdminAccountController.cs file, we change the declaration from 

  public partial class AccountController 

to  

  public class AdminAccountController 

Notice that we have removed the partial keyword. AdminAccountController is no longer a partial class – it’s now a separate class.  

Also, breaking down a large class might not always be this simple.

So, when is it appropriate to use partial classes?

There is an excellent reason to use partial classes. We’ll discover that next time.

Today’s takeaway is to avoid using partial classes to spread large classes over several files. It does not reduce class size and complexity but merely obscures it.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply