Thursday, January 28, 2010

Code #region considered harmful

I simply hate #regions. Apparently I'm not alone.

In C#, a bit of code surrounded in #region...#endregion markers is folded shut by any decent IDE. The code becomes invisible until you ask to see it. This sounds like a good idea, but it really is not. It makes code *look* smaller, but the code is not smaller. It is more of a girdle than a diet. The code is instead better-hidden, an attribute I can hardly describe as a virtue.

There are plenty of reasons to hate long methods and long classes. The foremost is that you cannot see and grok them at a single glance. The programmer needs to read code quickly without misunderstanding it. The #region tag is one of the most sure-fire ways to make that problem considerably worse. The region worsens most of the problems long classes and long methods cause.

The #region is almost certainly an American or British policy decision. It makes things seem better while all the time making them considerably worse. Whenever we prefer 'seeming' to 'being' we have taken a wrong turn. It is like the alcoholic who hides his booze so he can seem fine while drinking heavily in secret.

Take off the #region tags and look at your code in the clear light of day. Does it seem like it doesn't belong there? Move it instead of hiding it. Does it seem like too much boilerplate? Then cut down your framework so it demands less of you. You can make your system better, instead of hiding the dirt. Really.

Name it Badly

If you cannot name something well, then please name it appallingly badly. No, this is not a joke about the iPad.

When I am stuck for a name, the problem usually not my command of English or lack of a good Thesaurus. It is that either I don't know what kind of a thing I'm applying the name to, or it is in the midst of morphing from one kind of thing into another. In such cases, neither can my pair programming partner name it. Its identity is unclear. Yes, this is about the Single Responsibility Principle again.

A class with a clear single responsibility (does it all, does it well, does it only) is easy to name. Anything with a responsibility that is not clear, not complete, or is mixed with other responsibilities is going to be hard to name. Anything that can't have a good name should have a bad name. A very bad name.

Most of the rules still apply. You want something greppable, something that isn't going to disinform, and something that is pronounceable (etc). What you don't want to do is give it a name that is plausible and professional. DataUpgradeManagerClass is appallingly bad, but someone might take it seriously for just a minute or two, and might hesitate to rename it.

Some people like to embed a WTF in the name, as in WTFNames or ListOfWTF. I guess that's okay. Nobody will look at it and think it is something official and well-named. I personally like "Thing" or "Thingy" or "Doodad". I have named tests and variables after my programming partners. I have named them with nonsense words. I have given them joke names. When you see what I've done, you know I'm stuck for a name.

The point is not to leave the object unnamed, and not spend the next 20 minutes trying to name it. Throw on a stupid temporary name until you can think of something better, like when the class has found its single responsibility or has been broken into several classes which each are singly-responsible. As long as the name sticks in your craw just a bit, you are more likely to rename it. This will help prod you to rethink the strange things so-named.

I went for a week with a test suite that had a bad name, in a file called Class1.cs. We knew it was badly named, but our tests were scattershot and begging for reorganization. When we pushed the code, the suite was well-named and was organized into test classes which were named after testing scenarios, and the methods were consistent and meaningful. We were letting the code shape itself and lead us, so we could not pretend to know where we were really going. By putting stupid names in, we were able to keep going until we knew what we were into.

You should not push the code with stupid names. This means that you might want to search your conscience or maybe your diffs prior to pushing code. Pushing code that has some appallingly bad names means that you pushed code that has ill-formed thoughts in it, and probably ill-formed classes. Have I pushed badly-named code? To my shame, yes. Both I and my partner at the time forgot. I really need to read my own diffs more often.

If you do push with a stupid name, however, be assured that your other teammates will let you know. All the good version tools have a blame or annotate function, so they'll know it was you or your partner. I'm the guy who wrote "TheWillieTest" and "DeleteMe" in the same week.

Technically, DeleteMe was an intention-revealing name which I'd put into a file temporarily to help me explore some syntactic issue and opportunities. I accidentally did leave it in, and did not review my diffs (sigh) and when Ryan (my coworker) found it he knew just what to do. He deleted it. And tweeted it. And I blushed.

Bad naming is a tool, just as good naming is a tool. Seriously consider how appallingly bad names might help you produce code without obsessing on names for coding artifacts that have unclear identities. If you use appallingly bad names, though, it might pay you to review your diffs just in case.