Standardized Coding Design and Style Guide for Open Source Project Development in C#

Table of Contents

Introduction

The purpose of this document is to provide software developers a standard procedure and guide for developing, formatting, and implementing software solutions written in C#. These procedures are based on commonly accepted industry best practices and will assist in the readability and maintainability of C# code developed by Talegen and others. These rules were derived from multiple sources and meet or exceed previously defined development standards. These rules should also be compatible with the Microsoft StyleCop source code analysis plugin for Visual Studio found on Nuget.org. The StyleCop plugin will be the primary tool used to ensure source code development standards are being adhered to by projects managed by Talegen.

General Naming Conventions

Elements within the application code must adhere to the following naming conventions to ensure consistency and continuity of style and design.

Element Case

There are two capitalization systems that are standard in software development. The choice of style depends on the element you are naming as well as the commonly accepted standard for the given programming language. At Talegen, we will be adhering to one common standard between all programming languages to avoid conflicts and maintain consistency.

With only a few exceptions, all variables throughout all code should adhere to these element casing standards.

Naming Mechanics and Word Choice

Use nouns for objects, verbs for methods, and so on. If a method starts with Get or Set consider refactoring the method as a property with exposed get and set accessors. Use terms consistently throughout the application. For example, use “userName” when referring to the user account name, and “userKey” when referring to the unique user account record key. Using “userId” can be confusing for some developers differentiating between the two.

Naming Elements

Naming Namespaces/Assemblies

Classes and Structures

Documenting Code

Code files within the application must adhere to a standard documentation format to ensure consistency and continuity of style and design.

XML Documentation

C# syntax provides a mechanism for inserting documentation for classes and elements directly into the code, through the use of XML documentation headers. Describing these elements is beyond the scope of this document. For an introduction to these headers and a description of the header syntax, see the following article: http://msdn.microsoft.com/en-us/magazine/cc302121.aspx. The code file should always include a comment with the following types of elements should have documentation headers: classes, constructors, delegates, enums, events, finalizers, indexers, interfaces, methods, properties, and structs. Each of these elements should be completely documented including summaries for elements, fields, return values and parameter descriptions. Generic type parameters must also be documented to ensure completeness.

Source Code Headers

//------------------------------------------------------------- 
// <copyright file="ClassFileName.cs" company="Talegen, LLC"> 
// Copyright (c) Talegen, LLC. All rights reserved. 
// </copyright> 
//-------------------------------------------------------------
/*
  *
 (c) Copyright Talegen, LLC.
 *
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 *
 */ 

General Commenting Rules

else 
{ 
    // TODO: throw error because user name already exists 
}

Programming Style

A general adherence to the following programming style should be maintained to provide for consistency and legibility throughout the website application.

Layout Rules

These rules are defined to ensure a consistent layout within code to help the reader’s eye follow program structure and logic easier.

Curly Brackets

Class Properties

public string SomeString
{
get
{
return this.someString;
}
 
set
{
this.someString = value;
}
}
 
public override bool SomeBoolean { get; set; }
 
// starting with C# 6.0
public string AnotherValue => return this.someList.FirstOrDefault();

Maintainability Rules

These rules are defined to ensure that code is easily maintainable and help eliminate possible logic errors caused by coding style.

Parenthesis

Code Files

Code Ordering Rules

These rules are defined to ensure a consistent ordering pattern within code to help the developer quickly find program structure and elements easier within a code file.

“Using” Directives

Element Ordering

It has been argued that having related elements grouped together makes more sense, but in organizing by relation, one also breaks down the readability of the source code. For example, the following code blocks logically work the same but the ordered example is much easier to comprehend and allows for fast lookup of a private field. Because elements are ordered, #region keywords can also be used to organize sections of the class to enhance the readability of the code.

public class EasyToRead
{
    #region Private Fields
    private string someString;
    private int someInteger;
    private decimal someDecimal;
    #endregion
    #region Public Constructors
    public EasyToRead()
    {
        this.someString = string.Empty;
        this.someInteger = 0;
        this.someDecimal = 0;
    }
    #endregion
    #region Public Properties
    public string SomeString
    {
        get
        {
            return this.someString;
        }
 
        set
        {
            this.someString = value;
        }
    }
 
