coding_standards

Coding Standards

Introduction :

A coding standard is a set of guidelines and best practices that help ensure code consistency, readability, and maintainability across a development team or organization. It defines the conventions for writing code, including aspects such as naming conventions, indentation, comments, file structure, and error handling. By adhering to a coding standard, developers can collaborate more effectively, reduce the likelihood of introducing bugs, and improve the overall quality of the software. Coding standards also facilitate onboarding new team members and make it easier to review, maintain, and scale projects over time.

File Header Comment Block:

The file starts with a detailed comment header, specifying copyright information, licensing details, and legal disclaimers.
The header includes details about the ownership, permissions, and terms of use.

Source files:

Source files contain the body of the code for a given module, and can be broken down into parts, which must appear in the following sequence:

  • Module-level documentation block – Provides detailed documentation about the module, its purpose, and usage.
  • Global imports – All external module imports should be placed at the top, ensuring dependencies are clearly.
  • Pre-processor - Use #define for defining any contsant in the code.
  • Constant declarations – Use the const keyword for defining constant values that will be shared across multiple modules.
  • Global variable declarations – Variables that need to be shared across different modules should be declared with clear and descriptive names.
  • Static constant declarations – These constants are restricted to the local module and should be defined using the static const keyword.
  • Static function declarations – Functions that are only accessible within the same file should be declared static and placed before the implementation of the functions that call them.
  • Private class or structure declarations – Classes or structures that are only used within this file should be defined as private or static, depending on the language and requirements.
  • Implementation of public methods – Methods or functions that are part of the global API for the module must be clearly documented and follow naming conventions.
  • Implementation of private methods – Private methods, defined at the bottom of the source file, should follow the same documentation and structure as public methods but are restricted to internal use only.

Include files:

Include Guards:

