Feb 14, 2011

The Anti-Region Campaign

For the benefit of my twitter followers who know I have an ongoing issue with the abuse of #regions in the code I have to work with, let me take some time to explain why I dislike them so much.  In fact, let this be considered yet another step in my ongoing anti-#region campaign! (similar to the anti-if campaign)

This is not to say #regions aren’t useful, but that they are far too over used, and until people can consume #regions responsibly, prohibition laws should be enacted.

Got an Opinion? O‘course You Do!

Even without reading this post in full I’m sure you already have an opinion and like most people on internet time you’re likely to skim the first paragraph or two and then skip the rest, so to save you time here’s how to leave feedback:

If You Agree with Richard: If you too dislike the abuse of #regions then leave a comment on this post. If there’s enough support I might think about starting a proper anti-region campaign.

If You Think Richard is a Raving Lunatic: If you think I’m over-reacting, slightly unhinged, don’t understand your special needs and why #regions make the world around you glow, or if you count yourself as a #region lover then I would ask that you leave your comments and feedback on this post here instead.

Why Do #Regions Even Exist?

So why in the name of all things good and holy, do #regions exist in the first place?  Don’t they kill kittens?  Aren’t they pure evil?

Let’s have a look at what the MSDN documentation says, shall we?

#region lets you specify a block of code that you can expand or collapse when using the outlining feature of the Visual Studio Code Editor. In longer code files, it is convenient to be able to collapse or hide one or more regions so that you can focus on the part of the file that you are currently working on.

OK.  That seems nice on the surface, but isn’t the code I’m working on a class file?  Don’t I need to see it in context? Hmm.  Let’s have a look at the reasons I don’t like #regions shall we:

Reason 1 – It Hides Code

So, according the the spec, it’s to hide chunks of code to help us focus more on the bits we’re changing.  Do you see the problem with that?  Why would I, as a developer, want to actually see code?  Are you out of your mind!  Code is the last thing I want to see!  I want to write code, not read it!

I should be able to look at a piece of class and get an understanding of it straight away and how it fits in with the rest of the class.  #regions can prevent that from happening.

How can I actually tell what this code is doing? And apologies for the Hungarian notation VB code – I hope it doesn’t burn your eyes too badly!

image

I know there’s something going on in there (the line numbers give me a hint), but can I know at first glance what it is? No chance!  This is a bad thing.

P.S. One valid reason to allow #regions to exist is designer/code generated code.  However the availability of partial classes since Visual Studio 2005 means that a we’ve been able to pull all that designer generated crap out and keep it in a separate file for a long time now.  There’s no need to have that junk cluttering up my own hand crafted junk! #regions are redundant in this case.

Reason 2 – It Hides What You Think Might Be Code

I just love seeing this sort of thing:

image

There’s gotta be something in that code there right?  Something important!

So let’s open the region and have a look?

image

Say what!? There’s nothing useful there at all?! It’s just commented out code?

So the #region is “helping” us by hiding commented out code!  Surely I don’t need a region to help hide that from me, do I?  NO! Just delete the code! Don’t comment it out and wrap it in a #region!  What a great way to waste my time!

Reason 3 – It Hides Nothing At All

I don’t know wether to blame horrible coding standard that mandate the presence of specially names regions for segment class files or not but I’m sure you’ve never seen this little gem:

image

Only to open the #region to see what’s inside and realise there’s nothing there!

image

It’s like being given an empty box for your birthday.  All nicely wrapped up and making you wonder what special surprise is hiding inside only to open it and find that your kid brother has been playing a horrible, cruel joke on you.

What’s even better is when you see a class with all the mandatory regions in it (like the code we saw in Reason 1) and yet when you open all the regions up, there’s just a single static method in there and the rest is blank. Or even better, the whole class is empty!

Regions like this fail completely in their mission to help you focus on just the code you need to see, and instead add only noise and confusion to the understanding-what-the-class-does process, and make you doubt any other #regions you see elsewhere in the codebase.

Reason 4 – It Hides Just One Thing

What about this #region:

image

There’s going to be some really complex code in there, right?  Why else would I have a region there, especially since regions are meant to hide code that might distract me!

Open it up and what do I see?

image

Oh wow! Just as well we used a region to hide a single property!

Again, we’ve added noise to our code base for no reason.

Reason 5 – It Hides Butt-Ugly Code

So what about this situation?  You’re looking through a code base and see the method from hell and it’s associated demonic friends.  We don’t want to see that code do we?  No way! We want to hide that complexity, so let’s wrap it up in a region! Great thinking!

