UI Control Naming Conventions

Microsoft was kind enough to publish a set of design guidelines for developing class libraries, and I use the book Framework Design Guidelines that is based on them daily. This has settled many disputes over the conventions our team should follow, and it’s the basis of many suggestions I make on the XVBT forums. The guidelines help lay out the practices that the .NET Framework team tries to adhere to when designing types. If everyone adheres to the guidelines, then the entirety of the .NET ecosystem will be consistent and usability will increase.

The guidelines have an odd position in the documentation. I find that most of MSDN and Microsoft’s other efforts are focused on helping the application developer. Contrary to this position, the design guidelines are focused on developers of class libraries that will be used by other developers. This is what I do, so it’s great for my demographic to get some love. However, the lack of focus on application development means there’s some important guidelines that aren’t there.

Chapter 3 of the books involves naming guidelines; you can follow along sans commentary online. The chapter discusses capitalization conventions and how to name every aspect of your code from variables to interfaces to DLLs. One omission that would be useful for application developers is guidelines for naming controls in applications.  I’ve experimented with 3 approaches, and each has its disadvantages.

1. Hungarian Notation

If this is established as the guideline, Hungarian notation is used for each control. That is, a text box for name input becomes txtName and a list view for displaying songs becomes lvSongs. Optionally, a leading underscore might be used, but I tend away from it when using this convention.

One benefit of this notation is familiarity. VB6 developers in particular favor this approach because it follows the generally agreed-upon conventions used in that language.  Another benefit is an increase in understandability.  When you see txtName, it is clear that this is a text box that represents a name.

One drawback is the naming guidelines use a strong DO NOT guideline to condemn Hungarian notation.  Nothing else in .NET uses Hungarian notation. This makes applications that follow the notation seem like they stick out a little. Another drawback is the notations aren’t really standardized. Most people agree on txt for TextBox and lv for ListView because these controls have been around forever, but newer controls like TableLayoutPanel and Grid don’t have agreed-upon prefixes. Also, how do you decide what to use for custom controls, UserControls, and third-party controls? One more drawback is this notation makes code brittle to change. Maybe your prototype starts with a TextBox but later you switch it to a NumericUpDown. This means you not only have to change the control and any logic that worked with it, but you also have to hunt down all references to the variable and rename it. (I admit I’m a relative newbie to Presentation Model patterns and it could be that this is less of a concern in those since the form would likely expose the control as a typed property, but I think it’s still applicable.)

To me, the drawbacks seem to outweigh the benefits. However, this is the convention I learned when I started in VB .NET many years ago, so I find it most comfortable and no matter how many arguments against it I hear, it’s the one I use.

2. Suffixes

When following this guideline, you pick a descriptive name and suffix it with the type of control. Use of camelCase or PascalCase is disputed, but generally I see PascalCase used more prominently with this technique. Using the examples from above, we’d use NameTextBox and SongsListView.

This has practically the same benefits and drawbacks as Hungarian Notation. You’re still identifying the type of control alongside the purpose, and it’s still clear from the variable name what kind of control is at work. This is technically a form of Hungarian notation, so still falls afoul of the DO NOT guideline. The problem with standardized prefixes is eliminated: since you use the full type name there’s no need for agreement. This technique is still brittle if you change controls.

Personally, I find that this convention clashes with how I think about the UI and makes it harder for me to find the variable, but this is probably because I’ve used Hungarian notation for years. I’ve tried following this guideline, but I find that more often than not I forget if I chose ItemCount or NumberOfItems as the prefix, and knowing the suffix doesn’t help me find it. Perhaps my naming discipline is poor, but it just doesn’t work for me.

3. Plain Old Variable Names

When following this guideline, you pick a descriptive name for the control and use that. There’s dispute over casing and usage of a leading underscore, but I find that two camps are the most prominent: PascalCase and _camelCase. Using our example controls, we would use Name and Songs or _name and _songs.

There are a few benefits to this approach.  One benefit is you aren’t using Hungarian notation so you aren’t falling afoul of any DO NOT guidelines. Another benefit is the code is no longer brittle if you change the control type.

Despite the benefits, there are many drawbacks to this approach no matter what casing convention is followed. If we’re writing a custom control or a custom UserControl that needs a text box for a name, then Name is already taken by Control.Name and we’ll have to pick a different name like PersonName. This can lead to accidental use of Name when you meant PersonName, and since you aren’t using the first name that came to mind you’re going to spend a lot of time trying to remember what your 2nd choice was. In addition, this casing convention is used for properties and constants, so if you have many of those your controls will be buried among them in Intellisense. This is why many people use the _camelCase convention, but since this is a very common convention for private fields it’s not much better.  Is _songs the control that represents the songs or a collection of songs? If you’ve got 20 properties with backing fields and 5 controls on the form, you have to wade through 25 entries if you can’t quite remember the correct name. _camelCase also looks particularly heinous when used as the x:Name attribute in XAML.

