Skip to content

Pull Requests Coding Standards

Peter Robinson edited this page Jan 18, 2019 · 6 revisions

Pull requests and Coding Standards

While most computer programming courses will teach you basic code standards to follow, most of us will likely forget these rules once we start working in the 'real world', where getting something to work is way more important than getting something clearly documented and easy to read through.

When working on your own fork of T2D, you are of course free to work as you wish; it is your code.

When issuing a pull request to the official T2D repository however, you must make sure that your code follows certain rules and standards.

Not only will this make the merging process easier, it will also give a clear, common voice to the source code.

This guide focuses mostly on C++ source code changes. For a complete guide to TorqueScript standards and best practices, click here

Table of Contents

Chapter 1. How to place a pull request

Chapter 2. Coding Standards and best practices

Chapter 3. Portability

Chapter 4. Be Consistent

1. How to place a pull request

Make sure you are familiar with the basic git concepts and terms before continuing.

  • Cloning the repo and working with Git

    • Fork and Clone the official Torque2D repository

    • 'Check out' the development branch.

      • Create a new branch from development
        • Make the necessary code modifications and test thoroughly.
          • Add changes to the staging area with git add
            • Create a new commit for the staged modifications with a short, concise message regarding the modification.
    • From https://github.com/GarageGames/Torque2D, click 'Pull request' at the top of the screen.

      • Select the official repository development branch on the left-hand side

Creating a pull request

If additional information is required, feel free to add it in the comments section of the pull request on github.

After the pull request has been placed, the steering committee will try merging the changes and make tests to make sure that your modifications are fully compatible with the engine. Should any question or problem arise, the Steering committee will contact you via the Pull request's comments system.

Pull request requirements

Before submitting pull requests, you will have to fill out the 'Open Source Software Agreement' in your GarageGames account. You may find the option in the 'My Settings' section of garagegames.com.

It is important that pull requests focus on one feature at a time. For example, if your pull request adds basic shader support, it shouldn't also add in helper functions for trigonometry.

If you want to propose several pull requests at the same time, you will have to separate each pull request into a different branch. To continue with our previous example, one branch would feature the shader code and another branch would feature the trigonometry functions.

This might seem like overkill but it helps in testing the issues and allows us to easily keep track of separate commits.

2. Coding Standards and best practices

All pull requests should follow the suggested principles listed below.

Readability

The main thing to remember here is that your code will be read by others and should be easy to follow.

When writing logic, always favor readability.

Comments

While not all code changes require comments, it is good practice to include comments to specify what a function actually does. This simplifies things when users are trying to find a specific piece of code and allows them to avoid having to trace through the code line by line.

Do NOT use comments to specify that changes were made on day X by developer Y.

Example of what NOT to do : //Added function xyz - 15/03/13 - Simon Love

Use the // comment notation rather than the /* comment / notation. The latter style of comment leads to confusion when comments are nested. Furthermore, since the / and */ can span multiple lines, it is difficult to pair up the starting and ending points of the commented code.

As T2D is distributed under the git system, one can always look to the log to see what changes were made by whom and when.

Console methods usage strings

Whenever you define a new ConsoleMethod, make sure to fill out the usage string. It will help users reading through the code and will issue coherent error messages to the console, which will greatly facilitate debugging applications.

ConsoleMethod(ClassName, functionName, returnType, Minimum_arguments, Maximum_arguments, usagestring)
{
}

What follows is a usage string example from CompositeSprite_ScriptBinding.h

ConsoleMethod(CompositeSprite, setDefaultSpriteSize, void, 3, 4,    "(float width, [float height]) - Sets the size at which sprites are created.\n"
                                                                    "@param width The default width of sprites.\n"
                                                                    "@param height The default height of sprites\n"
                                                                    "@return No return value.")

Each parameter should have its dedicated @param line.

If Statements

Always make sure to clearly divide if statements on several lines as such

 if(condition)
      object->dosomething();
   else
      object->dosomethingelse();

The only time an if statement can be written on a single line is when using the ? operator as demonstrated in this example from actionmap.cc :

smBreakTable[entry].objectId = pNode->object ? pNode->object->getId() : 0;

Brackets and Indentation

Always keep bracket pairs lined up horizontally. If you open a bracket, the corresponding closing bracket should be place on the same column in the code, as in the following example :

if ( flag )
{
   for ( int i=0; i<10; i++ )
   {
      // some code
   }
   // some code
}
else
{
    // some code
}

File Header comment

All newly created files should contain the proper disclaimer and copyright information in order to be included in the official T2D repository.

You may copy this header from any file in the repository or paste it from here :

//-----------------------------------------------------------------------------
// Copyright (c) 2013 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

Compiler Warnings

When compiling the engine, you will notice that not a single warning message is issued.

Warnings are a great way to detect potentially problematic situations and should be treated as error messages. Even though your code might still run without a hitch, we want T2D to be warning-free.

The #define Guard

To prevent recursive inclusion, all header files (filename.h) have an #ifndef directive immediately following the File Header Comment, and a corresponding #endif directive as the last line of the header file. The following example shows the proper format and nomenclature for a header file called BaseClass.h

#ifndef _BASECLASS_H_
#define _BASECLASS_H_
 
// rest of header file for baseclass.h

#endif // _BASECLASS_H_

Variable types

All of the variable types have been replaced to allow for cross-platform compiling. Always use these instead of the intrinsic ones found in C++.

  • S8 -> signed char

  • U8 -> unsigned char

  • S16 -> signed short

  • U16 -> unsigned short

  • S32 -> signed int

  • U32 -> unsigned int

  • F32 -> 32-bit float

  • F64 -> 64-bit float (double)

You will find the complete list of supported types in /engine/source/platform/types.h

3. Portability

Torque2D currently supports several platforms

  • PC
  • OSX
  • iOS
  • Android
  • Linux
  • Web through Emscripten

Whenever possible, we should strive to keep the same functionality across all platforms.

Most of the engine's functionality will be platform-agnostic : creating a sprite is achieved with the same exact code across all platforms. As such, you can easily subclass a SceneObject and your code will immediately work across all supported platforms.

It gets more complicated if you need to modify low-level stuff such as writing and reading files or updating the OpenGL implementation. This type of code will differ depending on the Operating System you are targeting.

As an example, let's take a look at the Timekeeping functions.

To get the current local time in a T2D application, you would call Platform::getLocalTime();, regardless of the platform you are working on.

The function is defined in different locations, depending on your current platform :

Under /platformWin32/WinTime.cc for Windows

Under /platformOSX/osxTime.mm for OSX

Keeping the functions isolated in their own platform-specific folders makes it much easier to read the code that is related to your platform.

Note that code directories for other Operating systems will not appear in your local IDE solution but the files will still exist in Torque2d/engine/

In most cases, the wrong way to handle platform-specific code is to use multiple ifdef statements. Using ifdef creates cluttered code and is extremely difficult to maintain.

If your code modifications add a feature to one of the platforms exclusively, just keep it in the appropriate OS-specific directory.

For example, only the iOS code contains functions related to the iOS Game center without exposing these functions to T2D projects compiled on other platforms.

4. Be Consistent

Applying these common standards to the code base makes T2D easier to approach and easier to modify for all game developers, regardless of their skill level. While the methods used to obtain results might vary from developer to developer, if they are written coherently and well-documented, everybody wins.

Whenever doubt arises, just look at similar functions in the source code and adjust your code to match the coding style already present in the engine.