This is what we are really doing with our code: We’re sweeping all that ugly under the carpet.

As a general principle, classes should have a single responsibility and methods should be 20 lines of code or less so they stay readable.  If methods are longer than that then you’re likely working at multiple levels of abstraction in the one method or trying to do too much, and you should consider refactoring your code to improve it’s design and readability.

It’s better to keep the ugly visible so that you can deal with it.  Hiding bad code behind regions only serves to make bad code acceptable and it discourages efforts for improving it.

Reason 6 – It Hides Copy/Paste Efforts

The DRY principle means logic should exist in one place and one place only, not be repeated all over the place, because a change to the logic means finding all the spots that logic exists and fixing them all.  It’s much easier to make a fix once than it is to fix it in multiple places.

If I have a code base covered in regions I can’t tell if one section of code is similar to any other code I’ve seen before, because in all likelihood I’ve not seen it!  It’s probably been hidden away behind #region statements that mask all of the complexity and character of the code, instead making it a big block of beige.

Here’s what code looks like when #regions have been liberally applied to it:

It all looks the same.  And you’re not sure if it’s laughing at you or about to turn on you!

What About Grouping Your Code?

Let’s say you think #regions are great because they allow you to group your code and hide all those messy internal field and property declarations.  If you’ve only got a handful of them, do you really need the #region?  Probably not.  There’s not much to hide.

If you’ve got hundreds of the suckers do you need a #region?  Maybe – though at that point you should be considering the design of your system.  Do you really need a class with that many properties or fields?  Can you alter the design to improve things? Is your class doing too much?  That’s a judgment call you’ll have to make.

My gripe is with #regions is not with the directive in and of itself, but with it’s abuse.  If a #region is being used as I’ve outlined in the reasons above, then it’s time to stop, think about your code and why you’re using a #region and to then do yourself a favour.  Remove the #region and start writing better code instead.

That will be all.

