Coding Conventions

These are the official coding guidelines used by Nuclex Development Labs. The goal of this document is not to define a rigid, bureaucratic set of rules that are tedious to comply with, but to complement the programmer in creating readable and understandable code. All rules are intuitive and based on solid reasoning.

In general, we try not to stray from the mainstream in any major point, so as not to alienate us from the code of other programmers or from the classes offered by the .NET base class library.

The Motto: short – simple – obvious

1. File Structure

Establishing a common order of elements in each source file greatly helps programmers to navigate unknown code. In this context, we believe that someone looking at the code should first see the actual methods he can call from the outside and only then get to see the class’ bowels (namely, private methods and fields).

1.1 Order class elements by visibility

When you look at a class someone else has written, the first thing you want to see are its constructor and the public methods it exposes, not the implementation details. Thus, we order elements by their visibility, firs comes public, then protected, then internal and finally private members.

Place any definitions (such as nested classes, delegates and events) at the top of a class to give the reader an easy overview of the nested types and connection points belonging to the class. Next comes the constructor(s), the finalizer and the Dispose() method, if any. Then follow up with normal methods and properties. Fields are at the very bottom of the class because you can easily jump there (Strg+End) and because they’re definitely not the first thing another programmer wants to know about your class.

class Foo {

  // 1. Nested classes, delegates and events

  // 2. Constructors (of any visibility) and finalizer / Dispose() method

  // 3. Public methods and properties (visible globally)
  // 4. Protected methods and properties (visible in inheritance tree)
  // 5. Internal methods and properties (visible in same assembly)
  // 6. Protected Internal methods and properties (visible in inheritance-tree of same assembly)
  // 7. Private methods and properties (visible in class only)

  // 8. Public fields
  // 9. Protected fields
  // 10. Internal fields
  // 11. Protected Internal fields
  // 12. Private fields

}

1.2 Order class elements logically

Apart from the ordering by visibility, you should organize your files logically. For example, try to keep methods called by other methods directly below those, place different overloads of the same method next to each other and move methods not depending on each other close together if they are related.

1.3 Keep source files below 500 lines

No source file is allowed to become longer than 500 lines. In fact, you should try to stay way below that number. If you feel the need to write classes taking more than 500 lines, either the design of your class is too complex, your class tries to take on multiple roles or you haven’t properly identified reusable code sections and broken them down into small, understandable methods and helper classes.

There is always the option to factor out concepts and strategies into separate, reusable classes. This applies even more to UI classes that become too large by the mere amount of controls they need to manage, which not only is problematic for the developers, but also repels the end-user with overly complex dialogs.

2. Naming and Casing

Using concise, descriptive names is the most important thing about writing code. Try, figuratively, hitting the nail on the head whenever you name something. Always try to find a simple term that gives the reader the right idea about what a variable or method does. If you really can’t find a fitting term (or combination thereof), just standardize the closest matching term for this specific use throughout the project and document that!

2.1 Do not use abbreviations

Even well-known abbreviations make identifiers harder to read and in combination produce ugly chunks of letters. Your code becomes more esthetical and it helps to keep your variable names simple if you force yourself to avoid abbreviations at all costs. There are very few exceptions (like, Xml) and you certainly shouldn’t add more to those :)

2.2 Write all your names in proper English

Any variable, method or class name you choose should follow the conventions of the English language. Do not twist words around (eg. not FileOpen/FileClose but OpenFile/CloseFile instead) and use the correct plural forms (eg. not Childs, but Children instead). Do not use prefixes for your identifiers (a prime example of prefixes would be Hungarian notation). The only exception to this rule is that interface names are prefixed with an I, for the sake of keeping in compliance with .NET Framework conventions and nothing else.

2.3 Use NormalCase for public and camelCase for private elements

In order to not produce schizophrenic code when interacting with the .NET Framework, all public elements follow the same naming rules that the .NET Framework uses. Thus, anything that can be seen from the outside of a class, including internal and protected members, is written in NormalCase. Private things such as private methods and local variables are written in camelCase. Place uppercase letters only after complete English words, not after each syllable (eg. not DisConnect but simply Disconnect; not ReMove but Remove).

