Wiki

Clone wiki

Unit Class Library / Conventions

The following practices and guidelines are the standard by which any contributions to this library's code should conform.

For more information on good coding practices in C# and in general, have a look at Microsoft's .NET Framework Guidelines and Best Practices

#Naming

The naming conventions of this project are slightly different from the official Microsoft conventions. The differences are highlighted in this section, so if a naming case is not described below, you may assume that we are using Microsoft's conventions in that case.

Here are the following differences in our conventions:

All things that can be accessed from within a class and only within that class (or its derivations) have the syntax of underscore + lowercase word + if the variable is more than one word all additional words in the variable are capitalized. This is true for variable names as well as method signatures.

Examples:

#!c#
private int _numberOfClicks
private int _views
protected bool _calculateVelocity()
All things that are accessible from outside of a class (or its derivations) should have the first letter of each word Capitalized in what is known as Pascal Casing. This is true for variable names as well as for method signatures. Notice that this applies to the Internal as well as the Public modifier.

Examples:

#!c#
public int NumberOfClicks
public int Views
Internal bool CalculateVelocity()

Sometimes you will need to use a variable with public syntax inside of your class. (e.g include special logic in your getter or setter of a property). To show that this property does exist in this class (or parent class), include the this. syntax.

#!c#
double _privateDouble;
public double UsefulPublicMethod()
{
     ...
}

private double _internalMethod()
{
   return this.UsefulPublicMethod() + ...
}

In summary, always use the underscore + lowercase to start a private or protected variable, property, or method, as well as Pascal Casing for things accessible outside of the class, such as Public and Internal. Use this to in the cases where a public or internal variable is being used in a private or protected context.

#Line Endings

If you see this warning while using Visual Studio or a similar one elsewhere:

Line_Ending.PNG

Choose "No". Modifying line endings causes all sorts of messy merge conflicts. #Other

Never do single line if statements. Although they are valid, they provide no indication that code execution has changed when they are accidentally edited to contain more than one line.

Never:

#!c#
If(true)
    doStuff();
doMoreStuff();
Always:
#!c#
if(true)
{
       doStuff();
}


If a class or struct is contained in a single file it should be divided into the regions. If a region would be empty, or there would be only one (as in partial classes or structs), leave it out. Also, note that the regions themselves reinforce the naming conventions (e.g. _fields is written with an underscore and lowercase letters because that is the convention for naming fields.)

#!c#
#region _fields and Properties
#endregion

#region Constructors
#endregion

#region Public Functions
#endregion

#region _helper Functions
#endregion

#region ISomething Interface Implementation
#endregion

There should only be one statement per line. If you are unfamiliar with the term "statement" in this context look here. This is less of a rule more of a really good guideline. Note the following code examples that return the same thing:

#!c#
public override bool AreEqual(Dimension dimension1, Dimension dimension2)
{
     return (Math.Abs(dimension1.GetValue(dimension1._internalUnitType) - dimension2.GetValue(dimension2._internalUnitType))) <= dimension1.Abs(this.GetValue(dimension1._internalUnitType) * 0.00001);
}
and

#!c#
public override bool AreEqual(Dimension dimension1, Dimension dimension2)
{
    // find the value of dimension1 in terms of its own _internalUnitType
    double dimension1Value = dimension1.GetValue(dimension1._internalUnitType);

    // find the value of dimension2 in terms of dimension1's _internalUnitType
    double dimension2Value = dimension2.GetValue(dimension1._internalUnitType);

    // find the difference in the two values
    double difference = dimension1Value - dimension2Value;

    // in case one of those numbers was negative take the absolute value
    difference = Math.Abs(difference);

    // because of rounding errors introduced by type conversions, set a tolerance of .01% of the first dimension's value
    double tolerance = dimension2Value * 0.00001;

    // see if the difference is less than or equal to the tolerance, if it is, then they are close enough to be considered equal
    bool dimensionsAreEqual = (difference <= tolerance);

    return dimensionsAreEqual;
}
The second method's readability and "debug-ability" is well worth the downside of the extra lines. If you were to attempt to set a break point to debug the above code segments, you would realize that you can find the bugs much more easily. In fact, there is a different bug in each of the above segments. Can you find them? It is highly likely you will find the second one much faster.


In general, The goal of our naming is to make the code read like English as much as possible while accurately describing the code execution.

For example, look at this method:

#!c#

public static bool StringOfParensIsBalanced(string passedInputString)
{

    int numberofLeftParensFound= 0;
    int numberofRightParensFound= 0;

    for(int locationInString = 0; locationInString < passedInputString.length(); locationInString ++)
    {
           if(passedInputString.charAt(locationInString ) == ()
           {
               numberofLeftParensFound++;
           }
           else if(passedInputString.charAt(locationInString ) == ))
           {
               numberofRightParensFound++;
           }
           else
           {
               throw new ArgumentException(Please enter a string containing only parens.);
           }

           if(numberofRightParensFound > numberofLeftParensFound))
           {
               return false;
           }
    }

    if(numberofLeftParensFound != numberofRightParensFound)
    {
        return false;
    }

    return true;
}

The method shown above will look like this when called:

#!c#

If(StringOfParensIsBalanced("()()()()()(()()())"))
{
    ...

You see how easily understood that method is.

Here is an example of what that method could have looked like: The following code takes up less space and is slightly faster. In spite of this, we prefer the above sample because of its readability. For this library, always err on the side of readability.

#!c#

public static bool IsBalanced(string x)
{
    int cnt = 0;

    for(int i= 0; i < x.length(); i++)
    {
           if(x.charAt(i) == ()
           {
               cnt++;
           }
       else if(x.charAt(i) == ))
           {
              cnt--;
           }
           else
           {
              throw new ArgumentException(Please enter a string containing only parens.);
           }

           if(cnt < 0)
           {
             return false;
           }
    }

    if(cnt != null)
    {
        return false;
    }

    return true;
}

Updated