Download as pdf or txt
Download as pdf or txt
You are on page 1of 19

Source Code Conventions

Code Structure
Integrated Development Environment (IDE) options and settings
Statements
Block Indentation
Operators
Conditional operator (if-else)
Multi-case Conditional operator (switch)
Loop operator (while, do-while)
Loop statements (for)
Boolean Statements in operators
Clauses and declarations
Constants
Variables
Braces
Method Declaration
Method definition
Return Statements
Exception Handling
Method calling
Comments
Documentation Comments
Class description block
Method description block
Property description block
Demandware script description block
Tags description
Pipeline description block
Implementation Comments
Comments around large blocks of code
Commented code
Useless comments

This guideline includes some rules for code structure display, operators’ syntax and blocks ordering as well as syntax and code style for source
code clauses and declarations.

Code Structure
Integrated Development Environment (IDE) options and settings
It is strongly recommended for the developers to use common rules of IDE settings and code style. This is very useful for people, who work in
team and often exchange some experience and consult each other on their workstations.

The developers in one team should use common IDE settings (including coloring and short-keys) and each developer should adopt his/her habits
to the common working environment defined. Team members should feel comfortable on their team mates IDE. For this reasons, the following
rules below should be applied on each developer’s IDE:

Source code should always be viewed in fixed font style (Courier like font)
Max line size should be defined where applicable. Most of the IDEs support a markup vertical line, which can be calibrated. Source code
line should not exceed 120 characters (with the block indentation, counted as 4 characters).
Tab size must be set to 4 spaces. This setting is available as an IDE option.

Statements
Statements are building blocks of the program source code. They should be as simple as possible, easy readable, clear and understood between
all members of the team. By following these guidelines, current standard introduces list of rules for statement creation and usage, presented
below:

Statements should be simple and readable


Write only one statement per line
Complex long statements should be decomposed on smaller, clearer statements
Long statements should be broken in several lines
Statements should be grouped in semantic blocks, separated with white space lines
Separate operators and identifiers are with space where necessary for better readability
Do not use functions or complex statements within functions, since this would make it hard for code debugging. Create variables for
storing functions’ result in order to inspect them easier during debugging process.
Always use braces in order to point out the precedence in complex statements. Do not rely on operator precedence at all. Braces make
the reading process easier.
If the computed expression is long or the operands count exceeds 5, the expression should be divide in two or more parts, each on
separate line. The horizontal alignment of the following lines is according to the first operand and must start with operator.
Do not use embedded assignments

Example: Good and bad practice for simple statements declaration

j = j + 1; k = k – 1 -j; //WRONG: Do not use 2 statements in one row

sum[i]=sum[i]*2.0+salary/days/hours; //WRONG: Not clear enough

d = (a = b + c) + r; //WRONG: Nested assignment statements

a = b + c; //CORRECT: Statements are separated


d = a + r;

sum[i] = sum[i] * 2.0 + salary / (days * hours); //CORRECT: Brackets added

//CORRECT: Long statement separated in two lines


sum[i] = sum[i] * 2.0 + salary / (days * hours) + oldAmount
+ baselineAmmount * efficiencyRate + riskAmount * riskRate;

Example: Logic statements block separation

PersonA.setSalary(1000); // block 1: modifying Person A data


PersonA.setJobcode(5);
PersonA.commit();
// empty line for separator
Transaction.commit(); // block 2: committing the transaction

Example: Declarations code style


...
// short assignment statement
var size : Number = list.size();
...

// long assignment statement


var expr : Number = operator1 * operator2 * operator3
+ (operator4 / operator5);

// long assignment statement with method calling


var test : Number = obj.method(param1,
param2,
param3,
param4,
param5);

// short assignment statement with method calling


var test : Number = coef * obj.method(param1, param2);

// long assignment statement with method calling


var test : Number = (coef * obj.method(param1, param2)
* method1()) - method2(param);

Block Indentation
Block statement is represented by opening '{' and closing '}' brackets in the C-style languages.

For function declarations indentation style, known as “Align brackets”, is used. It uses following rules for block indentation:

