Digging into an existing software project of significant size can be confusing and, without a clear structure and organization of the code and the documentation, can result in a lot of wasted time. Structure guides and clarifies, and self-documents. Well, ideally. You can have an excess of structure – which can comprise an intellectual road-block. Later on that.
Here are some standards for structuring and formatting our code. This has evolved over many years of involvement in large projects involving C, C++, Java, and C# – especially in the aerospace and defense industries. For the examples I’m going to assume the programming-language is C#, and the GUI toolkit is WPF, SilverLight, or ASP.NET. These standards also apply (with the obvious adaptation) to Winforms, C++ or Java. I’m also going to assume the IDE is Microsoft’s Visual Studio 2012 (VS).
There is one all-important standard for your test code: At the top of your code file, put a TEST REQUIREMENTS comment that clearly states everything that test needs in order to run. Put all of the requirements that must be met apart from that of the code itself, the platform that it must be on, the preparation and cleanup that need to happen, everything. Do this for every file that contains test-code, and make absolutely certain that your team-members read this and concur. If you add a unit-test to this file, update the TEST REQUIREMENTS to make sure is is current and correct. This will save you at scrunch-time!
By “automated test” I am referring here to unit-tests, subsystem-tests, or system tests — that can be invoked to run without human interaction. This requirement really is for what we commonly refer to as subsystem-tests — those that access other things such as web services, the file-system, or a database. The naming convention varies, but the vital consideration is that, if you are using Test-Driven-Development (TDD) in your department, then these have to run and they need to pass. Machines go down, infrastructure changes, databases come and go — and you do not want to find yourself holding up everyone else on your team, late on Friday when everyone wants to go home, because the tests are suddenly failing. That TEST REQUIREMENTS section is vital.
Class Instance Variables (ivars):
For private variables, use the single underscore (“_”) prefix. E.g..
Caveat: for protected or public variables, if you want to mark your assembly as CLR-complaint you will need to NOT use the leading underscore, so in that case you could use the leading “m_” instead. If you use this just for protected variables, you now have two distinct naming styles, which may or may not be advantageous.
Previously in C++, in Microsoft, etc. some were using “m_” as the prefix, the “m” representing a “member” variable. Which would seem to make some sense. The advantage of using just the underscore is that nothing else begins with this. That lonely leading underscore is a really obvious flag. And this shaves off an extra character. In VS as soon as you type an object-name, and then a period, up pops a sorted list of everything this class has. Type a character, and the list scrolls down to the entries that start with that character.
This is wonderful for efficient coding, but we need to make effective use of it. If you type the letter “m”, that list now scrolls to those members that begin with m. This set is not as exclusive as the set of members that begin with the underscore. Just type the underscore character, and now you’re looking at only the ivars. That is, only your own ivars. Yeah baby – dats what I’m talkin about.
Uhm.. except, if this is a WPF Window or UserControl, the individual controls that are available to you as ivars will not come up, unless you also named those with beginning underscores. In the interest of keeping those separate, I never do. We have a separate standard for those.
Static class variables:
prefix these with an additional “s”, for “static”.
Caveat: with this I have some ambivalence and have seen (and used) the practice of simply using an underscore, and – honestly, I haven’t seen it cause any confusion. The thinking is, we don’t want to overload with syntactic sugar, but you may want to flag these as static in a visually obvious way. In your code reviews, you may want the fact that they’re static to stand out. We catch errors that way. On the other hand, the standard of simply beginning all fields with the underscore – is compelling. Thus, this is a choice which is quite fact-specific. Consider what works best for your situation, make a choice, and then stick to it.
I have in the past preferred to use a limited, common set of prefixes to denote the datatype – where that helps with clarity. Yes, it was a holder from my C++ days, and it serves a similar purpose. And yes — that usefulness is largely gone now, with Intellisense and type safety.
Perhaps it was more just habit. And when intermixing C++ and C#, it did seem nice to have similar formatting. On the other hand, my last contract project strictly avoided this. They (we) used simple camel-cased identifiers with no regard for datatype such as fileName, inputText, and count. Okay. Well, I got used to that. So we have two distinct styles, either of which works fine. After working with both, I have found myself drifting over to not using a strict hungarian-notation style, but with certain code standards yet where it does make sense to preserve clarity.
Yes, Intellisense does reveal the type, but when you’re glancing at a complete program listing, this can help guide your eyes to recognize what you’re seeing.
One of the most common sources of confusion is to use a common name for a variable, when it’s actually something more involved – and you can’t immediately tell by it’s usage. For example, _Identifier; Is that a number, a string, or some other type? Or outputFile. Is that a stream, or what? If it is a string denoting the pathname of the file, I would name it outputFilePathname, for example.
So. Here is a table of the basic type prefixes to use, IF you happen to be using type prefixes:
|Double or Floating-point:||f||_fElapsedTime|
|DateTime:||dt, or when||_whenEntered|
I don’t suggest using these religiously. Just where it makes sense for clarity. Yes, with auto-typecasting in C# and Intellisense, it’s not as important as before. But I think that, if you’re going to use this style, this can clarify your code even though it’s not as necessary as in days gone by. When you’re scanning a page of code, you want to be able to focus on the algorithms, on the code correctness, not on trying to pick out what each little identifier is. It can help.
For C# class properties, if it’s a boolean property: word it such that it begins with “Is”, or an equivalent such as “Has”, e.g. “IsValid”, “IsUsingAFixedDelta”, “HasAccess”. Other properties should be noun phrases or adjectives, not verbs. These are data, right? But the important thing is to word is as a property, not as an action or something else that is misleading. If it has to do some significant work or access a subsystem to return a value, then change it to a function.
On the other hand, methods do things. So give these verb-phrase names, if that is their main purpose, or else phrase it as an answer to a question if you’re using it like a function. e.g.,
public void DoTheAction()
public int NumberOfActionsIn(TaskType task)
For GUI controls like a TextBox, it’s better to identify the ivars with a short, standard prefix (“txtLastName”) rather than a suffix (“LastNameTextBox”). Why? Because the range of possible names (“LastName”, for example) is a wide-open universe. No matter how familiar you may think you are with this project, the object you seek could start with almost any letter! The best way to exploit your Intellisense is to have the initial characters narrow it down to a manageable list.
You often wind up having to scroll through a huge list of possible members, and the .NET classes have lots!
But you usually know whether you’re looking for a Label, or a TextBox, or a Button. It is far faster to simply type (again, in VS): “lbl”, to bring up all the Labels available in this class.
“txt” or “ckbx” may seem a bit cryptic at first, but you’ll quickly get used to them. Why? Because they are fixed. We’ve used these for years. They will become second nature to you.
Yes, the “TextBox” suffix says it loudly and clearly. But perhaps a bit too loudly? Once you get into your code, you know this darn thing is a TextBox. What you’re probably trying to distinguish amongst your ivars, is the semantic content: eg, “txtPassword”, “txtLastName”. You will get quite used to associating that little prefix “txt” with a TextBox. Second nature. Really!
txtName is shorter than NameTextBox, and that prefix flags loudly enough that we’re talking about a TextBox. Because you’re being consistent throughtout your code, right? Promulgate this policy across your development team, and be consistent.
The standard prefixes for GUI controls:
|GUI Control||Standard Prefix||Example|
|Masked-edit or specialized textbox||txtm||txtmPhoneNumber|
|GroupBox||groupbox, or gbx||gbxName|
Note that although these are all going to be instance-variables of your class or webpage, we don’t use the underscore (“_”) prefix for these. This helps distinquish them from your own instance-variables that your GUI-designer tool didn’t automatically add. Since these all begin with a standard and relatively small set of prefixes, you can find them easily enough with VS’s Intellisense.
Note too that the masked-edit textbox, the RichTextBox, and other variations of a textbox – all begin with “txt”. This helps you to narrow the list down quickly. It’s not always obvious what kind of textbox you’re dealing with. There are lots of custom controls and 3rd-party toolkits. But you generally do know that it’s some kind of a textbox. So just by typing in “txt” — you instantly see all possible candidates. This common prefixing is important!
CheckBox and ComboBox merit careful attention to avoid confusing them. If we used “cbx” for ComboBox, that would be too easy to confuse with “ckbx”. Too close. That extra “k” helps distinquish it.
Name your Buttons with something that describes the action they perform. That is, a verb. Please! What the heck does a btnAnalysis do? btnAnalyze is much clearer. And btnShowAnalysisResults. But not btnResults – this doesn’t make clear whether it generates results, displays it, saves it.. what?
Name your Labels to match the controls they’re associated with, and if they are paired with a TextBox – please, give them the same name. That lblPartName goes with txtPartName is as obvious as you can get.
As a further aid to clarity, I often try to name the label, the textbox, the view-model property, and the domain-model property all the same. For example: lblAge, txtmAge, Age. When you see these using totally distinct terms, for no reason other than that different people authored them — it’s time for some refactoring. Hopefully, your team is having regular get-togethers and devoting a smidgeon of that time to such matters.
I consider this to be one aspect of self-documentation.
The expandable regions within VS are a wonderful blessing for you when clarifying your code structure.
They are simple: they group your stuff into named blocks. Check it..
Note this comment format, leading with the triple-slash. VS recognizes this and feeds it into Intellisense, which in turn makes your comment into a tooltip for all your fellow coders to use. It’s awesome!
I strongly suggest you use this format to comment your classes (
class, please!), your class members, and to group all the members into functional groups.
It’s a characteristic of the human mind that we more readily comprehend something that has seven parts or less. In other words, if you have 99 methods, group them into blocks, and group those blocks into larger blocks, until you have no more than 7 top-level blocks. Now, your new programmer can glance at your class, and see only a few regions and know (hopefully) right where to go.
Let’s refine this a bit further..
One way to block them is by syntactic category. In other words, as in the above example – “properties”, “fields”, “methods”, etc. But this really doesn’t give you much. It’s an easy default way of organizing, but it’s usefulness is limited for any but the simplest classes. Another way is to group them into “public interface”, and “internal implementation”. Now the user can go straight to the right region to use your class from without, and ignore the internal implementation details until he needs that.
Caveat: for Windows and UserControls, this doesn’t necessarily contribute much. A Window may have all of it’s functionality defined in terms of private methods, with only it’s constructor being public. Your own usage of it may rely upon sub-classing and overriding it’s protected methods. That doesn’t lend itself to public/private organization. For other classes I do think that a public/private top-level organization is king.
If you have only one method within a category, eliminate that category! (unless it does add valuable additional information). Otherwise you’re simply forcing your user to perform an extra click to expand that region to see what’s inside. The principle is to group into categories in such a way that helps to mentally grasp what all these parts do, yet provide the easiest, fastest possible path for your user (by “user” I mean other developer) to drill down to see what the code actually is.
Another, very useful strategy for breaking your class-members up by region, is by functionality. For example:
This is usually more useful for larger classes, as a starting-point. I believe the superior strategy is to break up your regions by major function, not by syntactic category. This especially applies for very large, very complex systems.
Note that I use all lower-case for the region names (except for acronyms). This is a useful way to visually separate the regions that are there just to group things together, from the regions that surround individual methods – where the region-name is the same as the method-name.
It is also very important to use correct grammar in your comments, and to not assume domain-level familiarity on the part of your readers. Spell it out! Say it clearly, as though you’re addressing the line of customers at your local Post Office. This way, when you’re done commenting, you are nearly done documenting.
I appreciate your feedback, criticisms and suggestions for coding standardization. This is important for software engineering and we want our design to be the best possible, right?