I find I am always dissatisfied when I use this convention.  If I use PascalCase then I almost always get the controls mixed up with constants. Even more often, the control name clashes with a property that I want to have and I end up having to pick a worse name for the control.  Then, I can’t remember the name I picked.  If I use _camelCase then the controls are buried among property backing fields, and name clashes still happen.  If _songs is the control that represents a list of songs and I want a Songs property, what do I do for the backing field? (There’s a few answers that involve generating the property value in different places, but most of them wouldn’t occur to a novice.) No matter how I try to follow this convention, I don’t like it.

I’m sure there’s other approaches I haven’t thought of, but these are the three I’ve tried. All of them have drawbacks that seem to outweigh the benefits, but I side with Hungarian notation out of familiarity. If there were guidelines to follow, I’d settle on the method they suggest, but there are none so I have a hard time deciding if I’m right.  What do *you* do?

Documenting SyntaxHighlighter so they don’t have to

I upgraded to the new SyntaxHighlighter today in preparation for a couple of posts that hopefully I’ll make by the end of the month. (Topics: explaining and condemning default instances (VB .NET “feature”), a neat discussion of SRP that was generated from an XVBT post, and a possible series on creating design-time experiences for WPF controls.) My installation experience was less than desirable.

There is no documentation for installation on the SyntaxHighlighter wiki, or if there is documentation it’s not linked from the main page. There’s barely documentation for the features as well. There’s four or five “look what I can do” pages that demonstrate its features, but no pages that tell you how you can do these fancy things too. There’s some cool features, but the only way I can figure out how to make them work is to dive into the JS myself. Lame. For example, on the demo page there’s a demonstration of highlighting lines; what’s the syntax for this? Also, what’s the “html-script” attribute do? How am I supposed to find it.

Anyway, here’s how to install SyntaxHighlighter based on my experience:

  1. Copy the scripts, styles, and src directories to a location on your server. (Maybe src isn’t required; I included it just in case.)
  2. On the page that you want to highlight code, make sure to import brushes, import styles, and call the magic code that does the work. For example, if you want to highlight some C# code, your page header needs to include:
    <script type="text/javascript" src="scripts/shCore.js"></script>
    <script type="text/javascript" src="scripts/shBrushCSharp.js"></script>
    <link type="text/css" rel="stylesheet" href="styles/shCore.css"/>
    <link type="text/css" rel="stylesheet" href="styles/shThemeDefault.css"/>
    <script type="text/javascript">
        SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
        SyntaxHighlighter.all();
    </script>
    

    Do not load anything before shCore.js, or you will get errors.

  3. That’s all I would have needed to have an effortless install of SyntaxHighlighter; it’s a shame the documentation isn’t there. Before you get all “it’s a wiki: do it yourself” high-and-mighty on me, go try to add it yourself. You can’t. The leaf pages of the wiki are editable, but I can’t seem to find a way to edit the main page. Perhaps there’s a way to add a new page, but there’s no way to enumerate the pages on that wiki so without a link from the main page any new “Installation” page is going to be invisible. So I would, but I can’t. Hopefully, someone will eventually create an installation page so silly people like me don’t have to spend 20 minutes discovering that the order of the brushes really matters. Or maybe it’ll never happen and this page will be the only documentation for it. Who knows.

Ordering of numeric conditional tests

I’m reading Code Complete and something caught my eye in chapter 19. At first I wanted to argue with it, but the more I thought about it the more I liked it.

The idea concerns the situation where you need to test if a variable satisfies an inequality, for example, if you need to know if min < n < max. I’ve always done it like this:

if (x > min) && (x < max)
// -or-
if (x < lower) || (x > higher)

I did it this way because I liked having the comparison variable on the left and the constant on the right. McConnell suggested that the organization should look more like the inequality:

if (min < x) && (x < max)
// -or-
if (x < lower) || (higher < x)

I initially rebelled against this part of the chapter simply because it was not what I liked, but the more I think about it the more I like it. Almost every time I have to code an inequality like this I make a mistake, and I always write extra tests for these cases. I think if I start writing the conditions this way, I can increase the probability that I’ll get it right the first time.