Open Source RDBMS - Seamless, Scalable, Stable and Free

한국어 | Login |Register

CUBRID Coding Conventions

Table of Contents

1. Introduction

This chapter describes the need for CUBRID coding conventions, and elements and terms of coding conventions.

1.1 Need for Coding Convention

A large amount of maintenance cost is required throughout the software lifecycle. In addition, it is unlikely that the original developer of source code continues to maintain it for the whole lifecycle. Therefore, writing the source code in a way a person other than the original developer can understand it quickly and accurately is essential in reducing source code maintenance cost and increasing job efficiency.

With its high readability, source code written according to coding conventions helps developers to understand it quickly and accurately. This also makes easier to share them among project members and possible to produce a consistent source code appearance.

1.2 Basic Rules

Basically, CUBRID adopts “GNU Coding Standards” and “C Style and Coding Standards for SunOS” as its coding guide. It only uses basic features of the C/C++ language (compiler); it is not recommended to use techniques that are not used commonly.

GNU Coding Standards
http://www.gnu.org/prep/standards/standards.pdf

SunOS Coding Standards
http://opensolaris.org/os/community/on/cstyle.ms.pdf

This document describes a part to emphasize or additionally defined rules in the above guide.

1.3 Elements of Coding Conventions

1.3.1 Commenting Rules

Implementation Comment

Implementation comments describe implementation details or additional explanations, not source code specifications.

Documentation Comment

Documentation comments describe source code specifications. Developers can understand source codes through documentation comments.

1.3.2 Naming Rules

Naming rules are used to write names of functions and variables. These names should be descriptive enough to easily tell developers the source code structure.

1.3.3 Coding Rules

Indentation

Indentation is used to improve the readability of statements; programmers indent a certain amount of spaces from the first column on the left to the column on the right. It shows inclusion relationships between statements and blocks so that developers can easily understand the source code structure

Brace

Braces are used to indicate declarations and blocks. They show inclusion relationships between declarations, blocks and body.

White Space

White spaces are used to improve the readability of the source code. Using unnecessary braces or not using them where they are needed decreases the readability.

1.4 Terms of Coding Conventions

1.4.1 Syntax Terms

Variables

A variable is a space in memory where the state of an object or data is stored. It is defined by ANSI as follows:

“A character or a set of characters that represents a value for writing a program. It corresponds to an address in computer programming.”

Operators

An operator is a special symbol which is used to execute operations.

Expressions

An expression is an arithmetic or logical expression that returns a single value by using variables, operators and function calls.

Statements

A statement is a unit of execution, which is represented as an expression or a control flow statement.

Blocks

A block is an area between a pair of braces. Usually a block contains one or more statements, but it may not contain any in some cases.

Control Flow Statements

A control flow statement is a statement that controls the program flow.

Declarations

A declaration is used to define names and types of variables/functions, and return values, arguments and bodies of functions.

2.Naming Rules

This chapter describes naming rules.

2.1 Common Naming Rules

A. Using lowercase characters

There are some exceptions, but use lowercase characters for naming.

B. Avoiding the use of single-character names

Single-character names are unable to represent their meaning clearly, thus increase the possibility of errors because it is difficult to remember them. However, single-character names can be used as variable names in iterative statements; it is not recommended to use them if you can define a specific meaning.

C. Using underscores ("_")

Use underscores (“_”) to separate words.

D. Choosing words

The choice of words should be consistent as much as possible. For similar words such as add/insert, store/save/put, remove/delete, for example, use one of them consistently.

E. Avoiding use of abbreviations

For file, function, variable and constant names, use full names, not abbreviations. For example, use print_value or initialize_parameters instead of prt_val or init_params. However, commonly-known abbreviations and the ones frequently used as local variable names are allowed.

[Table 2-1] Example of Using Abbreviations

Item

Example

Bad example

prt_val, init_params

Good example

print_value, initialize_parameters

[Table 2-2] Example of Available Abbreviations

Available Abbreviations

min, max

F. Avoiding the use of negative Boolean names

