Copyright � 2005 Syntext, Inc.
Permission is granted to any institution or individual to use, copy, modify, and distribute this document, provided that this complete copyright and permission notice is maintained intact in all copies.
Syntext, Inc. makes no representations about the suitability of this document or the examples described herein for any purpose. It is provided “as is” without warranty of any kind.
E-mail suggestions to: info-general@syntext.com
Table of Contents
List of Examples
Table of Contents
This paper prescribes the concrete rules for Syntext project development.
In development it is necessary to follow coding conventions for the following reasons:
It is necessary to avoid the typical coding mistakes
It is necessary to unify the view of different code fragments
In any code fragment any project programmer has to understand semantics rapidly
New people can get up to speed quickly
In some typical situations it is convenient to apply a worked out coding style for performance increase (both human and computer).
Because of the above-mentioned reasons source code ought to satisfy the following:
Should be consistent (has complete structure)
Should be clear for reading and comprehension
Must not contain typical mistakes
Available to any programmer for modification
Must not lead to performance loss.
The following definitions are used in the paper:
Rule - statement that must be strictly obeyed.
Recommendation - statement that should be followed if it does not lead away from prescribed goals and does not contradict the common sense.
Rule.�If a rule is broken it has to be explicitly documented.
Recommendation.�Code is optimized only in the case of special performance requirements. Code is optimized only in extreme cases.
Rule.�Code must never be copy/pasted (literally doubled). If two functionalities have the common parts, they must reuse single code portion.
Rule.�Package and module names begin from uppercase letters. Each next word of the name starts with uppercase letter. The words are not separated with underscore.
Rule.�Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants. Imports should be grouped, with the order being:
standard library imports
related major package imports
application specific imports
You should put a blank line between each group of imports.
Rule.�Relative imports for intra-package imports are highly discouraged. Always use the absolute package path for all imports
Documentation implies literate programming. That is documentation to classes, functions, etc. is provided in the code, in special comments that are exported to documentation.
There are the two types of code comments:
Documenting comments .�Those forming the project documentation, i.e. describe given programming component, ways to use it, and the interfaces.
Explaining comments .�Those serving better (implementation) code comprehension.
Explaining comments that use special keywords are called key comments (see Example�1.3, “Documented fragment sample ”). They provide additional semantics in tagging specific code peculiarities. Non-key comments have arbitrary form.
Rule.�All comments are written in English.
Recommendation.�Every module, class, and function should be documented with python docstring.
Rule.�Python docstring are formatted in the manner given in Example�1.1, “Documenting Comments Example ”. All the lines of docstring have the same indentation and enclosed in triple quotes. Short (preferably one-line) description goes in the first sentence. Verbose description is following in the next paragraphs.
Rule.�Block comments are indented to the same level as the code they applied. Each line of a block comment starts with a # and a single space (unless it is indented text inside the comment). Paragraphs inside a block comment are separated by a line containing a single #.
Rule.�Keywords in key comments are separated with colon from the other words that are placed on the same line (see Example�1.3, “Documented fragment sample ”).
Recommendation.�Key comments are added if they do not cumber the code and increase visual presentation. (For example, if a class contains a constructor and a couple of functions there is no need in key comments).
Rule.�Each code file must have a comment header, presented in Example�1.2, “File Header”.
Rule.�It is necessary to distinctly document code with the key
comments where special attention needed in the following
form:
# KEYWORD: ,
where date is composed in YYMMDD form, for example
990619 (author and date are optional). Several line comments are acceptable, but the
first string has to contain the principal statement.
(See. Example�1.3, “Documented fragment sample ”). The following keywords
are accepted:
authordate : comment text
TODO.�Incomplete piece. Comments about what is to be done.
KLUDGE.� Dirty hack. Comments have to contain reasons for the workaround.
TRICKY.� Code is tricky and must not be modified without special attention.
WARNING.�Self-explanatory.
Rule.� All names are composed from English words and common English abbreviations.
Rule.�Names of variables, functions, class methods, objects must begin with lowercase letter.
Rule.� Names consisting from more than one word are composed as uppercase letter separated words in lowercase.
Rule.�Only team-accepted abbreviations may be used in the names.
Recommendation.�Name must distinctly describe an entity meaning.
Name that is pronounced with difficulty is a bad name. If it is difficult to make up a name for an entity then possibly design has to be revised.
Rule.�If name contains an abbreviation then abbreviation is written with lowercase letters, leaving only first letter in uppercase. (See Example�1.4, “Only first letter of abbreviation is in uppercase. ”).
Rule.�Accepted prefix and suffix must be used. Among them:
Prefixes:
is.� - predicate
(E.g. isSortable()).
make.� - object-factory function/member
Recommendation.�If a class name consists of more than three words then the class design should be reviewed.
Rule.�Names of classes must begin with uppercase letters.
Rule.�Class members (both data and function) that are not a part of interface must begin with “_” underscore or “__” double underscore ("private" members). See Example�1.5, “Example of class member names”)
Rule.�Class data members are named without underscore if class is purely representational (serves as a data holder).
Rule.�Class data members starting with “_” or “__” must not be directly accessed, but via access functions.
This makes easier usage tracing or further code modification if eventually a data member becomes a part of some class invariant.
Example�1.5.�Example of class member names
class Person:
"""
Personal information holder.
"""
def __init__(self, name, gender):
self.name = name
self.gender = gender
class Index:
"""
Index interface.
"""
def __init__(self):
self.__authInfo = None
self._cacheHolder = None
def update(self):
"""
Update Index.
Reimplement in concrete class
"""
pass
def getAuthInfo(self):
return self.__authInfo
def _updateCache(self):
"""
Update the row data cache.
Reimplement in concrete class.
"""
passRule.�Because method or function is an action, its name must contain a verb (See Example�1.6, “Function name example”). Exceptions are the data member accessors. (See Example�1.8, “Member-data access”).
Rule.�Standalone functions must contain only lowercase letters with underscore separated words “_”.
Rule.�If function is a predicate it must begin with "is" or "has" prefix.
Rule.�If function is an object factory it must begin with "make" prefix.
Rule.�Formal parameter names must begin with lowercase letters, and then class name rules apply. (See Example�1.5, “Example of class member names”)
Rule.�Local variable names must contain lowercase letters with underscore separated words "_".
Rule.�A line must not exceed 79 symbols.
Rule.�Four-space indentation is used. Tabulation must not be used for indentation.
Eventually tabs become an irritating headache in one or other case.
Recommendation.�If nesting exceeds 4 or 5 levels then it is recommended to review the algorithm.
Rule.�Any definition (class, function, class member function) must be separated from other in a row with at least one blank line.
Rule.�Binary operators and operands are separated with whitespace.
Rule.� Parameters of the exception keep the values specific to the exception type and do not change exception type semantics.
Rule.�Do not separate with a whitespace parentheses, brackets or braces. Example:
# ugly:
spam( ham[ 1 ], { eggs: 2 } )
# correct:
spam(ham[1], {eggs: 2})Rule.�Do not put whitespace immediately before comma, semicolon, or colon:
# ugly:
if x == 4 :
print x , y ; x , y = y , x
# correct:
if x == 4:
print x, y; x, y = y, xRule.� Function definition/declaration must be given in the following form: function name, leading parenthesis and the first argument should be placed on one line. If there is enough room then all the other arguments and closing parenthesis may also be written on the same line as the function name. Otherwise each additional argument must be written on a separate line (with the closing parenthesis immediately after the last argument). (See Example�1.7, “Function declaration example”).
Rule.�Always write the left parenthesis and colon immediately after function name. (See Example�1.7, “Function declaration example”).
Recommendation.�Use blank lines in functions, sparingly, to indicate logical sections.
Rule.� Data member access must be defined as in Example�1.8, “Member-data access”.
Rule.�Separate top-level function and class definitions with two blank lines. Method definitions inside a class are separated by a single blank line. Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations).
If not otherwise mentioned the rules and recommendations are also applied to member functions.
Recommendation.� Functions with the large number of arguments should be avoided.
Recommendation.� It is necessary to avoid large and complicated functions (more than 50-60 lines).
If function is large, then its comprehension is complicated.
Bugs are localized easier in short functions.
Rule.�
Constants are placed on the left side of "==" expressions.
(E.g. if (6 == errorNum) {)
Rule.� One line must contain only one statement except for the cases when they are very close in meaning.
Recommendation.� When in doubt of priorities parenthesis must always be used.
Rule.�
All exceptions must be derived from built-in
Exception class.
Rule.� Exception class inheritance hierarchy should be shallow (and wide).
Recommendation.� Exception classes should not have multiple inheritance.
Rule.�
Exception class must define __str__()
function that gives string with human-readable exception
description. (Exception must not have description string
as a parameter).
Recommendation.�
Exception parameter had better be also passed to Exception
constructor (therefore the values are also available is
standard parameter args of the exception.
Rule.� Each module has exception base class. Every type of exception in the module must be derived from the base.
Rule.� Type of exception is identified by specific class (each semantically specific exception should be expressed by a specific class).
Rule.� Parameters of the exception keep the values specific to the exception type and do not change exception type semantics.
Recommendation.� Exceptions must have specific semantics of the point they occurred. E.g. OsError exceptions within some module should be reinterpreted to an exception, describing semantics of the event, and which class was defined specifically for the module.
Recommendation.� Modules that have implementation code for interface modules should use base exception of the interface module.
Table of Contents
Rule: Do not duplicate what was done.�If some functionality is already implemented, it must be used. Creating alternatives is prohibited. If the interface or the implementation of the functionality does not satisfy a developer he should talk about the enhancements, and must not create yet another version.
Rule: Ask others if it was done.� If a programmer suspects that the problem faced has already been implemented then he must ask the team on e-mail on available solution.
Rule: Inform others on what was done.�Members must inform team on new reusable components implemented.
Python Style Guide. Available online.