    public int SomeInteger
    {
        get
        {
            return this.someInteger;
        }
 
        set
        {
            this.someInteger = value;
        }
    }
 
    public decimal SomeDecimal
    {
        get
        {
            return this.someDecimal;
        }
 
        set
        {
            this.someDecimal = value;
        }
    }
    #endregion
 
    #region Public Methods
    public void DoStringSomething(string value)
    {
        this.PrivateStringSomething(value);
    }
 
    public void DoIntegerSomething(int value)
    {
        this.PrivateIntegerSomething(value);
    }
 
    public void DoDecimalValue(decimal value)
    {
        this.DoSomeDecimalThing(value);
    }
    #endregion
 
    #region Private Methods
    private void PrivateStringSomething(string value)
    {
        this.someString = "Do something privately with" + value;
    }
 
    private void PrivateIntegerSomething(int value)
    {
        this.someInteger = value + 1;
    }
 
    private void DoSomeDecimalThing(decimal value)
    {
        this.someDecimal = value;
    }
    #endregion
}

The following HardToRead class is an example of how an unordered class may appear. The color coding of access types helps denote how fragmented the “by relation” ordering method is and makes finding an element for a related type more difficult when used elsewhere outside of the related elements. Also, because there is no organization of elements, developers can enter private and public methods in any order they desire providing more problems in discovering class elements when looking for a specific element of a given protection. An example of this is found in the HardToRead class example where public methods are defined after private methods except for the last two methods. As a developer reading the code, if one knows private methods will always be defined near the end of a class, one will save a significant amount of time skipping portions of code searching for a given method.

public class HardToRead
 {
     public HardToRead()
     {
     }
     private int someInteger = 0; 
     public int SomeInteger {     get     {         return this.someInteger;     }     set     {         this.someInteger = value;     } } 
     private void PrivateIntegerSomething(int value) {     this.someInteger = value + 1; } 
     public void DoIntegerSomething(int value) {     this.PrivateIntegerSomething(value); } 
     private string someString = ""; 
     public string SomeString {     get     {         return this.someString;     }     set     {         this.someString = value;     } } 
     private void PrivateStringSomething(string value) {     this.someString = "Do something privately with " + value; } 

     public void DoStringSomething(string value) {     this.PrivateStringSomething(value); } private decimal someDecimal = 0; public decimal SomeDecimal {     get     {         return this.someDecimal;     }     set     {         this.someDecimal = value;     } } 

public void DoDecimalValue(decimal value) {     this.DoSomeDecimalThing(value); } 

private void DoSomeDecimalThing(decimal value) {     this.someDecimal = value; }
 }

Readability Rules

These rules are defined to ensure a consistent readability within code to help the reader’s eye follow program structure and logic easier.

General Readability

Type AliasTypeFully Qualified Type
boolBooleanSystem.Boolean
byteByteSystem.Byte
charCharSystem.Char
decimalDecimalSystem.Decimal
doubleDoubleSystem.Double
shortInt16System.Int16
intInt32System.Int32
longInt64System.Int64
objectObjectSystem.Object
sbyteSByteSystem.SByte
floatSingleSystem.Single
stringStringSystem.String
ushortUInt16System.UInt16
uintUInt32System.UInt32
ulongUInt64System.UInt64

Spacing Rules

Application Design

ASP.NET MVC Page Development

When at all possible, a single controller shall be used to manage all actions for a programmatic interface within the application. There shall be a clear and clean separation of concerns between control logic, data models, and view interfaces.

Web Project Structure

Business Layer Classes

Business layer classes shall conform to the following standards to ensure consistency.

General Rules

Error Handling

Error handling shall be used consistently wherever an error may arise that needs entrapment and reporting. The developer should use a general catch for unhandled errors but also should be diligent in their use of try/catch to handle potential errors within their methods or methods being utilized from other libraries.

Try…Catch…Finally Statements

“Using” Blocks