The file uses include guards to prevent multiple inclusions of the header (ex: #ifndef __ATSC_TYPES_H__, #define __ATSC_TYPES_H__, #endif). This is a standard practice to ensure the file is included only once during compilation.

Library Inclusions:

Necessary standard libraries are included at the top of the file (e.g, inttypes.h, stdio.h, unistd.h), ensuring that dependencies are explicitly declared. Local module-specific headers are also included.

Macro Definitions:

Several #define pre-processor directives are used to define constants and strings .Each macro is preceded by a brief comment explaining its purpose.

Detailed Function Documentation:

Functionality, constants, and macros are documented using comment blocks, ensuring clarity about their usage.

Consistency in Naming Conventions:

All macro names are written in uppercase and follow a consistent naming convention, typically starting with the ATSCCORE_ prefix to indicate they are part of the ATSC core.

Separation of Declarations and Definitions:

Header files are used exclusively for declarations, ensuring that the implementation (definitions) resides in the corresponding source files.

File inclusions:

When including files in a source file, it is essential to maintain a logical and consistent ordering to enhance readability and avoid potential conflicts. The inclusion of files should follow these guidelines:

  • System and Standard Library Inclusions: Files that are part of the standard library or relate to system-level functionality should be included first. These files are enclosed within angle brackets (< >) and provide the necessary base functionality (e.g., threading, I/O, memory management). They must always appear at the beginning of the inclusion block to make dependencies clear and prevent issues during compilation.
  • Third-party Library Inclusions: If the project depends on any external or third-party libraries, these should be included immediately after the standard system headers. These are typically enclosed within quotes or angle brackets depending on the library type and its installation method.
  • Project-specific Inclusions: Project-specific header files should follow the system and third-party headers. These headers are enclosed within quotes (" ") and represent the internal components of the project, such as module-level or functionality-specific headers. These should be grouped logically by functionality, helping future maintainers quickly identify related modules.

Function layout:

Comment Header:

Before the function definition, there should be a comprehensive comment header that explains the purpose of the function, parameters, and return value. It should also include any preconditions, assumptions, or notable behaviors.

Function Definition:

The function definition matches the pre-defined prototype, with clearly named parameters in the parenthesis. If the function had no parameters, the void keyword would be explicitly declared.

Static Variable Definitions:

If any static variables were required, they would be defined here at the top of the function and initialized as necessary. Static variables would emphasize the impact on memory usage.

Automatic Variable Definitions:
  • All local variables are declared at the start of the function, promoting clarity. Grouping similar type variables together.
  • Variable initialization is performed where appropriate.
  • Unused variables are safely cast to void to prevent warnings, as shown by (void)(iVersion);
Code Body:
  • Complex sections of the code body should be supplemented with clear, concise comments, explaining the purpose of each step.
  • Modular and Reusable: The code body should aim to encapsulate logic into modular, reusable blocks where possible. This helps in maintaining and testing smaller sections of code individually, promoting readability and scalability.
Error Handling and Early Exits:

Error conditions should handled properly, with error flags or early exits. The function avoids the use of multiple return points, adhering to the standard of having a single exit point.

Call to Return:

The function concludes with a single return statement, adhering to the standard of avoiding multiple exit points. The return value is 0, signaling successful execution. Any error flags or conditions(eATSCResult_t) would have been handled earlier in the function without disrupting the flow.

Variable names:

Prefix Conventions:

Variables are prefixed to indicate their type or purpose:

  • i: For integer values (e.g., iMessageId ). This is a common convention that makes it immediately clear that the variable stores an integer.

  • p: For pointers (e.g., pData). This prefix makes it evident that the variable holds an address to a data buffer.

  • s: For string or character arrays (e.g., sMsgData), making it easier to distinguish arrays from other variable types.

  • ll: For long long or 64-bit integer types (e.g., llDstLen), denoting larger integers or specific memory sizes.

  • c : For character variable

  • b : For boolean flags

  • f : For Float variables.

  • d : for Double variable.

  • m : Class member variables.

Descriptive and Meaningful Names:

Variables are given descriptive names that convey their purpose and role within the function, improving readability:
Ex: iMessageId: This stores the message identifier, clearly indicating its purpose.

Grouping and Consistency:

Variables are grouped based on related functionality.
Ex:Timestamp-related variables use a common prefix (iTimestampSec, iTimestampFrac, etc.), creating consistency in the code.

CamelCase for Multi-word Names:

Variables with multi-word names follow the camelCase convention, where each word starts with a capital letter, making them easy to read:
Ex: iAtsc3MessageContentVersion

Structure Definition:

Structure Comment Header:

A comment header is provided at the top of the structure, briefly explaining the purpose of the structure. According to coding standards, the comment should provide a more detailed description of the structure’s role, its members, and how it is used.

Member Comments:

Each member of the structure has a corresponding comment that explains its purpose. The comments use the /**< Example > format and provide a clear, concise description.

Data Type Consistency:

The structure uses consistent data types such as int32_t and uint32_t, adhering to the standard practice of using fixed-width integer types to ensure portability across platforms.
The use of int32_t and uint32_t also ensures that developers are aware of the size and range of the variables, which is especially useful when dealing with cross-platform compatibility.

Grouping Related Variables:

Grouping related variables improves readability and helps maintain a logical flow within the structure.

Structure Typedef:

The structure uses a typedef to define a convenient alias, which simplifies the use of the structure in the rest of the code.

Enum:

Naming Conventions:

Ex : The enum name eATSCResult_t follows a consistent and descriptive naming convention:

  • e: Prefix indicating that the type is an enumeration.
  • ATSC: Identifies that the enumeration is related to ATSC (Advanced Television Systems Committee).
  • Result: Provides context that the enumeration is used for result or return values.
  • _t: Standard suffix used to indicate that this is a typedef type.
    - Comments for each Enum Value:
    Each enum value is followed by a comment explaining its meaning. While the comments are brief, they serve as helpful reminders for developers and improve code clarity.

Page Tools