Accessibility Skip to Top Navigation Skip to Main Content Home  |  Change Text Size  |  Contact IRS  |  About IRS  |  Site Map  |  Español  |  Help  

2.5.3  Programming and Source Code Standards (Cont. 2)

2.5.3.5 
C++ Programming

2.5.3.5.2 
Classes

2.5.3.5.2.4  (04-28-2006)
Class Execution

  1. A member function shall never return a reference or a pointer to a local variable. This will result in a pointer referencing a variable that has gone out of scope when the function returns.

  2. A member function that does not modify member data shall be declared const.

  3. A public member function shall never return a non-const reference or pointer to member data.

  4. A public member function shall never return a non-const reference or pointer to data outside an object, unless the object shares the data with other objects.

  5. No member functions shall be implemented within the class header declaration. The only exceptions are accessors and mutators (gets and sets).

  6. If the behavior of an object is dependent on data outside the object, this data shall not to be modified by const member functions.

  7. Avoid overloading on a pointer type.

  8. An assignment operator shall return a reference to the assigning object (as the assignment operator returns the left hand side (LHS)). Non-const reference is consistent with the behavior of built-in types.

  9. When overloading the assignment operator, assignment to self shall be checked by adding the check at the beginning of the assignment method.

2.5.3.5.2.5  (04-28-2006)
Inheritance

  1. Inheritance shall not be used for parts-of relations. Use template classes for parts-of relations.

  2. Use inheritance to implement a generalization to specialization (kind of) relationships.

  3. Inherited non-virtual member functions shall not be overridden.

2.5.3.5.2.6  (04-28-2006)
Initialization

  1. Uninitialized data present in variables, objects, etc. have led to many problems. Often the problems manifest themselves as the very difficult "unable to reproduce" kind of problem at test time since the behavior of programs is dependent on the content of unitialized variables, which may or may not change with every execution.

2.5.3.5.2.6.1  (04-28-2006)
Initialization of Variables

  1. Initialize all static variables explicitly.

  2. Always initialize object instance variables of all types.

  3. Every variable that is declared shall be initialized before it is used.

2.5.3.5.2.6.2  (04-28-2006)
Initialization of Classes

  1. Use constructor initializer lists to ensure that every instance variable in a class has a defined value.

  2. When allocating objects, ensure that all pointers to the objects are initialized via an initializer list or within the body of the constructor.

  3. Classes that allocate dynamic storage shall define a destructor that releases that storage.

  4. After deleting the object in a destructor, set the pointer to NULL.

2.5.3.5.3  (04-28-2006)
Variables Scope

  1. Header files shall use forward declarations instead of including header file(s).

  2. Global variables including using the C style extern declaration shall not be used unless the need is clearly documented and described for maintainers. Use namespaces to declare broad scope variables.

  3. File scope and static variables shall be defined using the unnamed namespace.

  4. Names occurring in close proximity to the current scope, including an enclosed scope, shall not be redefined.

  5. Do not write code that is dependent on the lifetime of a temporary variable.

2.5.3.5.4  (04-28-2006)
Data Types

  1. A const shall never be converted to a non-const, except when handling an exception.

  2. Use struct when a user-defined type contains only data. Use classes when a user-defined type contains data and code that processes the data.

  3. Predefined types shall not be redefined.

  4. Do not define boolean types. The predefined boolean values " true" and "false" shall be used.

  5. Do not declare the structure type and its associated variable in the same statement. Instead, declare the structure type first, and then declare a variable of that type.

  6. Use the const type qualifier to identify data that should not change during execution. The compiler will flag attempts to change const variables, which aids debugging.

  7. The size of an array shall be declared with an enum constant or const. This makes modifying the size of an array easier, and is more meaningful to the reader.

  8. Do not use the volatile qualifier. The purpose of volatile is to suppress optimization that can "optimize out" low level access to hardware.

  9. The use of numeric values (magic numbers) in code shall be avoided. Use descriptive constants instead, with the exception that the numbers 0 and 1 are permitted if their use is self-explanatory.