30 comments:

  1. Regions are a signal that your code is poorly structured and that you're trying to cope with IDE tricks. Code readability is best improved by proper structure.

    If you group elements by type (fields, properties etc)you are ignoring that they're interrelated and thinking too much about the implementation concerns and not the actual purpose of your type.

    ReplyDelete
  2. If you have enough code in a file to warrant a region the solution is to extract the code into smaller, more understandable bits (e.g. extract class refactoring).

    I agree with you that region misuse it bad, but disagree that regions aren't evil and can be used correctly. The only winning move with regions is not to play. :P

    Regards,
    A fellow raving lunatic

    ReplyDelete
  3. Regions are great for identifying junior developers who are otherwise referred to as senior.

    ReplyDelete
  4. I think the best use of regions I've seen (and use) is for wrapping author comments/OSS licence(s) at the start of a file.

    ReplyDelete
  5. That kind of info should not be in the code. Licence file at the project base, author comments in source control. Otherwise it's just noise as is demonstrated by the need for a region to hide it.

    Obviously some places have policies that require it. Those policies are wrong.

    ReplyDelete
  6. So if this gets off the ground do we partition JetBrains to add "remove regions" as a code cleanup option in ReSharper?

    ReplyDelete
  7. I agree with those much smarter commenters in the past, but will give my point anyway.

    Regions aren't bad. The way people use regions is bad.

    On one hand we advocate not mollycoddling everyone with the framework, we want more power, we don't want abstractions that prevent us from doing useful things, sealed classes, and only the Microsoft way.

    On the other hand we can't handle our own code management because we obfuscate and hide blocks of code, reducing their meaning and importance?

    You said it yourself, "This is not to say #regions aren’t useful, but that they are far too over used" - regions are useful, so let's not eliminate them, but train users to use them more responsibly.

    Your point 4 is kind of hilarious given the user can use Visual Studio to change the [-] beside the code itself to reduce the code to the signature itself, and the use of regions is redundant, given you're not saving yourself space, but you're hiding more information that would show the importance of the code, reduced.

    As others have said, it's a sign of something that should probably be refactored to smaller, more managable classes and/or to reusable code.

    Regions aren't bad, developers are bad.

    ReplyDelete
  8. "Guns don't kill people. Bullets kill people."?

    ReplyDelete
  9. @Colin, agree completely. I don't use them for personal stuff. The main point I was trying to make is that the best use I've seen is for file content that is not code, which according to MSDN is not what they're for.

    ReplyDelete
  10. I think it's a bit like the "guns don't kill people, people kill people" argument (bear with me) - some of the reasons you give such as hiding single implementations or ugly code are faults with either the code itself or the way the region feature is being used. It's not that the region syntax itself is evil.

    At the risk of being outspoken - and to be clear, I'm not a region proponent - there is some upside to the use of regions in that it *can* illustrates thought has gone into the logical order or grouping of code. Sure, single responsibility and separation of concerns and all that, I'm just saying I often see it approached with a degree of structure, just not the type we'd ideally like.

    Another mitigation to the region scenario is that for folks running ReSharper, at least the contents are exposed via the File Explorer window. Sure, not the whole code but you get a good idea of what's going on in a single glance which would otherwise hidden in the collapsed region.

    As for collapsing bucket loads of code, well of course that's available in the IDE anyway via the little plus icon (albeit it not across multiple structures), so the "hiding one thing" use is really pretty redundant.

    Bottom line; I'm not in favour of regions, but I also don't think they're the devil's spawn! SOLID and DRY and all the good stuff will lead people away from regions naturally, just go easy on the practitioners in the interim :)

    ReplyDelete
  11. Agree. I would add one more exception to the rule which is mock classes in tests where a mocking framework can't be used.

    ReplyDelete
  12. #region Indifferent about regions

    All of your reasons are due to stuff being hidden...

    Ctrl+M,L == 'The magic cure for region pain'

    #endregion

    ReplyDelete
  13. @Mark,

    Ctrl+M,L doesn't help change the fact there was so much code in the file the dev felt it necessary to use #regions. ;) :P

    ReplyDelete
  14. Recently I've used code regions to group together and sweep under the carpet a bunch of deprecated methods in a file. I don't want people using these methods and have attributed them with ObsoleteAttribute and so to clean up my view of the code until the next release when I can delete said methods I've wrapped them up in a code region at the bottom of the file. I reckon that's a pretty reasonable use of region.

    ReplyDelete
  15. Ceterum censeo regionem esse delendam.

    If you *really* feel you need to hide some code (extremely long declarative stuff, f.ex), put it in another partial of the same class.

    ReplyDelete
  16. Regions are mostly very annoying. Quite often coders put things in them that don't relate to the region.

    regions around Interface implementations would be the only time I would use them and that is because VS creates them.

    ReplyDelete
  17. I think all of your arguments are based on bad programmer practices, not usage of region statements.

    Region statements produced with static analysis (such as auto generated by Resharper) allow you to group your code into a very convention standard layout in your file.

    So I am strongly in favor of using a tool like Resharper to enforce code layout style and to group similar members, fields, ctors into respective regions. This is the pattern I have implemented for my shop.

    ReplyDelete
  18. All of those issues can be solved easily with this extension: http://teamsearchapp.com/region-tool

    It auto expands the regions and makes the #region/#end region lines less noticeable.

    ReplyDelete
  19. And there I was thinking I was the only person intolerant enough, thank you all :-)

    As I type write now, I'm looking at a codebase in the other monitor that has some of the worse uses of region I've ever seen. #regions hiding copy/paste code instead of refactoring to methods, #regions for each interface, properties #regions, public #regions, private #regions, constructor #regions (mainly empty), they are all there. (Oh and two partial class definitions in the same file, but I digress).

    Now I could live with them except I have a habit of using Ctrl-M,O Collpase to defintions, and everytime I do that my regions collapse again. For me this is where I think that regions are broken, that there is no good use for them at all...

    ReplyDelete
  20. I can only agree with any other reason from this list you have provided here in this post of yours. Everything is clear and logical to me. Thank you for sharing your opinion on this, that was very nice to read this post.
    Evan Hammond, fan of internet radio

    ReplyDelete
  21. Hmm, I disagree, I like regions in that they 'clean' up the class. I agree with your statements that the regions described in your article are bad, but if we were to start removing things from languages because they were misused we wouldnt have many things left to program with.

    ReplyDelete
  22. Not sure why Toggle Outlining is so hard to click to expand all regions.

    So your running an anti-region campaign for your own personal gain because you find it inconvenient ?

    Instead of anti-region how about, "pro-help with regions campaign" =)

    This would be the same as anti do while , anti for, anti thread.Sleep.

    All used incorrectly can cause issues!

    ReplyDelete
  23. I know, let's start an Anti-Comment Campaign:

    Comments are EVIL because they can give you a false impression of the code they decorate. They let people write ugly, unreadable code and think they can get away with it because they put in some comments to explain what is happening.

    Without comments, people would be forced to write better code. No more letting lazy programmers get away with using comments instead of writing good code!

    And once we do away with Regions and Comments, the next campaign will be to do away with all of those developer tools like code completion and all that rubbish. If you're going to be a programmer you shouldn't rely on crutches like that, right? Learn your language! Stop being lazy!

    Of course the ultimate goal is to have everyone hand-write their code in Notepad. By this time we'll have programmers who are so good that they won't need to debug, so no debuggers either. And to make sure there are no silly mistakes, they'll have to write in pure ASM until they learn how to translate to machine code in their heads. Until they can write an entire application in machine code, in one sitting, without reference to any help files, then we won't accept them as TRUE programmers!!!

    Or - and this is just an off-the-wall idea, you understand - we can stop bitching about irrelevant things like regions and focus on just being developers.

    And yes, this is a totally irrelevant complaint. If you don't like regions, don't use them. In fact if you go to your editor options and turn off outlining then you'll never have to worry about hidden code ever again.

    ReplyDelete
  24. @Emonk That's one of the better rants I've seen! Thanks! :-)

    ReplyDelete
  25. What a waste of time this is. There are so many more things that are being abused in code that would be so much deserving than #regions that I cannot help but think this is just some elaborate form of trolling.

    ReplyDelete
  26. It is good to see a better thought out rant, even if it is just the nearly 3 year old "go here" link for someone who doesn't want to explain their hatred of #regions. Even so, this isn't helping. Without regions, people would just find other ways to isolate their complex code.

    If you prefer seeing all the code at once - expand all regions. CTRL+M, CTRL+L, and you can even add a button if you're button-oriented.

    Legitimately, I do not need to see properties while I am working on a function any more than I need to see the auto-generated partial class. I don't need to see all three overloaded constructors while writing a function that appropriately doesn't care which constructor you used. It lets me collapse the things that aren't relevant to the task at hand and expand only those that are.

    Having a clean workspace makes it easier to focus on the problem at hand and not get distracted by the rest. Even for the things you are worried about being hidden, there is a time for "Oh, Bob put a functioning, but complex mess here, we need to fix it." thoughts, and it isn't while I'm writing my new function. The sort of awareness you talk about is appropriate for a code review, not for every time you open the code.

    ReplyDelete
  27. If all the above are such pure evils, I'd expect Resharper to have an integrated warning like an "Empty region" being highlighted. I am sure if it was so, you'd configure the inspection to treat this as a compile error.

    I am ranting a bit because the effort of expanding a region is the same for expanding a folded block of code (Visual Studio supports code folding for other types of code blocks for some time). So, if someone is LAZY enough never to expand a region, s/he would not care to expand a folded block of code and will possibly experience almost the same inconveniences you mentioned (and which are true of course)

    Indeed, all cases where code folding duplicates the function of regions, the latter are redundant, and should be removed when spotted, not complained about.

    What I want to say is that regions are sometimes redundant, but the boilerplate they introduce is insignificant. I am wondering how such an insignificant thing can spawn an entire campaign against it? Don't you people have work to do? Keeping with coding best practices will eliminate the majority of the issues introduced in this post. Blindly following this campaign (I hate this world already) will not make us better developers, will not teach us the best practices we were lacking when we put that region there, and will actually move the focus on improving away. For some folks who take this campaign seriously, removing all the regions in their projects may even be a form of major refactoring. Jesus, why would someone create such a distractive campaign? It is like making an elephant out of a fly thing. People may need to learn how to code better, why should we focus their attention on such insignificant feature, rather than show them how to really fix the code?

    ReplyDelete
  28. 1. It is fine to not want to use regions.
    2. Please do not support any "movement" to remove them for those of us who use them.
    3. When I use regions it is never to hide code, but many 3rd party tools (e.g. code maid) can make use of regions to let you keep related functions grouped together.
    4. When I do hide code, it is never with regions, when I have to use conditional compilation I appreciate the IDE's natural ability to hide the code that isn't going to get compiled.

    The point is all of your arguments are against code-hiding, which Visual Studio does even without regions. If you want to get rid of code-hiding then tell Microsoft to get rid of its code folding features.

    ReplyDelete
  29. I like this post. I've seen too many examples of region misuse. In my book Regions=Bad. Show me the friggin code. If the code is a mess... then clean it up. If the file is getting too big, then maybe it's time to refactor.

    ReplyDelete