Programming Style Guide

Introduction

This page outlines common FlatRedBall coding standards for consistency and clarity these should be followed when writing code for any first-part FlatRedBall game, FRB Editor, FRB Engine, or any other FRB application. In other words, if you are checking in any code to a FlatRedBall repository, follow these standards.

General Programming

Brackets

With the exception of single-line getters and setters in properties, brackets should be on their own lines. Correct:

public float Weight
{
   get { return mWeight;}
   set
   {
      // If there is more than one command in a setter
      // then don't keep it on one line.
      mWeight = value;
      UpdateAccordingToWeight();
   }
}

public void TryPieceCreation()
{
   if( ShouldCreatePiece() )
   {
      CreatePiece();
   }
}

Incorrect:

public float Weight
{
   get { return mWeight;} // The getter is correct.
   // Too many commands for a single line in the setter!
   set {  mWeight = value; UpdateAccordingToWeight();}
}

public void TryPieceCreation()
{
   // Brackets do not belong on the same line as the if.
   // We recognize that this is something that some prefer
   // to do, but to match consistency of the rest of the FRB
   // engine this practice is discouraged.
   if( ShouldCreatePiece() ){
      CreatePiece();
   }
}

Incrementing and Decrementing Values

The ++ and -- operators for incrementing and decrementing should always occur on their own lines. Correct:

while(!Party.IsEmpty)
{
   index++;
   Party.Characters[index].SwitchParties();
}

Incorrect:

while(!Party.IsEmpty)
{
   Party.Characters[++index].SwitchParties();
}

Exception: Compound statements are ok in for-loops:

for(int i = 0; i < List.Count; i++)
{
   List[i].Activity();
}

Use temporary variables to avoid complex statements

Each line of code should do one thing. Do not use method calls inside of other method calls, or complex logic inside of other blocks of code. Correct:

bool shouldPlayerBeDead = mPlayer.Health <= 0 && mPlayer.Type != PlayerType.Undead;
if(shouldPlayerBeDead)
{
    EndLevel();
}

Incorrect:

if(mPlayer.Health <= 0 && mPlayer.Type != PlayerType.Undead)
{
    EndLevel();
}

Limit use of "value"

The "value" keyword in properties is necessary for setters, but it should be used as little as possible inside properties. The reason for this is because it makes migrating code outside of properties into separate methods more difficult. In practice this usually means that the field represented by the property should be set first, then it should be used in any code that follows. Correct:

public int Age
{
   get { return mAge; }
   set
   {
      mAge = value;  // set mAge first so it can be used

      if(mAge < 0)
      {
         throw new Exception("Age can't be less than 0");
      }
   }
}

Incorrect:

public int Age
{
   get { return mAge; }
   set
   {
      if(value < 0) // mAge should have been set first and used here
      {
         throw new Exception("Age can't be less than 0");
      }
      mAge = value;
   }
}

Class Layout

Access Modifiers and Static

Access modifiers should be listed prior to modifiers such as static. Correct:

public static void Update()
{
   // Method code
}

Incorrect:

static public void Update()
{
   // Method code
} 

Regions

For readability all members in a class should be organized by type and surrounded with the proper regions. The following skeleton region structure shows how classes should be organized. Note, this is not required for smaller classes:

public class ExampleClass
{
   #region Enums

   #endregion


   #region Fields

   #endregion


   #region Properties

   #endregion


   #region Events

   #endregion


   #region Event and Delegate Methods

   #endregion


   #region Methods

   #endregion