2.5.3.5.5  (04-28-2006)
Conditional Constructs

  1. Logical expressions of the type if(test) or if(!test) shall not be used when test is a pointer, or the test is the return of a function which returns a non-boolean value.

  2. The "? :" operators shall not be used.

  3. A break statement shall terminate the code following each case label.

  4. The flow control primitives if, else, while, for and do shall be followed by a block, even if it is an empty block.

  5. The switch statement shall always utilize the default statement.

  6. For boolean expressions ('if', 'for', 'while', and 'do') involving non-boolean values, always use an explicit test of equality or non-equality.

  7. Avoid conditional expressions that always have the same result.

2.5.3.5.6  (04-28-2006)
File Prologs

  1. A file prolog shall be used at the beginning of all source code files (header, implementation and main program files), appearing as the first item of the file. The following section provide the required prologs for C++ header and implementation files (including main programs). The following file naming convention shall be used:

    File Type File Name/Suffix
    C++ Header file .h
    C++ Implementation file (non-main) .cpp
    C++ Implementation file (main) main.cpp

2.5.3.5.6.1  (04-28-2006)
File Size and Structure

  1. The section cites standards for File Size and Structure.

2.5.3.5.6.1.1  (04-28-2006)
File Size

  1. Unless precluded by the system or project requirements, C++ classes shall define class member functions for a single class in a single file (i.e., one .cpp file per class, defining all methods for that class).

2.5.3.5.6.1.2  (04-28-2006)
File Structure

  1. Developers shall declare classes, data structures, layouts, functions, variables, and constants in a header file named classname.h.

  2. The implementation of class methods, functions, and definition of non-static storage variables for each header file shall be located in a corresponding classname.cpp file.

2.5.3.5.6.2  (04-28-2006)
Name Conventions

  1. While such names may be permitted by C++ standard and supported by compilers, names that very solely by case tend to create readability problems for the maintenance programmer.

2.5.3.5.6.2.1  (04-28-2006)
General Naming Conventions

  1. Do not use names that vary solely by case.

  2. Do not use typedef to emphasize distinct numeric categories. Use a class definition instead.

  3. C++ names for all constructs such as classes, functions, variables, etc. shall use the intercap convention. Intercap runs all words of a descriptive name together without underscores. An exception is made for names for constants

  4. The following shall use the Capital form:

    1. Classes and Structures (nominal Classes)

    2. enum tagnames

2.5.3.5.6.2.1.1  (04-28-2006)
Identifiers

  1. Identifiers shall adhere to the conventions for ANSI standard C++.

  2. Variable and function identifiers shall use the normal form of the intercap notation. That is, the names of variables and functions shall begin with a lowercase letter.

  3. Do not use single variable names unless it is an index in a loop.

2.5.3.5.6.2.1.2  (04-28-2006)
Functions and Parameter

  1. The names of formal arguments to functions shall be specified and shall be the same both in the function declaration and in the function definition.

2.5.3.5.6.2.1.3  (04-28-2006)
Constants

  1. Define constants using fully capitalized words separated by underscore.

  2. Define constants using const or enum. Do not use #define.

2.5.3.5.7  (04-28-2006)
Formatting

  1. The IRS C++ standard indentation level is defined as 4 spaces; the programmer shall follow proper indentations to ensure readability and consistency of the C++ source code.

  2. Block statements shall be indented one indentation level to show scope and structural coherence.

2.5.3.5.7.1  (04-28-2006)
Indentation

  1. Indent the continued part of a statement at least one indentation level beyond the start of the statement.

  2. Indentation shall be performed using spaces instead of tab characters.

  3. Indentation shall be consistent throughout all source files.

