These conventions are designed to assist programmers in writing readable, organized, and maintainable code. They provide a standard that you can apply in your own coding or in a team for a consistency.
Developer Guidelines
Introduction
The objective of this document is to outline a set of language-level programming conventions and development guidelines to aid developers in writing high quality code using a consistent set of idioms. The patterns and practices that are discussed in this document are a result of years of education, research, and industry experience by qualified software engineers around the world. These guidelines cover how to write readable and well organized code, but should not be confused with software design, which focuses more on implementing well written solutions to a specific problem.
To use the conventions effectively there will be sections describing each idiom followed by a set of guidelines. The guidelines used are the same ones used in Framework Design Guidelines by Microsoft and are:
- DO: Do follow this guideline and don't stray from it
- DO NOT: Do not violate this guideline
- AVOID: Avoid a situation at all costs unless there is no other alternative
- CONSIDER: Consider this guideline and use it when possible, but otherwise it is not strictly necessaary
CONSIDER: This document’s conventions and guidelines are only as effective as its adoption rate by developers.
CONSIDER: It is highly recommended that you use this developer document in conjunction with the official Framework Design Guidelines, Conventions, Idioms, and Patterns for Reusable .NET libraries, and Code Complete 2, A practical handbook of software construction, both of which are high quality resources for engineering great software.
Class Layout
An application built in a CLR language can structurally be dismantled until you reach a class. A class contains fields, properties, methods, events, delegates, attributes, and other types. That will be the scope we work with, and by the end of this document you will be writing high quality classes that are easy to read and maintain, even for other developers who haven’t read or worked with your code before.
Organizing your class into a maintainable structure is equivalent to keeping your closet organized. If I keep all my shirts, pants, and socks in a single basket, I can’t find what I need without the possibility of having to go through it all. I may get lucky and find a pair of pants on top of the pile, or I might not be so lucky and have to dump the whole pile out. The opposite occurs when I keep my closet organized. If I have my pants and socks folded and put into their own bins and my shirts are on hangers, I can easily find everything I need without having to disrupt the organization of how I have my clothes placed. The same goes for your class structure. If you write every class in the same structure, each class becomes very easy to read and maintain.
The structure of your class is defined by the order and grouping of public API surface and implementation details. Fields should be defined in one place, and your methods in another. The same goes for properties, events, delegates, and nested types. By structuring your code in this manner your code serves as a sort of index that can be easily read and navigated. For optimal class layout and maintainability, use the following structure.
// Copyright information namespace CompanyName.Technology.Feature { // Using directives // Global Delegates class ClassName { // 1. Fields, Constants // 2. Constructors // 3. Events // 4. Properties // 5. Methods // 6. Nested Types } }
DO: Use this class structure consistently in all classes you write.
DO: Reserve the first part of the file for any copyright comments or important informational notices about the current source code file.
DO: Declare using directives in alphabetical order. Use the Organize Usings > Remove and Sort command in Visual Studio to easily maintain using directives.
DO: Declare fields, readonly fields, static fields, or constants at the beginning of the class definition by group, and in alphabetical order.
DO: Declare constructors in order of complexity (number of parameters), beginning with the least complex to the most complex.
DO: Declare events in alphabetical order.
DO: Declare properties in alphabetical order.
DO: Declare methods in alphabetical order. When declaring polymorphic methods, declare them in order of complexity (number of parameters), beginning with the least complex to the most complex.
DO: Declare nested types in alphabetical order.
DO: Declare only one type per file, and name the file after the type. When declaring type ClassName also rename the source code file to ClassName.cs.
DO NOT: Leave the name of a source code file as Class1.cs, Form1.cs, or any unidentifiable name.
David Anderson: Not naming a source code file actually says something about your attention to detail. It takes very little time to name a file something identifiable and useful, and you are helping other developers by doing this. The first point at which you search for source code is at the file level, and having to dig through dozens of files without meaningful names can be a nightmare for another developer, especially someone new or temporary to the project.
I just want to note briefly that as this document progresses you will build on the foundations of what you have learned from earlier sections. In later sections we will touch on topics such as documenting your code, formatting, and other more specific subjects that will bring more quality and maintainability to the code you write.
Now that I have laid out a list of do’s and do not’s for you to remember, let’s actually look at a small class as an example of what a good class might look like.
namespace DCOMEngineering.DeveloperDocument.Demo { using System; using System.Linq; public class Employee { private string email; private string name; private decimal salary; public Employee(String name) { this.name = name; } public String Email { get { return email; } set { email = value; } } public String Name { get { return name; } set { name = value; } } public Decimal Salary { get { return salary; } set { salary = value; } } } }
The first thing that should stand out is that the class follows the structure outlined in Figure 1. It begins with the enclosing namespace, using directives, class declaration, then finally fields, a constructor, and then properties. I kept the class simple enough for now, but you can see that you can easily read the class like an index. The fields come first and are in alphabetical order, then the constructor, and then the properties in alphabetical order. Finding what you need is relatively easy to do, and this becomes critical when you are working with very large classes.
Class structure and layout is a fundamental starting point to writing high quality classes, but even though the class is very simple, it is still very far away from being a high quality class. It is missing some key features that complete it, which brings us to our next section.
Naming Conventions
Be forewarned, there is extreme bias that lies in the coming text, but its bias that is correct and that’s all you need to know. Now that we have that settled; naming conventions are one of the most large and controversial discussions to have among developers, but to put it simple terms: there are far too many just plain bad conventions out there. I have seen conventions that are awkward, decent, or just completely horrid. If there is one thing that I do know from all that experience, it’s that Microsoft has it right.
Writing code is an art in of itself, and it’s pretty much identical to writing any kind of document. The analogy I like to use is that it is like writing a high quality essay. You either write a quality essay or you don’t. If you don’t, you get a D for a grade, or worse, an F. If you have read or written C++, you know just how cryptic some of the names for things are, and C++ and its vast libraries aren’t even the worst culprits out there. Unfortunately for some languages like C++ they are just dated (but don’t confuse that with deprecated) and they carry a lot of baggage, including poor naming conventions. C++ has improved and keeps improving though, but other languages, libraries and frameworks have carried that bad baggage and kept it.
This section will be similar to the previous section on documentation, because the way you name things will greatly affect how your code is both read and interpreted not just by you, but by others. In addition, when there is no documentation, all you have is code for your documentation, so it better be good, and that’s the goal. High quality code. I’m going to break naming conventions up into logical groups. We will start with namespaces, then move to classes and their implementation including fields, properties, events, methods, and member variables within methods.
Naming Namespaces
The following rules outline the guidelines for naming namespaces.
DO: Use Pascal case.
DO: Use a noun or noun phrase to name a namespace.
DO: Use a well-established company or brand name for the root namespace.
DO: Use a well-established technology name for the second level hierarchical namespace.
DO: Use plural names if it is semantically appropriate.
DO NOT: Use the same name for a namespace and a class.
DO NOT: Use the underscore character
namespace DCOMEngineering.Windows.Deployment { }
David Anderson: Most of the time when naming a namespace I tend to use a brand name for the root instead of my company name. This allows me to reserve my company name for the future of any absolutely critical namespaces. In return I don’t have to do any major refactoring due to namespace collisions because of poor decision making early on. I think it is very important to give your namespace names some serious short-term and long-term thought before you call it set in stone.
Naming Classes
The following rules outline the guidelines for naming classes.
DO: Use Pascal case.
DO: Use a noun or noun phrase to name a class.
DO: Use a compound word to name a derived class. The second part of the derived class’s name should be the name of the base class, such as InvalidOperationException is an appropriate name for a class derived from Exception.
DO NOT: Use a prefix such as C
or a suffix such as Class
in the class name.
DO NOT: Use the prefix I
unless the class is an interface.
DO NOT: Use the underscore character.
public class OperationsManager : Manager { }
David Anderson: Naming a class can be pretty difficult. Just like namespaces, give your classes some serious shortterm and long-term thought. Classes are more likely to encounter name collisions than namespaces, which in the event it does happen can be remedied by using namespaces and namespace aliases, but it’s best to avoid it, if at all possible. There are also exceptions to the conventions for naming a derived class, such as in the example of OperationsManager deriving from Manager. In the business world, both are an employee, so the convention is broken when your Manager class derives from the Employee class. In this situation, that’s okay, but don’t let this stray you from following convention.
Naming Fields
The following rules outline the guidelines for naming fields.
DO: Use Camel case.
DO: Use descriptive field names preferring a noun or noun phrase. Field names should be descriptive enough that the name of the field and its type can be used to determine its meaning in most scenarios.
DO: Use names that describe the fields meaning rather than names that describe the field’s type. DO NOT: Use reserved names as field names.
DO NOT: Use Hungarian type notation.
DO NOT: Prefix field names with _
or m_
.
CONSIDER: Choosing a different name for a field if the current name is too long, and cannot be shortened without sacrificing the ability to easily identify the fields meaning.
public class OperationsManager : Manager { private Department department; private ICollection<Manager> managers; private decimal salary; private SiteDirector siteDirector; }
Naming Constructor Parameters
See Method Parameters.
Naming Events
The following rules outline the guidelines for naming events.
DO: Use Pascal case.
DO: Use a verb in the event name to describe the action the event represents, such as Changed in ProgressChanged or Clicked.
DO: Use a gerund (the “ing” form of a verb) if possible to create an event name that expresses the concept of pre and post-events such as in ProgressChanging and ProgressChanged.
DO NOT: Prefix an event with On
or suffix an event with Event
.
public class CustomerService { public event EventHandler CustomerCalling; public event EventHandler CustomerCalled; }
David Anderson: Events are another construct that can be hard to name. I remember countless times when I was learning Windows Forms years ago where I would get confused about the order in which events fired. A case that comes to mind is a lot of the controls have both Resized and SizeChanged events. Without documentation it can be hard to deduce which one fires first without debugging it, and what if the order in which they fire could change? This is why it is important to name your events well and document them like we discussed in the previous sections.
It’s also worth noting that it can be hard to name events with pre-event and post-event in mind. Take the example in Figure 4. CustomerCalling is not actually a pre-event, it’s a current event, because you can’t technically know the exact time before a customer calls, until they call. It is a pre-event in the sense that it is a notification you can handle before the action of calling is allowed to continue, but is definitely something to keep in mind when naming an event, because how you name the event may be drastically different depending on the action. You can have an action where you can control when it is invoked, like calling method you know when pre-event takes place, but when you have an event you don’t control like an incoming request, the pre-event isn’t exactly known. For situations like I just stated you need to make sure your events are well-documented on how and when they are triggered so they can be properly consumed by developers.
Naming Properties
The following rules outline the guidelines for naming properties.
DO: Use Pascal case.
DO: Use a noun or noun phrase to name properties.
DO NOT: Use Hungarian notation.
CONSIDER: Naming the property the same as its underlying type when its meaning is literal. For example, if you declare a property named Color, the type of the property should likewise be Color.
public class OperationsManager : Manager { public String Email { get; set; } public SiteDirector SiteDirector { get; set; } }
Naming Methods
The following rules outline the guidelines for naming methods.
DO: Use Pascal case.
DO: Use verbs or verb phrases to name methods.
DO: Use precise method names that easily describe the action the method performs.
CONSIDER: If a method is hard to name because it does more than one thing, it is usually a clear indication that your method needs refactored into multiple methods.
public class OperationsManager : Manager { public void FireEmployee(Employee employee) { } public Report GetEmployeeReport(Employee employee) { } public void HirePerson(Person person) { } }
David Anderson: I don’t find methods particularly hard to name, but I do spend a lot of time naming them. Method names are one of the most important, if not the most important identifier to name. They are your implementation details of your class, and where you will spend the majority of your time in code. Name these well enough, and maintaining your code is a lot easier for everyone.
Naming Method Parameters
The following rules outline the guidelines for naming parameters.
DO: Use Camel case.
DO: Use descriptive parameter names preferring a noun or noun phrase. Parameter names should be descriptive enough that the name of the parameter and its type can be used to determine its meaning in most scenarios.
DO: Use names that describe the parameters meaning rather than names that describe the field’s type.
DO NOT: Use reserved parameters.
DO NOT: Use Hungarian notation.
public void SetPosition(int x, int y) { } public void CalculateProgress(int minimum, int maximum, int value) { } public void DownloadFile(Uri uri, String filePath) { }
David Anderson: Generally you should follow the same guidelines for parameters as you do fields. You can differentiate between a field and parameter by using the
this
keyword.
Documenting Code
Someone wrote a class, and now you need to consume its implementation. Where do you start? How do you use this class? What does it even do? These are all very common questions from developers when they first discover a type, and the answer to all of these questions is documenting the code itself. Have you often wondered why Msdn has such great documentation? I can tell you that it’s not because there is a technical documentation team doing all the work. Yes, there is a documentation team that does a lot of work, but the majority of the documentation already exists because it was documented by the developers who wrote the code and took the time to do it, in the actual code.
Visual Studio provides a rich means of documenting your code through Xml Documentation Comments. I also want to point out how incredibly easy this is to do, and how very little time it takes. Take the class I wrote in Class Structure, Figure 2; and in Visual Studio, place your cursor right above the class constructor and type /// (three forward slashes). You will notice that Visual Studio adds a bunch of stuff to your code.
/// <summary> /// /// </summary> /// <param name="name"></param> public Employee(String name) { this.name = name; }
Typing three forward slashes in Visual Studio automatically generates empty xml documentation comments for you to fill out. This is nice because no matter how many parameters you have, it will automatically provide you with ready to fill out comments for each one of them.
David Anderson: You can use this on almost anything, but there are some things that it will not work for, such as using directives to import namespaces and namespaces directly. Furthermore, even though you can document almost anything, you shouldn’t and should you should avoid over-documenting. There are ways to document code, and ways not to. Then there is also what to document, and what not to document. Luckily, the rules I usually give to developers to follow on this are very simple.
DO: Document a summary of all classes, regardless of their accessibility modifier.
DO: Document all public, protected, internal, and protected internal classes, constructors, methods, properties, constants, readonly static fields, events, and delegates.
DO NOT: Document items that have a private accessibility modifier, unless it is very useful to do so, either because its implementation is large, complicated, or follows some complicated business rule that is hard to remember.
David Anderson: If you’re wondering why you should use xml documentation comments rather than regular code comments, it’s because the xml comments are used by Visual Studio to provide information to Intellisense (the tooltip you get when you hover over an identifier in code). It’s a rich documentation set that allows you to even make bulleted lists in comments, and it’s even used to generate xml documentation comment files on disk that you can use to generate Msdn style documentation sites with. Let’s put these rules into practice and document our Employee class. I will demonstrate documenting the class itself, constructor, and its various properties.
namespace DCOMEngineering.DeveloperDocument.Demo { using System; using System.Linq; /// <summary> /// Provides information about a company employee. /// </summary> public class Employee { private string email; private string name; private decimal salary; /// <summary> /// Initializes a new instance of the DCOMEngineering.DeveloperDocument.Demo.Employee class /// using the specified name. /// </summary> /// <param name="name">The name of the employee.</param> public Employee(String name) { this.name = name; } /// <summary> /// Gets or sets the employee's email address. /// </summary> public String Email { get { return email; } set { email = value; } } /// <summary> /// Gets or sets the employee's name. /// </summary> public String Name { get { return name; } set { name = value; } } /// <summary> /// Gets or sets the employee's salary. /// </summary> public Decimal Salary { get { return salary; } set { salary = value; } } } }
Documentation is absolutely critical to writing high quality code. I always advocate what I read in Code Complete 2 by Microsoft, because it is one of the most accurate statements I have ever read about documentation in code.
Construction’s product, the source code, is often the only accurate description of the software.
In many projects, the only documentation available to programmers is the source code itself. Requirements specifications and design documents can go out of date, but the source code is always up to date. Consequently, it’s imperative that the source code be of the highest possible quality. Consistent application of techniques for sourcecode improvement makes the difference between a Rube Goldberg contraption and a detailed, correct, and therefore informative program. Such techniques are most effectively applied during construction.
Documenting Classes
Document classes using a summary-description of what the class is, and preferably its overall purpose. Anyone reading the class summary should easily be able to deduce what the class’s purpose is.
/// <summary> /// Provides information about a company employee. /// </summary> public class Employee { … }
Documenting Constructors
Document constructor’s using the following grammar: “Initializes a new instance of the
Namespace(s).ClassName class”. This provides consistency with how .NET Framework classes are documented, which will be familiar to most developers.
/// <summary> /// Initializes a new instance of the DCOMEngineering.DeveloperDocument.Demo.Employee class. /// </summary> public Employee() { }
Documenting Properties
Document properties first with “Gets or sets …”, “Gets …”, or “Sets …” following by its summary description. This clearly indicates to a developer whether the property is read-only, read-write, or write-only. This provides consistency with how .NET Framework properties are documented, which will be familiar to most developers.
/// <summary> /// Gets or sets the employee's email address. /// </summary> public String Email { get { return email; } set { email = value; } } /// <summary> /// Gets the employee's name. /// </summary> public String Name { get { return name; } }
Documenting Methods
Document methods using a summary description of what the method’s action is, being as precise as possible. Describing a method’s action is generally more difficult than describing a simple property or class, so make sure to give it the time and thought to produce the most clearly understandable description you can. Optionally, use the
/// <summary> /// Calculates the employee's base salary. /// </summary> /// <param name="hourlyRate">The hourly rate the employee makes.</param> /// <devdoc> /// At our company, a salary is based on a 300-day work-year /// with 8 billable work hours per day. /// </devdoc> public decimal CalculateSalary(decimal hourlyRate) { return (hourlyRate * 8) * 300; }
Method documentation is arguably the most critical documentation in your class, because methods generally contain almost all of your class’s behavior. In Figure 8, you see the summary description that describes what the method’s action is, but in addition you have documentation for the arguments it takes as parameters too. This is important because a developer needs to know what a parameter is, and what it expects as an argument so that they can use the method correctly.
In addition to the standard documentation, you will note that there is also a
David Anderson: When a method’s implementation is too complicated to explain without forgetting a bunch of details, has unique business rules, or there is something else about it that warrants some detailed explanation, you should prefer to use the
tag. The advantage of the tag is that it is generally included by documentation generators like Msdn where you see a remarks section. In most cases though, development teams do not generate documentation sites, and use the code itself as documentation. In these scenarios, favor the tag while still considering that you might use a documentation generator in the future.
Documenting Fields and Constants
Fields and constants are not normally publicly accessible and their naming conventions (covered in later sections) should be self-explanatory and easy to deduce. Sometimes though you do want a field or constant to be public, and in that scenario a simple summary description is all you need. An exception to this rule is if a field has such a critical role in the class that it would be absolutely beneficial to document it, then do so.
/// <summary> /// This field is critical to our system. If this is removed, /// or modified in any way there could be adverse behaviors. /// </summary> private string email;
There isn’t much else to say about documenting fields. Usually you shouldn’t and don’t, but in the event you do it’s not a major discussion.
Documenting Events
Document events such as “Occurs when …”. This provides consistency with how .NET Framework events are documented, which will be familiar to most other developers.
/// <summary> /// Occurs when the progress of the file download has been changed. /// </summary> public event EventHandler<ProgressChangedEventArgs> ProgressChanged;
As you can clearly see, documentation can easily become quite a large subject to discuss. However, I have covered enough to give you a good foundation to start documenting your classes well, adding that extra layer of quality. You will find that other developers reading your code will not have a difficult time, and the even better news is that neither will you two weeks from now when you have to go back and read it again.
DO: Use the
DO: Favor the
DO: Be extremely consistent in your documentation while being as articulate and precise as possible.
DO NOT: Document private fields, unless there is a very good reason to do so.
DO NOT: Use normal code comments for documentation. These are included in compiled source code and create code bloat. Xml documentation comments are stripped from the source code when it is compiled, and are not included in the final output assembly.
At first it seems like unproductive and tedious work, but as you keep documenting your code it becomes a natural process. A good rule of thumb is that as soon as you declare something you know should be documented, document it now and not later. You already know what you are about to write (if you don’t, you probably need to revisit your requirements and design), and it will save you time and frustration for everyone in the long run.