3. Braces

We handle all the different kinds of braces with just one rule (C# actually has 4 kinds of braces: curly braces, brackets, rounded braces and wedges). That means if the argument list of a method becomes too long, break it the same way as you break the code inside a multi-line if statement. One rule for everything.

3.1 Put opening braces at the end of the line

We like our opening braces at the end of declarations and control flow keywords. The indentation already shows very well where a block begins and where it ends. There have even been successful languages (Python being the most prominent example) that rely solely on indentation to determine the length of blocks. Free standing curly braces would act as semi-empty lines whereas we believe that empty lines should instead be at the programmer’s disposal to separate logical sections of code.

3.2 Always use curly braces for cases in a switch statement

This is mainly for consistency reasons, since historically, the switch and case statements don’t blend in with the rest of the language very well. Using curly braces for each case in a switch statement makes the indentation more logical and prevents variables declared in one case from becoming visible in the scope of other cases.

4. Indentation and Line Breaks

Indentation in general is a matter of personal preference and regularly subject to discussion. Using a consistent scheme throughout an entire project goes a long way in helping developers quickly grasp the workings of the code without being irritated by small discrepancies from the style their brain is currently trained to read.

4.1 Indent any nested block by 2 spaces

Indentation is done with spaces, not tabs. This keeps code looking identical in web browsers and editors with different tab widths. While of course the nesting level should not go too deep, 2 spaces provide good visual cue without scattering the code all over the horizontal width of an editor for developers using larger fonts or a lower screen resolution.

4.2 Limit your lines to 100 columns at most

This is not just a suggestion, it’s an actual rule. Creating long lines will prevent the developer from seeing what’s going on and require him to scroll the text window or enable line wrapping, both of which are awkward for anyone trying to get a quick grasp of the code. It will also make it harder to post code snippets on the web or to print them. So do not cross the 100 column boundary, ever.

4.3 Try to break long lines at the brace level

When you decide to break a long line, try to do so after an opening brace (or a comma sign if no brace is available). As outlined in section 3, the opening brace is left at the end of the line, while everything that was inbetween the braces goes into the next line(s), indented by 2 spaces. Example:

Do not:

public void MethodWithLongArgumentList(int argument1, int argument2
  int argument3) {
  // ...
}

Instead, do:

public void MethodWithLongArgumentList(
  int argument1, int argument2, int argument3
) {
  // ...
}

5. Special Regulations

Some additional regulations not fitting into any of the topics laid out above:

5.1 Dot not wrap fields in pointless properties

Do not write useless properties around fields if there’s not reason to do so! If you write a Vector or Matrix class for your math library, just expose the X, Y, M11 etc. fields. Use properties where they make sense: when you need to check assigned values of validity or need to perform a calculation to return a value (such as when a rectangle’s Width property calculates Math.Abs(X2 - X1) to determine the width).

5.2 Keep your code together

Try not to create too many assemblies (eg. don’t create a separate assembly for each namespace). It might feel nice and clean to have lots of assemblies with different logical responsibilities, but the inter-assembly dependencies quickly become a real pain to manage and it leaves a negative impression when someone has to identify all the different assemblies required to use a given class by working his way through the dependency tree one step at a time. This is very much a matter of experience and taste, so please consult other developers when you’re unsure on whether you should create a new assembly or extend the responsibilities of an existing assembly.

5.3 Use regions very sparingly

Never use regions to group things like your constructors, public methods or fields. This only serves as an annoyance to other developers, obstructing their view of the code and causing them additional work unfolding the regions.

Good uses of regions are few and far between. If you have a nested helper class (remember nested classes go at the top), that should go into a region so other developers don’t have to scroll over it in order to see the constructor and public methods. Simple noise like a ton of secondary interface methods for implementing tedious interfaces like IList<T> or IDictionary<K, T> can also be hidden inside a region.

Leave a Reply

Your email address will not be published. Required fields are marked *

Please copy the string J8ENPy to the field below:

This site uses Akismet to reduce spam. Learn how your comment data is processed.