NDEVR Coding Format

Naming

Naming Convensions
Item Format Example
Class Names Upper Camel Case ExampleClass
Static Function Upper Camel Case ExampleStaticFunction
Member Function Lower Camel Case exampleMemberFunction
Enum Names Upper Camel Case ExampleEnum
Enum Item Lower Snake Case with prefix e_ e_example_a
e_example_b
 Local Variable  Lower Snake Case

example_local_var

Public Member Variable Lower Snake Case example_public_var
Protected/Private Member Variable Lower Snake Case with prefix m_ m_member_variable
Static Private/Protected Member Variable Lower Snake Case with prefix s_ s_static_variable
Templated Variable Type Lower Snake Case with t_ template<class t_type>
Macros All CAPS Snake Case  EXAMPLE_MACRO_DEFINE
 Enum Primitive Index  All CAPS  X, Y, LAT, LON
Additional Naming Convensions
File Names
  • File Names are Upper Camel Case. 
  • Paths in the code are always represented using / instead of \
  • For Modules, Public Headers stored in a “Headers” Folder, Source Files in a “Source” Folder,  Qt UI in the “UI” folder, and additional Resources in “Resources” folder. See Projects and Files
 
  • Signal functions should have the suffix of Signal
  • Slot functions should have the suffix of Slot
  • Classes that directly implement a Qt class, will usually be written QTCustom[classname]

set Functions are generally set[Var]. Get functions are generally just [var](). Both follow the function naming convention of lower camel case.

_t[X] are macros defined for translated strings. _t and _td being most notable. When using the function _td, the first argument should be lower snake case.

 

Variable Types

In general, we avoid using the built-in ambiguous types such as int, long, short, etc, opting instead to use the NDEVR explicit types 

Projects and Files

Structure

In order for our automated tools to work optimally, we recommend using the directory structure described in the diagram.

Each Module should have its own code folder, as well as a folder within VS and QtCreator for the IDE specific files.

The “Create Module” Function within NDEVR DevTools can be used to easily add modules to projects that follow this directory structure.

Include Brackets
In C++, the #include directive is used to include header files in your code. The difference between using quotes (“”) and angle brackets (<>) lies in where the compiler searches for the header file:
Quotes (“”)
  • Local Search:
    The compiler first searches for the header file in the same directory as the source file that contains the #include directive.
  • Then System Search:
    If the file is not found locally, the compiler searches the system include directories.
Angle Brackets (<>)
  • System Search: The compiler directly searches the system include directories specified by the compiler and environment variables.
When to Use Each:
  • Quotes: Use quotes for header files that are part of your project, such as your own custom headers.
  • Angle Brackets: Use angle brackets for standard library headers and external libraries.
				
					#include "../Headers/ThirdPartyLibsDialog.h"//Relative Path include (Only use for library)
#include <ui_ThirdPartyLibsUI.h>//Use for "additional include directories"
#include <NDEVR/Button.h>//Use for other libraries
				
			

Strings

Strings in NDEVR should be created and used with the built-in String class which uses Unicode, UTF-8, as its storage protocol. For functions that use UTF16 (Windows, Freetype, etc) getAs<std::wstring>() can be used as a convenient means of conversion.

Passwords

In order to prevent passwords from being included in memory dumps, logging, and to ensure they aren’t used directly in IO operations, NDEVR utilizes the PasswordString. Any passwords should be stored in this structure. User entry of passwords is done via QCustomLineEdit::setIsPassword(true), which will automatically return data as a PasswordString. The moment passwords are used they may decoded then and only then. In this way, we implicitly ensure protection of sensitive user data.

Display Strings

All textual information displayed to end users should be stored and created in the TranslatedString structure. This optimized structure hashes the string for use with a translation file, ensuring the user gets the message in the language of their choice while still allowing for readable English in-line comments. For simple strings, the macro _t(…) can be used. For more complicated strings or ones with replacement use the macro _td(…).

Virtualization

Virtual Functions have an impact on speed. Thus, their use should be limited when possible. 

When To USe
  • A software service used to augment functionality in the software (See NDEVR::SoftwareService)
  • IO or file services such as PipeStreams or IO streams.
  • Inheritance from Qt Objects
  • Hardware Devices.
When Not To Use
  • Any class inheriting from DesignObject.
  • Any function that may potentially be executed in a large loop.
  • Any class inheriting from Buffer

Exceptions

Exceptions provide for an alternative workflow, which, while can provide benefit, may also cause problems if not handled correctly.

When to use
  • Inheriting from functions or classes that already throw exception. 
  • Classes inheriting from IOFactory. This allows quick exit and is guaranteed to be handled.
  • When mentioned explicitly in the documentation.
When Not To Use
  • For checks against logic that should not fail (programmer errors), use lib_assert
  • Anything that can happen in a long loop as there is overhead to the throw function.
  • For issues that can happen under normal conditions, at runtime, unless using or inheriting from CancelException.
  • Undocumented code