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?
I usually stick with the suffix notation with camel casing. The result is that a lot of my control names are pretty unwieldy, but I think it’s the most self-commenting method of naming controls.
However, it is brittle, as you said, changing from stateTextBox to stateComboBox requires searching for every instance of the control.
Maybe naming it something like stateInput or stateInputControl (or whatever) would eliminate the confusion inherent in just calling it “state” but still allow the control type to be changed without breaking everything.
This made me remember what we once used for a school project that had like zillion controls and the requirements were changing every period.
We decided to prefix each control with one of the following:
ic for input control, oc for output control and dc for display control. Of course, this ends up to be Hungarian notation too. Tho, one can always suffix InputControl, OutputControl and DisplayControl.
I’m so glad I found this site…Keep up the good work I read a lot of blogs on a daily basis and for the most part, people lack substance but, I just wanted to make a quick comment to say GREAT blog. Thanks,
A definite great read…:)
-Bill-Bartmann
Personally I prefer to use:
– “Label” suffix for all labels
e.g. `nameLabel`
– “Field” suffix for all editable controls
e.g. `nameField` whether it be a TextBox, CheckBox, RadioButton, etc.
– “List” suffix for all list controls
e.g. `nameList` whether it be a ListBox, DropDownList, etc.
– “Grid” suffix for grid controls
e.g. `studentsGrid` for GridView, etc.
This provides enough information to differentiate between controls which have entirely different purposes and functionality (label vs. field vs. list) without specifying the exact type of the control. I can bind to many different views, each which may display data using different UI controls, and `nameLabel` / `nameField` always make sense.
No less important, Intellisense groups related controls by name (e.g. “dueDate”) rather than type (e.g. “txt” in Hungarian).