Regions and Readability

Link. July 30, 2007. Comments [2]. Posted in: .NET | Tools

David Laribee wrote a few days ago about why he dislikes the #region construct in code. Interesting comments, and made me reflect a bit on how I use regions myself. In general, I don't agree with David that using regions is evil per-se. but I do agree they are often overused. In particular, I find the practice of forcing a specific set of regions on each and every code base to be a significant hindrance to readability.

The truth is that small classes don't usually need regions at all. However, I still find them very convenient for classes with a lot of members, even if they are short 1 or 2 liners. What I noticed, however, is that I don't have a hard and fast rule about how I apply regions. Instead I sort of vary my use of them according to the needs of the code I'm working on.

Here are some of the things I keep in mind when applying regions:

Lots of properties

If a class has a lot of properties (common, for example, in some business entities or DTOs), then I do like to wrap properties in it's own region. This is because a lot of cases properties are created once, but not so often modified after wards, and the other thing is that property declarations in C# do take up a lot of space because of the syntax used.

Automatic properties in C# will be nice, but from a syntax perspective, they don't really help as much as one would like. It was unfortunate the C# team decided to go for that syntax instead of the really nice one used by C++/CLI...

Multiple Interfaces Implemented

If a class implements multiple interfaces, each one having more than a couple of methods, I do tend to wrap each one into its own region. If it's only a single interface, or something simple like IDisposable, I don't bother with it.

Lots of Related Methods

Sometimes you have to implement a lot of simple, related methods in a class. We all wish classes had few members and were small and simple, but sometimes you have to do otherwise (this is usually forced when complying with an externally defined interface).

For example, in a lot of cases I've had to deal with there are a lot of simple GetXXX() accessor methods that need to be implemented (e.g. GetInt16(), GetInt32() and so on). Each one usually won't have more than 1 or 2 lines of code in it, but when put together, they take a sizable chunk of space, and if there are other, more significant methods in the class, I like to get the accessors out of the way so I can concentrate on the rest (the important stuff). Regions help out nicely in this case.

Related Test Methods

A case similar to the above one happens in Unit Testing classes: Sometimes you have several test methods that are closely related to one another, so I like to group them together. Here are a couple of examples:

  • I once worked in a code base that, although fairly simple, had tons of methods in a single class: a combination of type-specific Read/Write methods. For each type, I usually had to write four or five test methods to test all possible corner cases, so that meant a hole lot of methods involved. I grouped test methods by type (i.e. "Int32 tests") inside the fixture.
  • I'm currently working on an ADO.NET provider, and writing/testing my IDataReader implementation. The IDataReader class has tons of methods (of the accessor variety mentioned before), which, means lots of test methods in my test fixture. Again I use regions to group certain related tests methods together to make it easier to read and maintain.

There might be a couple of more cases I base my regions on, but I think these cover the basics. I think, in general, these rules give me a set of regions that are far more useful and that really make the code easier to read and maintain than the rigid Using/Fields/Properties/Public Methods/Private Methods stuff a lot of people use; but that's just my opinion :-).

Coincidentally, like David, I use search a lot to go around (though in my case I use '/' for searching and not Ctrl-I), and the other thing I've found is that tend to very rarely use the class/member code navigation drop downs in the Visual Studio Editor. I do use them sometimes, but usually when I'm just getting into a foreign code base I'm not familiar with.



Monday, July 30, 2007 8:48:02 AM (SA Pacific Standard Time, UTC-05:00)
These are good reasons, I'd say. I'd say in the case of "Lots a Related Methods" I often extract a role interface. In which case the grouping interface implementation heuristic comes into place. I also agree that when you've got a class with lots of role interfaces regions can help express intent.
Monday, July 30, 2007 9:15:19 AM (SA Pacific Standard Time, UTC-05:00)
@David: Absolutely agree about extracting a role interface; I do practice it a number of times, but others I'm stuck with the design the base class library came with :)

(Though, interestingly enough, the data reader case almost matches this, as most of the accessors are in IDataRecord, from which IDataReader inherits).
Comments are closed.

Syndicate

About

Tomas Restrepo is a software developer located in Colombia, South America. His interests include .NET, Connected Systems, PowerShell and lately dynamic programming languages. More...

tomasrestrepo @ twitter My Flickr photostream My saved links on delicious My Technorati Profile

email: tomas@winterdom.com
msn: tomasr@passport.com

View my profile on LinkedIn

MVP logo

Ads


Links

Categories

Statistics

Total Posts: 1032
This Year: 102
This Month: 1
This Week: 1
Comments: 801

Blogroll

Archive

Other

Copyright © 2002-2008, Tomas Restrepo.

Powered by: newtelligence dasBlog 2.1.8139.823

Sign In