Wednesday, May 14, 2008

Misuse of Regions in Code

I am sure a lot of you that program in .NET using Visual Studio have become familiar with the concept of "regions" in your code. A "region" is a way to separate a block of code so that it can be collapsed and expanded as necessary. This can be good when you want to "hide" code that isn't updated often as to not confuse, or annoy any developers that may be working their way through your code.

I'm sure many of you are already familiar with "regions" but here is the obligatory example anyway:


#region
Code I want to Group Together
// Some truly amazing code here
#endregion

Sounds good right? Well, there is a seedy underbelly to this "freedom" in coding. It is nice to be able to "partition" your code out to make it easy to "collapse" code away that you are not interested in to make it easier to navigate your code but when you think about it, if you have so much code in one code file that warrants adding "regions" to "hide" certain code as to get it out of the way doesn't that set off a bell in you that maybe your code file is way too large? Could it be that "regions" are now providing you with an excuse to fall into the old "spaghetti code" mentality?

For me, it is quite annoying when I get into a code file only to find that there it consists of several "regions". Sure it looks neat and tidy but when you open such a file what is your first instinct? You may know exactly what "region" to open and thus you dive directly into that one and continue with your work. However, you may not be too familiar with this code file so you may find yourself hitting the old +"Ctrl+M,L" shortcut to expand everything. But as soon as you do that you find that this innocent looking code file is now thousands and thousands of lines of code including multiple nested "regions" to muddy it up all the more.

So what can you do to make such tasks easier? What can you do to separate related code out to make it easy to find and easy to work with? Two words for your "Partial Classes". With .NET 2.0 and above you have the ability to separate the "guts" of a code file into multiple code files simply by adding the word "partial" to the class definition.

Here is an example:


public partial class
Customer : IPerson

It is important to note that "Partial Class" file can have any File Name but most people use the format: MainFileName.PartialClassName.cs just to make sure the files are grouped together and make sense to other developers.

I know, I know, many of you are saying "big deal, this has been around a long time now". Yes, this capability has been around since 2005 but most people out there only ever use "Partial Classes" when dealing with ASPX and ASCX Files and never consider using this great idea with their regular Class Files.

Usually when you think about an Object you may find yourself breaking out multiple Class Files that all relate to a specific task surrounding your object. This makes perfect sense and so finding several related Class Files that break out functionality is "normal", however, there are times where a single Class File grows quite large and you don't wish to separate its "guts" into different sub-objects but you also want it to be easier to maintain and easier to share in a Team Environment. This is where "Partial Classes" come into play.

If you separate related code in a Class using "regions", that will make it easy to see what code is related to each other (in a sense) but it still goes against Team Coding practices. If Developer A wants to edit Functionality X of this Object, he has to check out the same file that Developer B already is editing. Modern "merge" features are better now than they used to be but this can be a pain. However, if instead you separate such related functionality into "Partial Classes", Developer A can check out just the "Partial Class" he/she needs and thus not disturb the work of Developer B. Oh sure there will be instances where multiple developers will need multiple "Partial Class" files checked out but having these all separated out will ultimately prove to make development and maintenance easier.

Don't get me wrong, I am not suggesting including all functionality into one big Object via "Partial Classes". If you have an Object, lets call it "Customer" and this Object has "Accounts", you would still want to create an "Account" or "CustomerAccount" Object. What I am suggesting is instead of using multiple nested "regions" to partition your code, why not use separate "partial" class files to not only make it easier to understand but easier to maintain and easier to share development work in a Team Environment.

To give an example of how "regions" can be bad, just yesterday I found myself editing a monolithic code file that was not only filled with multiple nested "regions" but it also had an extreme number of unused Compiler Directive #if/else conditions. In this case I simply deleted all the unused Compiler Directive conditions which meant deleting 2,500+ lines of code. This still left an excessive number of nested "regions". Maybe someday when I am feeling brave enough and have the time I will pull those out and create "Partial Classes" for each distinct area of code.

Removing the "dead" code made this Class File easier to navigate, just think how much easier it would be to maintain with all the "regions" pulled out into their own "Partial Class" files.

1 comment:

Tomasz said...

I am deleting region markings when I see them around nothing (really :-)), or around a couple of lines of code. The code for the whole file fits one screen, but still is grouped into a number of regions. The regions are just noise in that case.

I like your idea of splitting one big class into multiple files using partial classes and a naming convention. I will try to use it next time I have a chance.

Thanks Kevin.