Negative Boolean names represent double negative, making difficult to be understood. Therefore, use positive Boolean names.

[Table 2-3] Example of Using Boolean Names

Item

Example

Bad example

is_not_available

Good example

is_available

G. Observing simplicity and clarity

Use simple and clear names for files, functions, variables and constants so that they can represent their roles and purposes. It is recommended to use nouns with adjectives.

H. Observing English Word Order

Observe English word order when you create a name by combining multiple words. The following word order is recommended.

  • Verb + Object.
  • Subject + Verb + Object
  • Subject + Verb
  • djective + Noun

More accurate conventions are described in the detailed naming rules for functions and variables.

[Table 2-4] Example of English Word Order

Item

Example

Bad example

date_check

Good example

check_date

2.2 File Names

A. Using descriptive file names

Use descriptive file names that note the contents of the file.

B. Avoiding the use of duplicate file names

Do not use duplicate file names in the same project.

C. Avoiding the use of special characters

Do not use special characters other than underscores ("_").

D. Using lowercase alphabets

Use lowercase alphabets to create file names; use underscores ("_") between words.

E. Using prefixes

Use sub-system names as prefixes to create file names systematically. However, a prefix is not used for the name of a file which constitutes a common module.

[Table 2-5] Example of File Names

Item

Example

Example of using a prefix

connection_list_sr.c

Example of a common module

tcp.c

F. Using unique names

Do not use name that are likely to be duplicated; use unique names.

[Table 2-6] Example of Unique Names

Item

Example

Bad example

evaluator.c

Good example

query_evaluator.c

G. File Extension Rules

Comply with the rules described in Chapter 2 of SunOS Guide.

[Table 2-7] File Extension Rules

File

Extension

C source file

.c

Assembly source file

.s

Object file

.o

Header file

.h

Archive library file

.a

C shell source file

.csh

Bourne shell source file

.sh

ANTLR grammar file

.g

Yacc source file

.y

Lex source file

.l

2.3 Function Names

Use prefix_verb_noun(_suffix) format for a function name. For a prefix, use an abbreviation that represents a corresponding module.

For a function name, use a verb to say what a function does. Start a function name with the "get_" prefix if the function is a get that reads data. Start a function name with the "set_" prefix if the function is a set that sets data. Use a verb such as "is_" or "has_" for a function that returns a Boolean type.

[Table 2-7] Example of Function Names

Item

Example

Example

qdump_print_xasl_type

2.4 Variable and Constant Names

Names of variables and constants have prefix_noun(_suffix) format; adjective or adverb can be used. A compound noun such as noun+noun+noun format can be also used. For a prefix, a module name is used.

A. Global Variable Names

Use an uppercase character only for the first one after a prefix. For example, prm_Parameter_definition. This also applies to static global variables.

B. Local Variable Names

Do not use a prefix and use a simple name. More abbreviations are allowed for local variable names. However, if there are more appropriate ones than a, b, c or i, j, k, use them. For example, use a self-explanatory name that delivers meaning such as first_param. For a pointer variable, use "_p" as a suffix.

C. Constant Names

Use uppercase characters such as PRM_QUERY_CACHE_OPTION for a constant name.

D. Macro Names

As a constant-like global variable, use uppercase characters for a macro name that is defined with #define. However, when defining a constant, it is recommended to use a variable that include "const" rather than using a macro definition.

2.5 Type Names

A. Type, Struct and Enum Names

Use only lowercase characters for type, struct and enum names; only uppercase characters for typedef names. Do not use a suffix such as _t for a type name.

[Table 2-8]Example of Type, Struct, Enum and Typedef Names

Item

Example

typedef

typedef SCAN_CODE

struct

struct log_2pc_coordinator

enum

enum log_flush

B. Struct Member Name

Use only lowercase characters; do not use a prefix.

C. Function Parameter Names

Create a function parameter name in the same way as described in Local Variables.

This chapter describes coding rules..

3.Coding Rules

3.1 Indentation

A. Observing tab spacing