2.5.3.5.7.2  (04-28-2006)
Spacing

  1. The '*' and '&' shall be directly connected with the type names in declarations and definitions. I.e., no space shall be placed between the '*' or '&' and the type names in declarations and definitions.

  2. There shall be no spaces between a function name and the left parentheses.

2.5.3.5.7.3  (04-28-2006)
Grouping

  1. Begin each statement on a separate line.

  2. Limit the length of source statements so that complete source statements is visible on the screen without having to scroll right and left repeatedly.

  3. Braces ("{}" ) that enclose a block shall be placed in the same column, on separate lines directly before and after the block.

2.5.3.5.7.4  (04-28-2006)
Includes

  1. Each header file shall #include any other headers on which it directly depends.

  2. #includes shall precede any declarations or definitions in a file.

  3. #include shall not be used to insert executable code into a file or to insert part of a class definition from an external file unless it is required by the use of software developed externally to the project, such as commercial off-the-shelf (COTS) products.

  4. Place #include statements in the following order:

    1. (If a .cpp file) the corresponding header file

    2. System header files

    3. COTS header files

    4. Project specific header files.

2.5.3.5.8  (04-28-2006)
Functions

  1. The section cites standards for Functions and Declarations.

2.5.3.5.8.1  (04-28-2006)
Declarations

  1. Function prototypes and external variables shall be declared in a header file (to avoid multiple declarations), not in implementation files.

2.5.3.5.8.2  (04-28-2006)
Function Parameters

  1. The return type of a function shall always be stated explicitly. Functions that do not return a value shall be declared as void.

  2. Pass parameters in input, modify, output order.

  3. Variable argument lists shall not be used (ellipses notation).

  4. Where the return value from functions are stored for future use, the function invocation shall not be embedded in conditional or other function invocations. Functions may be embedded if return value is only used within that source.

  5. Check the fault codes that may be received from library functions even if these functions seem fool proof.

2.5.3.5.8.3  (04-28-2006)
Function Invocation, Execution, and Return

  1. Do not depend on the order of evaluation of arguments to a function.

  2. Always return a value from main().

  3. For functions with non-void return type, ensure that all paths have a return statement that contains an expression of the return type.

2.5.3.5.9  (04-28-2006)
Error Handling

  1. Error notification, memory cleanup is very important in error-handling situations. The programs need to have a consistent way of handling memory deallocations.

2.5.3.5.9.1  (04-28-2006)
General Error Handling

  1. Calling functions shall check for errors reported from functions

2.5.3.5.9.2  (04-28-2006)
Throwing Exceptions

  1. Do not throw exceptions from within destructors.

  2. Throw only objects of class type.

2.5.3.5.9.3  (04-28-2006)
Handling Exceptions

  1. Avoid memory leaks in exception handling code by using references in parameter lists for exception handlers.

2.5.3.5.10  (04-28-2006)
Expressions

  1. Avoid using shift operations instead of arithmetic operations and validate arguments to be used in shift operators.

2.5.3.5.10.1  (04-28-2006)
Expression Arithmetic

  1. Pointer arithmetic shall not be used.

  2. Do not depend on the behavior of underflow or overflow.

  3. Apply unary minus to operands of signed type only.

2.5.3.5.10.2  (04-28-2006)
Type Conversions

  1. Code shall not depend on implicit type conversions.

  2. The following assignments shall not be used:

    1. Assigning a pointer value to a non-pointer object

    2. Assigning a non-pointer value to a pointer object

    3. Assigning a function-pointer value to a data-pointer object

    4. Assigning a data-pointer value to a function-pointer object

  3. Do not convert floating values to integral types except through use of standard library routines.

2.5.3.5.10.3  (04-28-2006)
Pointers in Expressions

  1. A pointer shall not be compared to NULL or assigned NULL without casting the NULL to the proper type.

2.5.3.5.11  (04-28-2006)
Comments

  1. Use // for in-line comments. Use /* and */ for block comments.