Opening and closing brackets are indented always on the same vertical line
Lines with brackets do not contain any statements
Statements within the block are indented with one tab

For all other block declarations opening bracket is at the end of the previous line.

Example: Block indentation

1234567890123456789012345678901234567890123456789
01 function functionName(aNumber : Number, aStartDate : Date) : Boolean
02 {
02 if (condition) {
03 statements;
04 } else {
05 statements;
06 }
07 }

Operators
Conditional operator (if-else)
Current standard introduces following rules:

There is a space between the “if” and the opening brace “(“
There are no spaces between the braces and the condition itself
The else statement appears on the same line as the closing bracket.
When the condition is complex and does not fit in the line, we can break it leaving the Boolean operator on the new line, indented once
(just after the bracket on the previous line)
When there is a single statement after the “if”, the statement should be placed indented on a new line inside brackets.
Avoid complex boolean statements. For more information see “Boolean Statements” section

Example: if-else statements

function functionName(aNumber : Number, aStartDate : Date) : Boolean


{
if (condition) {
statements;
} else if (condition1 && condition2
&& contidion3) {
statements;
} else {
if (condition) {
statements;
} else {
statements;
}
}
}

Multi-case Conditional operator (switch)


The default case is always the last one in the row
There is a space between the switch and the identifier in brackets
Cases with statements are always separated with break operands. Do not try to make complex reusable patterns with the C-style switch
operator without having a break after the statements.
There is an empty line between undependable cases. Combined cases (as case 3 and case 4) are not separated.

Example: switch statement


...
switch (identifier)
{
case 1:
statements_1;
break;

case 2:
statements_2;
break;

case 3:
case 4:
statements_3;
break;

...

default:
statements_4;
}
...

Loop operator (while, do-while)


Current standard introduces following rules for applying of while and do… while operators:

There is a space between the while statement and the Boolean condition in brackets
The while operator always has a block, even the loop body is a single statement. The one-line shorthand in the form while (condition)
loop_statement; is forbidden.
In case of do-while statement, the while statement lies on the line with the closing block, separated with one space.

Example: while loop

...
while (boolean_condition) {
loop_statements_1;
}

...

do {
loop_statements_2;
} while (boolean_condition)
...

Loop statements (for)


Current standard introduces following rules for applying of for operator:

There is a space between the for statement and brackets


There is one space after the statement separator “;” and the following statement
The “for“ operator always has a block, even the loop body is a single statement. The one-line shorthand in the form for (s1; s2; s3)
loop_statement; is forbidden.
Do not use for loops if you can use while loop, without adding any additional statements to the loop body. The for operators complying to
the following style for (; s2; ) should be substituted with a while statement in the form while (s2). The for ( ; ; - ) loop is substituted with whi
le (true) loop.

Example: for loop

...
for (init_stm; cond_stm; loop_stm) {
loop_statements;
}
...

Boolean Statements in operators


Current standard introduces following rules for applying boolean statements in operators:

Boolean statements should be simple and readable


Boolean operators and identifiers are separated with space
Do not use complex boolean functions, which are target for debugging. Create boolean variables and store the function result in order for
inspection and use the variable instead.
Always use brackets in order to point out the precedence if different boolean operators are used in one statement. Do not rely on
operator precedence at all. Braces make the reading process easier.
Do not use more than one boolean function in statements. Do not rely on any purpose, what is the execution plan for the statement. Store
the results in variables and manually control the execution of the functions.

Clauses and declarations


Constants
Current standard requires following rules for constants declaration and usage:

Following constants are available for use in method implementation:


Integer : 0, 1, 2
Float: 0.0, 1.0, 0.5, 2.0
String: '' (For strings use single quotes)
Boolean: true, false
All other constants should be defined outside of the method implementation (declared at module, class level or at package level in a
separate file)
Constants are declared always before the variables and methods, in the top part of the source file.

Variables
Variables are data identifiers, used to refer to specific values that are generated in a program. The term “variable” also denotes class members
(static or not static) in Object Oriented Programming. Current section includes some rules for variable definition. These rules are listed below:

Each variable should be defined on a single line. The shorthand var a1, a2; is allowed only when there's no initialization of variables on
the line. The shorthand var a1 = 0, a2; is forbidden.
Local functional variables should always be initialized upon their declaration.
Class member variables (static and non-static) can be initialized either in the declaration statement or in a constructor method
When declaring a variable always give its type (String, Number, Object, etc.)
When assigning a value to a variable there must be a space before the "=" and a space after it.

Example: Variables definition


{
...
var size : Number = vector.size();

for (var i=0; i<size; i++) {


var obj : Object = vector.getElement(i);
...
}
...
}

Types of variables declared in a class:

var className = function className()


{
...

// This is a private variable


var _size : Number = vector.size();

// This is a public variable


this.paramName : String = "";

// This is a static variable


className.staticVar : String = "";

...
}

Braces
After opening and before closing braces there should not be any spaces.

Example:

for (var i = 0; i < 10; i++) {


}

function foo(var1 : Number) : Number


{
}

There are exceptions: when imprting packages and scripts, the declaration of the function execute for pipelet scripts.
importPackage( dw.customer );

importScript( 'ecm_utils:library/common/libContext.ds' );

function execute( args : PipelineDictionary ) : Number


{
// some code here
}

Method Declaration
Method represents a source code structure, which defines the behavior of an object in Object Oriented Programming. The term method applies
also to functions and procedures, without any matter of the scope (class method, inner class method, global or local function and procedures).

Method’s declaration consists of defining the method signature (interface part) – return type, name, parameters. The method definition addresses
the method body (the implementation).

Current standard requires following rules for methods declaration:

There should be 2 empty lines before a method with declaration and definition.
The method declaration should be indented according to the indentation of the scope/block.
Name and the first parameter are placed on the same line.
Return type is placed on the same line with the closing parenthesis of the parameter list.
If the parameter list is short, all the other parameters can be enlisted on the same line. The line should not exceed the Max Line Length
(120 chars). There should be a space after each comma in the parameter list.
If the parameter list is long or the parameters count exceeds 5, the parameters should be placed vertically, each on separate line. The
horizontal alignment of the following lines is according to the first parameter or 8 spaces after method declaration in case when method
name is very long. All parameters should be in one vertical column.

Example: Methods declaration


// method with a short list of parameters
function fooShort(var aParam1 : String, var aParam2 : Number) : Number
{
...
}

// another method with a short list of parameters


obj.fooShort = function (var aParam1 : String, var aParam2 : Number) : Number
{
...
}

// long list of parameters, exceeding the Max Line Length


function fooLong(var aParam1 : Number,
var aParam2 : String,
var aParam3 : Object,
var aParam4 : Boolean,
var aParam5 : String,
var aParam6 : String,
var aParam7 : String,
var aParam8 : String) : String
{
...
}

Method definition
The method definition is the implementation part of the method or so called “method body”. It can contain zero, one or more statements and
should conform to the following rules:

Opening block is below the method declaration and has the same indentation
Statements are indented with one tab (as normal block indentation)

Example: Method definition

// method with a short list of parameters


function fooLong(var aParam1 : String, var aParam2 : Number) : Number
{
// method body begin
statements;
// method body end
}

// method with no body – empty definition


function fooEmpty()
{
}

Return Statements
The methods, considered as functions, have a return value, defined by the return operator. Current standard applies following rules for return
statements:

The return operator should always return a value, stored in a method local variable.
The count of return statements in a method should be as minimal as possible.

Comments: Many return statements make the method harder for visual verification. Complex return statements make tracing and debugging a
difficult process

Exception Handling
Example: Exceptions handling

...
try {
statements;
} catch(err) {
handling_statements;
} finally {
final_statements;
}
...

Method calling
Current standard requires following rules for method calling:

There is a space after each comma in the parameter list


If the parameter list is long or the parameter count exceeds 5, parameters should be placed vertically, each on a separate line, aligned
according to the first parameter. The first parameter is placed along with the method name.

Rules exceptions: The second rule can be omitted, in case the parameter list looks short and clear.

Example: Method calling

// method with a short list of parameters


// calling a method with a short list of parameters
foo1(param1, param2, param3);
...

// calling a method with a long list of parameters


foo2(param1,
param2,
param3,
param4,
param5,
param6);

Comments
Current standard defines some rules for several types of comments, listed in the current section.

Documentation Comments

The documentation comments are describing the purpose of a module / class / method / variable / constant definition or declaration. They
should act as a short usage manual of the item.
This type of comments should be developed according to each item importance.

Class description block

/**
* This is the description for my class.
*
* @class MyClass
* @constructor
*/

Method description block

/**
* My method description. Like other pieces of your comment blocks,
* this can span multiple lines.
*
* @method methodName
* @param {String} foo Argument 1
* @param {Object} config A config object
* @param {String} config.name The name on the config object
* @param {Function} config.callback A callback function on the config object
* @param {Boolean} [extra=false] Do extra, optional work
* @return {Boolean} Returns true on success
*/

Property description block

/**
* My property description. Like other pieces of your comment blocks,
* this can span multiple lines.
*
* @property propertyName
* @type {Object}
* @default "foo"
*/

Demandware script description block


/*************************************************************************************
* Name: ReleaseCouponPoints.ds
*
* Description: Subtracts the redeamed points amount from all Released points and adds
history record
*
* Pipelet parameters:
* @input Customer : dw.customer.Customer The customer that Loyalty profile will be
updated for. Mandatory.
* @input LoyaltyEvent : String The Loyalty event type to process. Mandatory.
* @input PointsAmount : Number The points amount that will be processed. Optional if
not event that requires points.
* @input EventId : String The loyalty event ID used to distinguish events of same
type. Optional if it is unique(one time) event.
* @input ecsLogger : Object eCommera custom logger.
*
* @output ecsLogger : Object eCommera custom logger.
**************************************************************************************
/

Tags description

Primary Tags

Name Example Description

class Indicates that the block describes a class.


/** In JavaScript, this is generally an object with
A utility that a constructor function
brokers HTTP
requests...

@class IO
@constructor
**/
function IO (config)
{

method Indicates that the block describes a method.


/** A @method block should always reside
Returns this model's directly above the method's definition.
attributes as... At a minimum, you should also document
any parameters
@method toJSON (@param) and return values (@return).
@return {Object} Copy
of ...
**/
toJSON: function () {
event Indicates that the block describes a custom
/** event that the
Fired when an error class can fire at some interesting moment of
occurs... code execution.
An @event block is somewhat similar to a
@event error @method block, except that @return is
@param {String} msg A irrelevant,
description of... and @param is used to describe properties
**/ hanging off the event
var EVT_ERROR = object that callbacks listening for the event
'error', receive.
Ideally, an @event block should reside
above the code
that defines the event, even if that code is
just a simple string declaration.
If you find that your @event block is "floating
in space,"
you should at least place it underneath the
class
that owns the event, grouped with any other
events that the class can fire.

property Indicates that the block describes a property


/** belonging to the current class.
Template for this As with methods, a @property block should
view's container... always reside directly
above the point where the property is
@property defined. At a minimum,
containerTemplate you should also provide the property's
@type String @type, even if the value is "any" or "mixed".
@default "<div/>"
**/
containerTemplate:
'<div/>',

Secondary tags

Name Example Description

constructor Indicates that the class is instantiable


/** (created with the new keyword).
@class IO A @class tag should be paired with either a
@constructor @constructor tag or a @static tag.
**/

static Indicates that the method or class is static:


/** For methods, indicates that the method is
YUI user agent meant to be called without
detection... instantiating the class: var node =
Y.Node.create('<div/>');
@class UA For classes, indicates that you should not
@static instantiate the class with new.
**/ You can call all of the class's methods
statically.
A @class tag should be paired with either a
@constructor tag or a @static tag.
final Indicates that the property or attribute
/** is a constant and should not be changed.
Identifies state
changes
originating from...

@property SRC_REPLACE
@type String
@static
@final
**/

optional Indicates that the attribute is not required


/** to be provided for proper use of this class.
An optional
attribute,
not required for
proper
use.

@attribute extras
@type {Object} extra
data
@optional
**/

required Indicates that the attribute is required to be


/** provided for proper use of this class.
A required attribute
that is required for
proper
use, module will
likely fail
if this is not
provided.

@attribute url
@type {String} url to
fetch remote data
from
@required
**/
param Defines a parameter for an ordinary
/** @method, a parameter for a @constructor
@param {String} name (generally defined inside a @class block), or
An a property that resides
Attribute name or on an @event object. Can take either of the
object property forms:
path. @param {type} name description
**/ @param name {type} description
The {type} is optional, but if you include it,
/** you must surround
@param {Object} it in curly braces so that it is distinguished
[options] Data from the name.
to be mixed into The name also has optional syntax:
the event [name] — optional parameter
facade of the [name=foo] — default value is foo
`change` name* — placeholder for 1..n args
event(s) for these [name]* — placeholder for 0..n args
attributes. As shown in the example, you can also nest
@param {Boolean} @param tags.
[options.silent] This enables you to document object
If `true`, no parameters that have their own particular
nested structure.
`change` event
will be fired.
**/

return Specifies a method's return value.


/** A @return tag has the structure @return
@method {type} description.
generateClientId The {type} is optional.
@return {String}
Unique clientId.
**/

type Specifies the type of a property or attribute.


/** You can specify a single type, a list of legal
@type String types
**/ separated by vertical bars, or if you are lazy,
"any" or "mixed".
/**
@type
HTMLElement|Node|Stri
ng
**/
private Indicates a member that should not be used
/** externally.
Reference to the
internal JSONP
instance used to make
the queries.

@private
@property _jsonp
**/

default Specifies the default value of a property or


/** attribute.
@default false Should be paired with a @type tag.
**/

uses Specifies that the class has some other


/** class's properties, methods,
@class Panel and other members mixed into its prototype,
@constructor perhaps using Y.mix(), Y.Base.mix(),
@extends Widget Y.Base.create(), or similar methods.
@uses WidgetAutohide
@uses WidgetButtons
...
**/

deprecated Indicates that the module, class, or member


/** is
@property locale deprecated and will be removed in a future
@type String release.
@deprecated Use You can optionally supply a string message
`config.lang` describing what to use instead.
instead.
**/

async Indicates that the method is asynchronous


/** and requires a callback.
@async
**/

throw Indicates that a method throws an exception.


/** You must specify the exception type.
@throw ExceptionType
**/

Pipeline description block

Above each pipeline start node there must be a comment block describing the purpose of the pipeline. The comment should include INPUT and
OUTPUT information of the pipeline.

It is recommended to fill the "Custom Label" and "Description" fields of the pipeline nodes.

Implementation Comments
The implementation comments are the comments, found in method body implementation.

In general, the source code implementation should be self-documented. But there are always cases, where comments should be explicitly
applied:

In case of reasonable irregular operator usage (complex switch operators, complex statements). The reason should be specified.
In case of strange workaround/fix or irregular action – The reason should be specified!
In case of reasonable complex statements – the reason and the statement description should be specified.

Comments around large blocks of code

In case there is an operator with a block of code that does not fit in a normal screen, it should end with a comment after the closing bracket "}".

for (var i = 0; i < foo.size(); i++ ) {


...
// very long block of code
...
} // END for (var i = 0; i < foo.size(); i++ )

switch (bar)
{
...
// very long block of code
...
} // END switch (bar)

Long sections of code for a single functionality that do not fit in a normal screen should be surraounded with comments indicating the start and the
end of the section.

/********* START generating return string **************/

...

/********* END generating return string **************/

/********* START sending data **************/

...

/********* End sending data **************/

Commented code

Piece of code can be temporary commented during testing or debugging. In general, no commented code should be left when claiming the source
file is ready (during check-in).

In case of any reasons to leave a piece of code commented, specify and describe in another comment why the code is left commented.

Commented code without such “reasonable comments” should be discarded by every developer upon editing the source file. Commented code
with “reasonable comments” should not be discarded by everyone.

Useless comments

There are comments, which are not describing more than the code itself. Such comments are useless and should be discarded.

Example: Useless comment


...
//calculating the total amount
total = amt + tax;
...

You might also like