Use GNU indent without an option. Note that the indent program does not perfectly process #if/#else/#endif of cpp.

[Code 3-1] Example of Indentation
static bool qdump_print_db_value_array (DB_VALUE ** array_p, int count)
{
	int i;

	if (array_p == NULL)
	{
		return true;
	}
 
	for (i = 0; i < count; i++, array_p++)
    {
		if (!qdump_print_db_value (*array_p))
        {
			return false;
        }
		
		fprintf (foutput, "; ");
    }
 
	return true;
}

B. Observing indentation of enum definition

When you define an enumeration type value, write each item on a new line with indentatio.

[Code 3-2] Example of Indentation of enum Definition
typedef enum
{
	LC_OBJECT = 0,              /* Don't know if it is an instance or a class */
	LC_CLASS,                   /* A class  */
	LC_INSTANCE                 /* An instance  */
} LC_OBJTYPE;

C. Observing indentation of function parameters

When you define a function, if it cannot be defined in a single line because there are too many input parameters, move the last parameter in the line to the next line. Set the indentation of parameters in the next line to the column where the first parameter begins.

[Code 3-3] Example of Indentation of Function Definition Parameters
static void rop_to_range (RANGE * range, ROP_TYPE left, ROP_TYPE right);
static void range_to_rop (ROP_TYPE * left, ROP_TYPE * rightk, RANGE range);
static ROP_TYPE compare_val_op (DB_VALUE * val1, ROP_TYPE op1,
DB_VALUE * val2, ROP_TYPE op2);

D. Observing indentation of function use parameters

When you define a function, if it cannot be defined in a single line because there are too many input parameters, move the last parameter in the line to the next line. Set the indentation of parameters in the next line to the column where the first parameter begins.

[Code 3-4] Example of Indentation of Function Use Parameters
/* check if the two key ranges are mergable */
if (compare_val_op (&curp->key2, cur_op2,
	&nextp->key1, next_op1) == ROP_LT ||
	compare_val_op (&curp->key1, cur_op1,
	&nextp->key2, next_op2) == ROP_GT)
    {
		/* they are disjoint */
		nextp++;
		next_n++;
		continue;
	}

E. Observing indentation of logical expressions

If a condition statement consisting of multiple logical operators, and they cannot be written in a single line, break up the logical expression into multiple lines. Place one logical operator per line, or combine multiple operators based on logical operation order.

If the line break is based on logical operators, indent a line by a tab from the column where the first logical expression started, beginning from the second line.

[Code 3-5] Example of Indentation of Logical Expressions
if ((s_id->direction == S_FORWARD && s_id->position == S_BEFORE)
    || (!BTREE_END_OF_SCAN (&s_id->s.isid.bt_scan)
    || s_id->s.isid.indx_info->range_type == R_KEYLIST
    || s_id->s.isid.indx_info->range_type == R_RANGELIST))

3.2 Others

A. Adding blanks

Place a space between words, before and after an operator, and after punctuation marks (e.g. comma, colon, etc.). However, spacing may not be required when unary operators are used. In addition, the last line should not be blank.

B. Using spaces for blanks

Except for a tab that is created by indentation, use a space for a blank instead of a tab.

C. Priority

When you write an expression, use parentheses to clearly specify the order of operations if multiple operators are used.

[Code 3-6] Example of Priority
a = k * ((b + c) / d);

D. Number of columns

Write source code within 80 columns. If a comment is long, arrange it appropriately (see the Comments section).

E. Blocks

A brace and a control statement must be written on separate lines.

[Code 3-7] Example of Blocks
switch (last_scan_p->position)
{
	case S_BEFORE:
		status = qfile_scan_list_next (thread_p, next_scan_p, next_tuple_p, PEEK);
		break;

	case S_ON:
		do
		{
			status = qfile_scan_list_next (thread_p, next_scan_p, next_tuple_p, PEEK);
			
			if (status != S_SUCCESS)
			{
				break;
			}

			error_code = qfile_compare_tuple_helper (last_tuple_p->tpl,
												next_tuple_p->tpl,
												types, &cmp);
		}
		
		while (error_code == NO_ERROR && cmp == 0);
		break;

	case S_AFTER:
	default:
		status = S_END;
		break;
}