2.5.3.5.12  (04-28-2006)
Memory Management

  1. If a function is returning an allocated object that the caller must free, then the memory for the allocated object shall be documented in the filename.h file as well as in any function comment header block that is used.

  2. When memory allocated to a pointer has been deleted, a new value shall be assigned to the pointer or the pointer should be deleted.

2.5.3.5.12.1  (04-28-2006)
Heap and Stack Memories

  1. Do not allocate dynamic objects contained within other objects as instance data.

  2. Class authors shall provide default values for dynamic objects within other objects and/or constructors that can be used on initializer lists.

2.5.3.5.12.2  (04-28-2006)
Memory Leaks

  1. Save the address of allocated memory to prevent orphaned allocation.

  2. Explicitly deallocate a dynamically allocated segment prior to assigning a new value.

  3. Avoid memory leaks in exception handling code.

  4. Do not use code that can throw an exception in a destructor.

  5. Avoid memory leaks involving external components.

  6. Avoid memory leaks involving reuse of "dead" objects.

  7. Avoid memory leaks by explicitly clearing memory after use.

  8. Avoid memory leaks by unfreezing frozen stream objects.

  9. Avoid memory leaks by ensuring that you write the operator delete whenever the operator new has been written for a class.

2.5.3.5.12.3  (04-28-2006)
Buffers Overflows

  1. The size of an array shall be declared with an enum constant or const. This makes modifying the size of an array easier, and is more meaningful to the reader.

  2. When reading array contents, check to ensure that the index does not exceed the array size.

  3. When adding to an array, check to ensure that the size of the array can hold the existing content in addition to the new contents to be added.

  4. Always test a pointer’s value for NULL before using it.

2.5.3.6  (02-28-2007)
Java Programming

  1. This section of the IRM provides controls to ensure Java programs are reliable, maintainable, and portable.

2.5.3.6.1  (02-28-2007)
File Names

  1. Use the following controls for File names.

2.5.3.6.1.1  (02-28-2007)
File Suffixes

  1. Java Software uses the following file suffixes:

    File Type Suffix
    Java source .java
    Java bytecode .class

2.5.3.6.1.2  (02-28-2007)
Common File Names

  1. Frequently used file names include:

    README The preferred name for the file that summarizes the contents of a particular directory.
    build.xml Default build for Ant.

2.5.3.6.2  (02-28-2007)
File Organization

  1. Use the following controls for File Organization.

2.5.3.6.2.1  (02-28-2007)
General

  1. A file consists of sections, separated by blank lines and an optional comment identifying each section

  2. Avoid files longer than 2000 lines, since they are cumbersome.

2.5.3.6.2.2  (02-28-2007)
Java Source Files

  1. Each Java source file contains a single public class or interface.

  2. When private classes and interfaces are associated with a public class, put them in the same source file as the public class.

  3. Make the public class the first class or interface in the file.

  4. Order Java source files as follows:

    • Beginning comments

    • Package and Import statements

    • Class and interface declarations

2.5.3.6.2.2.1  (02-28-2007)
Beginning Comments

  1. Begin all source files with a C-style comment that lists the class name, version information and date:

    /*

    * ClassName

    *

    * Version information

    *

    * Date

    *

    */

  2. Use available tools to manage version and date information.

2.5.3.6.2.2.2  (02-28-2007)
Package and Import Statements

  1. The first non-comment line of most Java source files is a package statement. After that, import statements can follow. For example:

    package java.awt;

    import java.awt.peer.CanvasPeer;

  2. The first component of a unique package name is always written in all-lowercase ASCII letters and should be one of the top-level domain names, currently com, edu, gov, mil, net, org, or one of the English two-letter codes identifying countries as specified in ISO Standard 3166 of 1981.

  3. Package statements will follow the convention gov.irs.project or gov.irs.program.project as determined by the program or project.

2.5.3.6.3  (02-28-2007)
Indentation

  1. Use the following controls for Indentation.