4. Commenting Rules

 

This chapter describes commenting rules.

 

4.1 Common Rules

Comments are used to improve understanding of source code by providing brief explanation or describing additional information that cannot be delivered just with the code.

A. Basic rules

  • All comments must be written in English.
  • Simple comments: Complicated comments are difficult to read and to modify, increasing the possibility that improper comments are left as they are. Therefore, write simple comments only with necessary contents.

B. Source code that does not need comments

?Comments are not needed if you can clearly understand only by reading source code.

?Do not write comments about packaging or build. (e.g. directory information to be located)

?Do not write comments about source code developers or revision history. To provide this information, use a logging feature of the configuration management system.

There are three formats of comments: block comments, single-line comments and trailing comments. In terms of usage, there are file comments, function comments, variable comments, etc.

4.2 How to Write Different Formats of Comments

A. Block Comments

This format is used when comments are written in multiple lines. There are two types as shown below.

[Code 4-1] Example of Comments at the Top of the Code
/*
* This comment lines are too long to write within one line.
* So, you can choose proper style like this. It is up to you.
* GNU indent will not violate this style of comment.
*/
[Code 4-2] Comments within the Code
/* Nonzero means truncate lines in the display;
zero means continue them. */

This format with * in every line is used to write comments at the top of the code, such as file comments and function comments.

For comments within the code, start with /*, do not use * when a line changes and end with */ according to the GNU definition. In addition, use the same indentation as the code.

B. Single-line comments

For a single-line comment, write comments in the following format.

[Code 4-3] Example of Single-Line Comments
/* codes to be used in the module */

C. Trailing Comments

This format is used to add a short comment beside the code.

[Code 4-4] Example of Trailing Comments
int trail_file_vdes = 0;      /* the trail log file descriptor */

4.3 How to Write Different Usage of Comments

Write comments at the top of the code for declaration and definition (e.g. function, variable and type); write comments at the end of the code for struct members or local variables. Make sure that comments at the end of the code do not go over the next line.

A. File comments

File comments are written in the following format. The copyright statement is followed by the GPL license statement.

[Code 4-5] Example of File Comments
/*
 * Copyright (C) 2008 Search Solution Corporation. All rights reserved by Search Solution.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */
 
/*
 * list_file.c - Query List File Manager
 */
 
#ident "$Id$"

B. Function comments

Function comments are written in the block comment format. The first line describes brief information about a function, and the second line describes a value that the function returns. The third line and the rest lines describe the parameters of the function. Specify in, out, or on/out for each parameter. After the parameter description, add brief information that can help improve understanding of the function.

[Code 4-6] Example of Function Comments
/*
 * qfile_copy_list_id - Copy contents of source list_id into destionation list_id
 *  return: NO_ERROR or ER_FAILED
 *  dest_list_id(out): destination list_id
 *  src_list_id(in): source list_id
 *  include_sort_list(in):
 */
int
qfile_copy_list_id (QFILE_LIST_ID * dest_list_id_p,
                   const QFILE_LIST_ID * src_list_id_p,
                   bool is_include_sort_list)

C. Variable comments

Comments are written for static variable declaration in the following format (see the GNU coding guide).

[Code 4-7] Example of Variable Comments
/* Nonsero means truncate lines in the display;
zero means continue them. */
int truncate_lines;

D. Type/struct comments

Comments with the format /* … */ are also used for struct, enum and typedef. In addition, write comments for a condition after #else and #endif (see the GNU Standard).

[Code 4-8] Example of #ifdef Comments
#ifdef foo
…
#else /* not foo */
…
#endif /* not foo */
#ifdef foo
#endif /* foo */
 
#ifndef foo
…
#else /* foo */
..
#endif /* foo */
 
#ifndef foo
…
#endif /* foo */

5. Rules for Declarations and Definitions

 

This chapter describes functions/variable declarations, common type definitions, initialization and using macros.

 

5.1 Function Declaration and Writing

For the naming rules of functions and parameters, see Chapter 2. Naming Rules; for the commenting rules, see Chapter 4. Commenting Rules.

A. Observing simplicity and clarity

Write simple and clear functions. Long functions decrease readability and make maintenance difficult. It is recommended that the length of a function do not exceed 200 lines.

B. Observing the one-task-per-function rule

Implement a function so that it performs only one task. A function performing multiple tasks is difficult to understand because it decreases simplicity and clarity. Non-intuitive functions are likely to generate errors. Therefore, implement a function that performs a single task.

C. Function declaration rules

Do not use old declarations such as INTERFACE, PUBLIC, or PRIVATE; instead, only static and extern should be used. In addition, function declarations must be included in a header file (.h) and source file (.c). Even for a static function, function declaration must be included at the beginning of a source file. Use an appropriate header file in a source file instead of declaring an external function with extern rather than #include.

D. Validating input parameters

Write code that checks the validity of input parameters passed into the function.

E. Parameter declaration rules

Basically, declare function parameters in the order of out, in/out, and in. However, parameters that are frequently used throughout a module and passed like the keyword "this" of C++ (e.g. PT_PARSER parser, etc.) must be located at the beginning. For input parameters, use the const specifier. And use a pointer every place where const is required, such as const char * const in_p.

F. Function return value rules

Basically, create a function that can return an error code. If it is more significant to return a pointer value as void *malloc() or char *strcpy(), create a function that accepts an error code as an output parameter. That is, every function must return an error code in general. Only when a function is clear, it can return 0 or NULL. For example, int (*compar)(const void *, const void *) in qsort() returns a specific value instead of an error code.

Error codes are negative numbers, but NO_ERROR is 0 exceptionally. Basically, an error code means ER_XXXX_XXXX (a global error code) defined in dber.h. If it is necessary to define its own code in a module or function due to a program structure, define the code by using enum in a header file. In this case, use a negative number for an error. If it is not an error, use 0. That is, make the following statement become TRUE in most cases.

[Code 5-1] Example of Error Processing
if (xx_function() < 0)
if (xx_function() != NO_ERROR)

Although an error code is defined as DB_ERROR type, typedef is not used to define it in the code. (NO_ERROR is defined as 0.) Therefore, most functions have int as a return type. If the result of a function is positive number, it is a result of the function. If it is a negative number, it is one of error codes defined in DB_ERROR. If there is a function whose return type is DB_BOOL in the code, change its return type to int and make it return an appropriate error code.

When a function is called, perform an error checking for the result value. Even when the called function always return the same value, you must check the result value if the function is designed to return an error code according to its definition. In addition, checking result values must be performed after calling system functions. Especially, an error checking must be performed for malloc(). And make sure that exceptions are handled appropriately.

5.2 Variable Declarations

For the naming rules of variables, see Chapter 2. Naming Rules; for the commenting rules, see Chapter 4. Commenting Rules.

5.3 Common Type Declaration

If you want to use typedef for struct/enum, declare typedef first. If names are not specified in struct/enum, process them at once as follows:

[Code 5-2] Example of Defining Common Types without Specifying Names
typedef enum
{
    FALSE = 0,
    TRUE = 0
} bool;

5.4 Constant Declarations

Place a constant defined by #define within a block by using parentheses if the constant contains an expression. By doing so, you can prevent operation priority issues. However, #define is replaced during compilation and the name is not displayed in the symbol table, making debugging difficult. Therefore, use enum and const instead of #define when you declare a constant. The first element of enum must be set to 0.

[Code 5-3] Bad Example of Processing Constants
#define MAX_SPEED 256
[Code 5-4] Good Example of Processing Constants
typedef enum
{
	LC_OBJECT = 0,              /* Don't know if it is an instance or a class */
	LC_CLASS,                   /* A class  */
	LC_INSTANCE                 /* An instance  */
} LC_OBJTYPE;

6. Rules for Expressions and Statements