2.5.3.6.3.1  (02-28-2007)
Line Length

  1. Lines should be broken/ wrapped at column 100 for readability.

  2. Lines longer than 80 characters, while allowed, may affect readability since they are not handled by many terminals and tools.

  3. Examples for use in documentation should have no more than 70 characters.

2.5.3.6.3.2  (02-28-2007)
Wrapping Lines

  1. When an expression will not fit on a single line, break it according to these general principles:

    • Break after a comma.

    • Break before an operator.

    • Prefer higher-level breaks to lower-level breaks

    • Align the new line with the beginning of the expression at the same level on the previous line.

    • Indent four spaces if these rules lead to confusing code or to code that's squished up against the right margin.

  2. How to break the lines of method

    someMethod(longExpression1, longExpression2, longExpression3,

    longExpression4, longExpression5);

    var = someMethod1(longExpression1,

    someMethod2(longExpression2,

    longExpression3));

  3. How to break an arithmetic expression. The first example is preferred, since the break occurs outside the parenthesized expression, which is at a higher level.

    longName1 = longName2 * (longName3 + longName4 - longName5)
    + 4 * longname6; // PREFER
    longName1 = longName2 * (longName3 + longName4  
    - longName5) + 4 * longname6; // AVOID

  4. How to indent method declarations. The first example follows the conventional practice. The second indents 4 spaces because the conventional indentation would shift the second and third lines too far to the right.

    //Conventional Indentation.  
    someMethod(int anArg, Object anotherArg, String yetAnotherArg,  
    Object andStillAnother) {  
    ...  
    }  

    //Indent 4 Spaces To Avoid Deep Indents

    private static synchronized workingLongMethodName(int anArg,

    Object anotherArg, String yetAnotherArg,

    Object andStillAnother) {

    ...

    }

  5. Line wrapping of If statements should generally use the 4-space rule, making it easier to see the body of the statement. For example:

    //Use this indentation

    if ((condition1 && condition2)

    || (condition3 && condition4)

    ||!(condition5 && condition6)) {

    doSomethingAboutIt();

    }

    //Or use this

    if ((condition1 && condition2) || (condition3 && condition4)

    ||!(condition5 && condition6)) {

    doSomethingAboutIt();

    }

  6. Here are three acceptable ways to format ternary expressions:

    alpha = (aLongBooleanExpression) ? beta : gamma;
    alpha = aLongBooleanExpression) ? beta
        : gamma;
    alpha = aLongBooleanExpression)  
      ? beta  
      : gamma;  

2.5.3.6.4  (02-28-2007)
Comments

  1. Java programs can have two kinds of comments: implementation comments and documentation comments.

2.5.3.6.4.1  (02-28-2007)
Implementation Comments

  1. Implementation comments are like those found in C++, which are delimited by /*...*/, and //.

  2. Implementation comments are meant for commenting out code or for comments about the particular implementation.

2.5.3.6.4.1.1  (02-28-2007)
Implementation Comment Formats

  1. There are four types of implementation comments: block, single-line, trailing, end-of-line.

2.5.3.6.4.1.1.1  (02-28-2007)
Block Comments

  1. Use Block Comments to provide descriptions of files, methods, data structures and algorithms. Block comments inside a function or method should be indented to the same level as the code they describe.

  2. Block Comments may be placed at the beginning of each file, before each method, or immediately after the imports.

  3. Precede a block comment with a blank line to set it apart from the rest of the code.

    /*

    * Here is a block comment.

    */

  4. Block comments can start with /*-For example:

    /*-

    * Here is a block comment

    * one

    * two

    * three

    */

2.5.3.6.4.1.1.2  (02-28-2007)
Single-Line Comments

  1. Place short comments on a single line indented to the level of the code that follows.

  2. Precede a single line comment with a blank line. Here is an example of a single-line comment in Java code:

    if (condition) {
      // Handle the condition.
      ...
    }  


More Internal Revenue Manual