This chapter describes rules for writing expressions and statements.

These rules correspond to the SunOS Guide (see Chapter 9, Chapter 15, and Chapter 17).

  • Chapter 9: Statements
  • Chapter 15: Goto
  • Chapter 17: Multiple Assignments

This chapter describes how to write file configuration and information.

7. File Configuration and Information

7.1 Program Configuration

These rules correspond to the SunOS Guide.

  • Chapter 3 Program Organization

7.2 File Configuration

These rules correspond to the SunOS Guide.

  • Chapter 4: File Organization

7.3 Header Files

The structure of the header file (.h) is described below.

1. Copyright statement

2. Comments that describe the file contents, if necessary

3. Include checking with #ifndef

4. #ident line

5. #include other header files (system header first)

6. Repeat the followings in meaningful units

  • #define, etc.
  • typedef definition
  • strcut, enum definition
  • extern global variable declaration
  • extern function declaration

[Code 7-1] Example of Header File
/*
 * Copyright (C) 2008 Search Solution Corporation.
* All rights reserved by Search Solution.
 *
 * This program is free software;
* you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street,Fifth Floor,Boston,MA 02110-1301 USA
 *
 */
 
/*
 * hdr.h - Brief description of this file as one sentence
 *
 * Note: if you feel the need
 */
 
#ifndef _HDR_H_
#define _HDR_H_
 
#ident "$Id$"
 
/* Explain main concept or logic of your code
   contained in this file if possible */
 
#include "other.h"
 
#define DEFINE define
 
typedef strcut record RECORD;
 
/* codes to be used in the module */
enum code { CODE1, CODE2, CODE3 };
/* … */
struct record {
  int no;
size_t size;
};
 
/* … */
extern int hdr_Global_variable;
 
/* … */
extern int hdr_process_line(char *line, int line_no);
extern int hrd_end_of_processing(const char *line);
 
#endif _HDR_H_

7.4 Source Files

The structure of the source file (.c) is described below.

1. Copyright statement

2. #ident line

3. Comments that describes the file contents, if necessary

4. #include header file (system header first)

5. You can write the followings in meaning units.

  • #define, etc.
  • typedef definition
  • strcut, enum definition
  • static variables definition
  • static function declaration
  • function definition (execution code)

Here, it is not recommended to place struct far way from a related typedef; declarations must be grouped in the same place. In addition, if there is #define that is only used for a specific function, it can be used at the beginning of the function or within the function.

The following formats used in the old file structure should not be used.

/***** IMPORTED DECLARATIONS*****/

/***** PUBLIC DEFINES *****/

/***** PUBLIC TYPEDEFS*****/

/****** PRIVATE DECLARATIONS *****/

8.Compatibility

This chapter describes how to implement compatibility.

A. Using compatibility related types

Do not use int instead of size_t or off_t that is available in the C library. If necessary, use int32_t or uint32_t. The recommended basic types are defined in the config.h. The types defined in dbport.h (e.g. DB_INT32 or DB_BOOL) must be used mostly for API.

B. Others

The additional information regarding compatibility corresponds to the SunOS Guide.

  • Chapter 20: Portability

9. Security

This chapter describes how to implement security code.

9.1 Assertion

Use assert() appropriately in the code after #include assert.h. Do not use it frequently and try to avoid calling other functions in the assert expression. The most recommended types are as follows:

  • Checking whether a parameter of a function is valid
  • Warning risks in advance
  • Verifying a return value at the end of a function as a unit test

10. Other Rules

This chapter describes other rules to comply with.

  • Delete the extern "C" part.
  • Do not use inline or register.
  • Use volatile only for very sensitive parts.
  • After coding, use the GNU indent to align the indentation.
  • There must be no warning by compiling with the following option in the gcc:
    -all -extra -missing-prototypes -redundant-decls -long-long
  • Check the code by using splint if the compiling is successful.




You are either using a very old browser or a browser that is not supported.
In order to browse cubrid.org you need to have one of the following browsers:



Internet Explorer: Mozilla Firefox: Google Chrome: