openerp-expert-framework team mailing list archive
-
openerp-expert-framework team
-
Mailing list archive
-
Message #00062
Re: Coding guidelines and standards - additional info
Hi Ferdinand,
Is there a wiki for these guidelines?
On Tue, Dec 15, 2009 at 2:29 PM, Ferdinand Gassauer <office@xxxxxxxxxx>wrote:
> some additional ideas
>
> we also prefer to code table descriptions for better readability
> (see screen shot)
> * fixed column width for name and filed type
> (I know sometimes the name is to short ....)
> * alphabetical order of fields
> * split long lines
>
>
>
> The Syntax is "MoinMoin"-Wiki.
>
> -------------------------------------------------------------
> --
> Best Regards
>
> ChriCar Beteiligungs- und Beratungs- GmbH
> http://www.chricar.at/ChriCar/index.html
> Dr. Ferdinand Gassauer
> Official Tiny Partner
>
>
> = Introduction =
>
> These rules augment the rules stated in PEP-0008 (
> http://www.python.org/dev/peps/pep-0008/).
>
> == Purpose ==
> Coding guidelines help to:
> * '''ensure maintainability''' -- any programmer should feel "at home"
> when reading any source code. Therefore, any source code needs to have a
> uniform structure. Moreover, it is essential to disallow difficult-to-read
> code fragments requiring a lot of time to be understood.
> * '''ensure automatization''' -- so that we can automatically rewrite code
> and generate documentation, for example, API documentations and reference
> manuals.
> * '''avoid faulty software''' -- following the below guidelines will help
> programmers to avoid or circumvent common errors and pitfalls.
>
> == Scope ==
> * These coding guidelines apply to Python files only. However, major parts
> can be adapted to other languages as well.
> * '''Any Python file must conform with these coding guidelines,'''
> regardless of whether it is a library, a tool-specific file, a "goodies"
> script or just a quick hack for rapid prototyping.
> * However, there might be some cases where it makes sense to break a
> rule. It is up to you as careful and intelligent programmers to identify
> these cases and handle them in a proper way:
> * If it appears to be a single case, the item shall be documented in the
> artefact itself.
> * If the violation is considered to be systemic and should be taken into
> account in the guidelines, file a change-request against the documents. See
> section 6 how to do so.
>
> == Terminology ==
> * The word "shall" is used for requirements. You need to have a very good
> reason not to use "shall" where it is mandatory, and you have to document,
> why you have done so.
> * The word "should" is used for recommendations, good practices and hints.
>
> == General Advice ==
> * Program '''defensively'''. Consider in particular that parameters of a
> function may be incomplete (for example, filename without extension or full
> path) or have a different type (`int` instead of `float`, `tuple` instead of
> `list`, ...).
> * Program for '''portability'''. For example, use `os.path.join` instead
> of concatenating strings with "/".
> * Program '''unambiguously'''. Define unique values only once.
> * Avoid defining "magic" numbers in the source code. Use definitions
> instead of hard-coded numbers.
> * Use '''symbolic names'''. This improves readability, makes the program
> easier to maintain, reduces the potential for errors, and requires less
> development effort.
>
>
> = Formatting =
>
> == General ==
> 1. There shall be no trailing spaces
>
> == Header ==
>
> 1. Every file shall start with a header.
> This header shall include:
> * the Python coding cookie. You had best use the `iso-8859-1` charset.
> * licence information.
> * The name of the file, as it would be imported by Python. For the
> `App_Type` module in the`_TTA` package, this would be `_TTA.App_Type`.
> * the purpose of the file.
> * revision dates including the Bugtracking number.
> 2. The header shall ''not'' include:
> * hash-bangs so that the Python script can be executed just by calling it
> (that is, "`#! \usr\bin\env python`"). When the Python version is changed,
> it can be very hard to find errors caused by these hash-bangs.
>
> '''Hint:'''
> It is good practice to check the header of every file you edit.
>
> 3. The header shall have the following format. (Two different licenses are
> given as example.)
> {{{
> #!python
> # -*- coding: iso-8859-1 -*-
> # Copyright (C) 2000-2004 Swing GmBH. All rights reserved.
> # Gruenlandgasse 1, 2620 Neunkirchen, Austria. office@xxxxxxxxxxxxxxxx
> #
> #++
> # Name
> # _TTA.App_Type
> #
> # Purpose
> # Define application types for TTA tools
> #
> # Revision Dates
> # 7-Nov-2000 (GK) Creation
> # 28-Jul-2002 (GK) [4711] Adapted to packaging of `TOM`
> # 2-Apr-2004 (GK) [4712, 4713] `NODE__cluster` added to definition of
> `NDT`
> # ««revision-date»»···
> #--
> }}}
>
> {{{
> #!python
> # -*- coding: iso-8859-1 -*-
> # Copyright (C) 2000-2004 Swing GmBH. All rights reserved.
> # Gruenlandgasse 1, 2620 Neunkirchen, Austria. office@xxxxxxxxxxxxxxxx
> #
> #
> ****************************************************************************
> # This library is free software; you can redistribute it and/or
> # modify it under the terms of the GNU Library General Public
> # License, as published by the Free Software Foundation; either
> # version 2 of the License, or (at your option) any later version.
> #
> # This library 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
> # Library General Public License for more details.
> #
> # You should have received a copy of the GNU Library General Public
> # License along with this library; if not, write to the Free
> # Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> #
> ****************************************************************************
> #
> #++
> # Name
> # _TFL.DL_List
> #
> # Purpose
> # Doubly linked list
> #
> # Revision Dates
> # 11-Sep-2003 (GK) Creation
> # 12-Sep-2003 (GK) Creation continued
> # 9-Mar-2004 (GK) [4714] `_doc_test` changed to not use `import`
> # ««revision-date»»···
> #--
> }}}
>
> == Footer ==
> 1. Every file shall end with the following comment, repeating the name of
> the header.
> {{{
> #!python
> ### __END__ TTA.App_Type
> }}}
>
> == End of Classes and Functions ==
> 1. Every class shall have a closing comment with the syntax as shown
> below.
> 2. Every method shall have a closing comment with the syntax as shown
> below.
> '''Example:'''
> {{{
> #!python
> class Coding_Guidelines (Guidelines) :
> """General and abstract guidelines."""
>
> def __init__ (self, name) :
> self._name = name
> # end def __init__
>
> def formatted_name (self) :
> """Returns the internal variable `_name` nicely formatted.
> """
>
> return ">>%s<<" % self._name
> # end def formatted_name
> # end class Coding_Guidelines
> }}}
>
> == Indentation and Spacing ==
> (See http://en.wikipedia.org/wiki/Bracket on a definition of brackets,
> parentheses and braces.)
>
> 1. Source files shall not contain consecutive multiple blank lines.
> 1. There shall exactly be one blank line between a method and a class
> definition.
> 1. You shall use a blank space before `\` or `:`
> 1. You shall use a blank space before and after any operator.
> 1. You shall use a blank space after `,` or `;` or `:`
> 1. You shall not place spaces after openings and before closings.
> 1. You should concentrate args, but never keywords.
> '''Example:'''
> {{{
> #!python
> CSE_Object_Selector.__init__ \
> ( self, r_map, master
> , label = "Subsystem"
> , list = list
> , name = "subsystem_selector"
> )
> }}}
>
> == Alignment ==
> 1. If, and only if, a call or definition exceeds one line, it shall
> immediately be broken after the name, keyword or (assignment) operator.
> 1. Exception names shall be in the same line as `raise` or `except` to be
> able to ''grep'' for them.
> '''Example:'''
> {{{
> #!python
> raise TypeError, \
> "%s needs a list as first argument, not a %s." % (self.name, type
> (x))
> }}}
> 1. If the remaining line is still too long, one line shall be used for
> every parameter.
> 1. Brackets and commas shall be aligned horizontally.
> 1. If a closing bracket is on a different line than its opening bracket,
> both shall be in the same column.
> 1. `=` signs for keyword defaults shall be aligned horizontally.
> 1. `=` signs shall be aligned horizontally, in consecutive lines of
> statements.
> 1. Triple-quotes (`"""`) shall be normally indented and horizontally
> aligned.
> 1. Expressions shall be aligned so that their visual appearance matches
> their logical structure.
> '''Example:'''
> {{{
> #!python
> class Function_Definitions (Coding_Guidelines) :
> """More about function definitions. Several lines are welcome,
> and they do not affect the general layout of this class or
> function description.
> """
>
> def __init__ \
> ( self, typ, version
> , a_default_parameter = "something"
> , a_long_parameter_name = 1
> , another_parameter = "something other"
> ) :
>
> self.typ = typ
> self.version = version
> self.r_map.tag_highlight \
> (event, self.f_tag, self.r_map.frame_high, "current_frame")
> self.name = self.r_map.name + self.version
> self.userints [i] = self.map_from_object \
> (self.r_map, self, rtag, i + 1, typ = "host")
> CSE_Object_Selector.__init__ \
> ( self, r_map, master
> , label = "Subsystem"
> , list = list
> , name = "subsystem_selector"
> )
> # end def __init__
> # end class Function_Definitions
> }}}
>
> == EOL Quotes ==
> 1. You shall use the EOL quote (backslash + carriage_return) only if
> really necessary. The only exception is right after a function name, a
> keyword or an assignment operator, if the line would otherwise be too long.
> 1. There shall be no more than one EOL quote per statement.
> 1. Adjacent text literals on multiple lines shall be put in parentheses,
> instead of quoting the line ends with backslashes. See example below.
> 1. You shall factor as much as possible, even in text literals.
> 1. Expressions spanning multiple lines shall also be parenthesized.
> '''Example:'''
> {{{
> #!python
> Abbreviations = "\n".join \
> ( ( "`bb` ... bytes_bus effective length of the frame on the bus"
> , "`vs` ... validity_span duration in which the frame is valid "
> " in the CNI, starting at the next slot"
> , "`tt` ... transmission_time duration of the transmission phase
> on"
> " the bus"
> , "`d` ... duration slot duration"
> , "`s` ... size net size of the frame in bytes"
> )
> )
> }}}
> 1. You shall not use an EOL quote, if the subsequent opening bracket is
> below the EOL quote or to the right of it.
> '''Bad Example:'''
> {{{
> #!python
> if \
> ( long_expression
> and another_long_expression
> ) :
> }}}
> '''Good Example:'''
> {{{
> #!python
> if ( long_expression
> and another_long_expression
> ) :
> }}}
> 1. Long strings shall be broken into pieces or written with triple-quotes.
> The new line shall be aligned with the beginning of the string at the same
> level on the previous line.
> '''Example:'''
> {{{
> #!python
> a_rather_long_string = \
> ( "A very long string "
> "split over multiple lines."
> )
> another_rather_long_string = \
> """A very long string
> split over multiple lines.
> """
> }}}
>
> = Structure =
>
> == Module and Class ==
> 1. Every file shall have a file history documenting any modification made.
>
> == Order of Definitions ==
> 1. The most important class should be the last one.
> 1. Within a class, you shall first define the attributes of this class,
> then properties if any, then the methods.
> 1. The methods of a class shall be sorted in the following order:
> * First `__new__`, then `__init__`, then `__call__`.
> * Then the public interface (that is, externally used methods) shall
> follow. Such methods look like "`x`".
> * Then non-public methods shall follow. Such methods look like "`_x`".
> * Then other special methods shall follow. Such methods look like
> "`__x__`".
> * Name-mangled methods (looking like "`__x`") shall not be used.
> 1. Within the above sections, methods should be sorted in a natural way
> (for example, most important first, according to the control flow, grouped
> logically), else in alphabetical order.
> 1. The `__main__` script shall be at the end of a module.
> 1. If there are long lists of attributes, keywords, or other items, for
> example, they should be sorted alphabetically (or numerically, if
> applicable).
> 1. '_' shall be ignored when sorting, but underscores should be grouped.
> For example, `affe`, `ameise`, `_aachen`, `_amsterdam`, `bingo`, ...
>
> == Package Name Space ==
> 1. Related modules shall be grouped into a Python package.
> 1. Each package shall be implemented as a Package_Namespace.
> * The name of the package shall start with a single underscore, for
> example, `_Foo`.
> * The name of the package namespace shall be the same as that of the
> package, with the exception of the leading underscore, for example, `Foo`.
> * The package file `__init__.py` shall define the package namespace
> instance (see package `TOM` for an example).
> * All the modules of the namespace package shall contain an export
> statement guarded by `__name__ != "__main__"` at the bottom of the file.
> '''Example:'''
> {{{
> #!python
> if __name__ != "__main__" :
> TFL._Export ("*")
> }}}
> 1. Any access to objects of a namespace package shall use a qualified name
> which shall start with the name of the namespace package, for example,
> `Foo.bar ()`.
> '''Example:'''
> {{{
> #!python
> from _TFL import TFL
> import _TFL.DL_List
> ...
> l = TFL.DL_List ()
> }}}
> 1. `From` `import` shall not be used to import objects from a namespace
> package.
> '''Bad Example:'''
> {{{
> #!python
> from _TFL.DL_List import DL_List
> }}}
>
> == Nesting and Recursion ==
> 1. Nested function definitions should be avoided.
> 1. Recursion shall be used only, if it substantially simplifies the code.
>
> = Semantics =
>
> == Documentation ==
> 1. Any comments and descriptions documenting a source file shall be
> written in '''English'''.
> 1. Any documentation in the source code has the following objectives:
> * Defining a uniform structure of all source code modules.
> * Providing an easy way to find information on the file contents.
> * Making it easier to maintain files.
> * Providing information on how a certain problem has been solved.
> * Facilitating to generate additional documentation (such as reference
> manuals) automatically.
> 1. If actual names or values appear in any documentation, they shall be
> enclosed by backquotes (`).
>
> == Docstrings ==
>
> There is '''no''' reason (IP-protection, etc.) to '''not''' write
> docstrings.
>
> 1. Docstrings presented to the user shall have appropriate wording and may
> contain whatever is necessary for the specific purpose and due to usability
> considerations.
> 1. Docstrings that are not presented to the user shall contain a brief
> description of the relevant class or method. This description should not
> contain any redundant information (and repeat, for example, the default
> value) or misleading information (for example, requiring an int although any
> numeric would do).
> 1. The constructor should not have a description.
> 1. Docstrings should contain doctests whereever feasible.
> 1. Docstrings shall be concise. About the content see sub-section
> "Detailed Documentation" below.
>
> == Detailed Documentation ==
>
> The intention is to document any Python package or module using Sphinx.
>
> 1. A Python package shall be documented in the `__init__.py` file by using
> Sphinx. The generated documentation shall explain the purpose of the package
> and its structure and components.
> 1. A Python module shall be documented by the module docstring using
> Sphinx. The generated documentation shall explain the purpose of the module,
> its primary use case(es) and its structure.
> 1. Detailed documentation should contain design decisions, rationales,
> background information, usage examples and other helpful information for
> developers. It shall not repeat what is obvious from the code.
> 1. Detailed package or module documentation shall be done inline
> (docstring) or in a dedicated directory. For lib/python, this is
> `_DOC/Sphinx/packages`, maintaining the same structure as the source code.
> 1. Detailed documentation of concepts shall be done in a dedicated
> directory. For lib/python, this is `_DOC/Sphinx/concepts`.
> 1. As scripts are usually seen and used without the context of lib/python,
> all necessary documentation shall be in the same file as the source code
> itself.
> 1. Detailed documentation shall reference but not repeat other documents
> (SDD, customer's specifications, standards, etc.).
> 1. For detailed documentation in other files, a reference to this location
> shall be given. The location may be omitted if it is obvious. For Sphinx,
> use:
> {{{
> #!python
> # SPHINX_DOC [location]
> }}}
>
>
> == Comments ==
> Always consider that someone who sees your code for the first time has to
> be able to understand it.
> 1. You should use doctests (or at least docstrings) instead of comments.
> 1. Comments shall describe why something is done in a particular way, and
> not what is done or how something is done. This is documented by the code
> itself!
> 1. You shall place comments after a line, if possible (length). Otherwise,
> place it above the line of code to which it belongs.
> 1. You shall use the "`### XXX`" prefix for comments relating to future
> versions or constituing hints how to fix a problem.
> '''Example:'''
> {{{
> #!python
> another_function \
> ( first_very_long_parameter
> , (some * complicated + expression)
> , elapsed_time # in microseconds
> )
> # avoid rounding errors
> e = ((w_x * (ttime + self.ifg_in_ns)) / self.duration_in_ns) - d
> ### XXX adapt to improved Package_Namespace
> pkg_namespace_import_pat = Regexp (r"x", re.X)
> }}}
> 1. You shall use self-explanatory names instead of comments.
> '''Bad Example:'''
> {{{
> #!python
> a_function \
> ( first_long_parameter
> , 42 # number of lines
> )
> }}}
> '''Good Example:'''
> {{{
> #!python
> a_function \
> ( first_long_parameter
> , number_of_lines = 42
> )
> }}}
>
> == Naming ==
> 1. The name of a module shall have the extension ".py".
> 1. The base name of the module shall be identical to the name of the (only
> or most important) class.
> 1. If a module contains no class, its base name should refer to the
> intended use.
> 1. The name of the identifier shall be unambiguous and self-explanatory to
> specify the purpose of the identifier.
> 1. The larger the scope of visibility, the longer a name should be (and
> vice versa), this means that loop variables should be as short as possible,
> global names should be long enough to convey sufficient meaning.
> 1. If the name comprises multiple words, they shall be separated by
> underscores ("`_`").
> 1. `CamelCaseWordsLikeThisOne` shall not be used.
> 1. Magic names, to be specific, names with two leading and two trailing
> underscores, shall not be used except when magic methods are to be defined,
> as is defined by Python (otherwise existing code might become invalid in
> future Python versions, when the set of official magic gets bigger).
> 1. Any class name shall start with a capital letter (to be specific, with
> a capital letter at the beginning of the name and after every underscore).
> The rest are lowercase letters, underscore or digits. Exceptions are allowed
> when the name consists of an abbreviation (for example, `PCP_Driver`) or
> when the class implements an association (for example, `Host_uses_Message`).
> 1. Constants shall be all uppercase with words separated by underscores or
> digits.
> 1. The other identifiers (which can also have an underscore as the first
> letter) shall be all lowercase with words separated by underscores or
> digits. Exceptions are allowed for names being abbreviations.
> 1. Class names shall be nouns or noun phrases, in mixed case, with the
> first letter of each internal word capitalized (see above).
> 1. Mixin class names shall be adjectives or nouns having the "`_mixin`"
> suffix.
> 1. Names of states that change functions shall be verbs (for example,
> `connect`, `schedule`) or verb phrases.
> 1. Names of states that query functions shall be adjectives,
> noun-verb-adjective combinations or verb-noun combinations (for example,
> `connected`, `is_valid`, `has_key`).
> 1. You shall avoid "`get_`" prefixes.
> '''Bad Example:'''
> {{{
> #!python
> def get_version (self) :
> return "%s.%s.%s" % (self.major, self.minor, self.patchlevel)
> # end def get_version
> }}}
> '''Good Example:'''
> {{{
> #!python
> def version (self) :
> """Returns the version as <major>.<minor>.<patchlevel>."""
>
> return "%s.%s.%s" % (self.major, self.minor, self.patchlevel)
> # end def version
> }}}
> 1. Non-public names shall start and end with a single underscore ("`_`").
>
> = Pragmatics =
>
> == Avoid redundancy ==
>
> 1. Do not repeat yourself (DRY!). This also applies to
> * literals: use named constants,
> * (sub)-expressions: assign them to named variables,
> * blocks of code: factor them into functions or methods,
> * sets of methods: factor tem into common ancestors.
> 1. You shall be brief and concise.
> '''Bad Example:'''
> {{{
> #!python
> (x, y) = (self.current_slot [0], self.current_slot [1])
> }}}
> '''Good Example:'''
> {{{
> #!python
> (x, y) = self.current_slot [:2]
> }}}
> 1. You shall make the closing clearly visible.
> '''Example:'''
> {{{
> #!python
> (time, value) = reduce \
> ( lambda l, r, o = grid_opt : min (l, (o / r + r / o, r))
> , self.time_list
> , (2 * self.time_list [-1], ) * 2
> )
> r_slot = filter \
> ( lambda l, rs = rs : l.r_slot.round == rs.round
> and l.slot.number == rs.slot
> ### XXX place filter condition for Cluster_Mode here
> , r_slot
> ) [0].r_slot
> return \
> ( self.slot.duration * self.r_map.pix_per_MT_x
> + 2 * self.r_map.frame_border_x
> )
> }}}
>
> == New-style classes ==
> 1. For newly written code, new-style classes shall be used whenever
> possible, which is unfortunately not yet feasible for exceptions or
> descendents of some classic classes already existing.
> 1. New-style classes should normally inherit directly or indirectly from
> `TFL.Meta.Object`.
>
> == Reference to Ancestor Class ==
> 1. For new-style classes, `__super` shall be used to upchain method calls
> (`__super` is provided by the `TFL.Meta.M_Autosuper` meta-class).
> 1. Every classic class shall define an ancestor attribute which shall be
> used throughout the class to upchain method calls.
>
> == Import order ==
> 1. The role types of an TOM association shall be imported before the
> association itself. Role types are the object types connected ("linked")
> with the association.
> '''Good Example:'''
> {{{
> #!python
> from _TTA import TTA
> import TTA.Message
> import TTA.Subsystem
> import TTA.Subsystem_sends_Message
> }}}
>
> '''Bad Example:'''
> {{{
> #!python
> from _TTA import TTA
> import TTA.Subsystem_sends_Message
> import TTA.Message
> import TTA.Subsystem
> }}}
>
> == Use of properties ==
> For new-style classes, properties shall be used whenever control over
> attribute access is called for. A Python property associates an attribute
> name with methods to get, set, and delete the attribute's value and to an
> optional documentation for the attribute.
> 1. Properties shall be only used inside new-style classes.
> * Using properties for readonly attributes:
> {{{
> #!python
> class Foo (TFL.Meta.Object) :
> ro = property (lambda s : s._ro)
> def __init__ (self, x = 0) :
> self._ro = x
> }}}
> {{{
>
> >>>>>> f = Foo (1)
> >>>>>> f.ro
>
> 1
>
> >>>>>> f.ro = 3
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: can't set attribute
> }}}
> * Using properties for read/write attributes:
> {{{
> #!python
> class Complex (TFL.Meta.Object) :
>
> def _get_r (self) :
> return math.sqrt (self.x ** 2 + self.y ** 2)
> # end def _get_r
>
> def _set_r (self, r) :
> theta = math.atan2 (self.y, self.x)
> self.x = r * math.cos (theta)
> self.y = r * math.sin (theta)
> # end def _set_r
>
> r = property (_get_r, _set_r)
> }}}
>
> 1. Properties shall be used instead of parameterless access functions.
> '''Bad Example:'''
> {{{
> #!python
> class Foo (TFL.Meta.Object) :
> def position (self) :
> return self._position
> }}}
> '''Good Example:'''
> {{{
> #!python
> class Foo (TFL.Meta.Object) :
> position = property (lambda s : s._position, doc = "attribute
> documentation")
> }}}
>
> == Scope of Visibility ==
> 1. Do not make an identifier visible outside the scope for which it is
> required.
> 1. The larger the scope of visibility, the longer an identifier should be.
>
> == Identity vs. Equality ==
> 1. `is` shall be used to check for identity. As a general rule, identity
> checks should be used only for singleton objects.
> 1. `is` shall not be used to check immutable objects, such as numbers,
> strings, and tuples.
> 1. `==` shall be used to check for equality.
> 1. `==` shall not be used to check, whether a name refers to `None`.
> 1. To check for a specific type, use `isinstance (i, o)`.
> '''Bad Example:'''
> {{{
> #!python
> type (s) == type ("")
> type (s) is type ("")
> import types
> type (s) == types.StringType
> isinstance (s, type (""))
> }}}
> '''Good Example:'''
> {{{
> #!python
> isinstance (s, str)
> isinstance (s, (str, unicode))
> }}}
>
> == Boolean Expressions ==
> 1. Boolean values shall not be compared against `True` or `False`.
> '''Bad Example:'''
> {{{
> #!python
> if x == True :
> do_something ()
> }}}
> '''Good Example:'''
> {{{
> #!python
> if x :
> do_something ()
> }}}
> 2. To test, if a list or dictionary contains elements, you shall not use
> `len`.
> '''Bad Example:'''
> {{{
> #!python
> if len (x) == 0 :
> do_something ()
> }}}
> '''Good Example:'''
> {{{
> #!python
> if not x :
> do_something ()
> }}}
> 3. To test, if a name refers to `None`, identity testing shall be used.
> '''Bad Example:'''
> {{{
> #!python
> if not x : ### will be entered for any empty structure or zero-valued
> number
> do_something ()
> if x != None : ### calls `__cmp__` of x.__class__
> do_some_otherthing ()
> }}}
> '''Good Example:'''
> {{{
> #!python
> if x is not None :
> do_something ()
> }}}
>
> == Parentheses ==
> 1. You should use rather more than less parentheses.
> 1. You shall avoid redundant parentheses, like in `if (x == 5) :`.
> 1. You shall avoid precedence gotchas.
> '''Bad example:'''
> {{{
> #!python
> a = b and not c or d
> }}}
> '''Good example:'''
> {{{
> #!python
> a = (b and (not c)) or d
> }}}
> 1. You should do the optical layout in a such way that the code can be
> read correctly. If unsure, use parentheses.
> '''Bad example (actually incorrect code, see bug report 9073):'''
> {{{
> #!python
> return int \
> ( self.home_scope.TTA.Cluster.root.max_delay
> + preamble_bits
> +
> (start_of_frame_bits[self.home_scope.TTA.Cluster.root.physical_interface]
> + self.protocol.header_bits
> + databits
> + self.protocol.crc_bits
> ) * (1E6 / speed) # convert kbit/sec to nanoseconds/bit
> )
> }}}
> '''Good example:'''
> {{{
> #!python
> TTA = self.home_scope.TTA
> return int \
> ( TTA.Cluster.root.max_delay
> + ( preamble_bits
> + start_of_frame_bits [TTA.Cluster.root.physical_interface]
> + self.protocol.header_bits
> + databits
> + self.protocol.crc_bits
> )
> * (1E6 / speed) # convert kbit/sec to nanoseconds/bit
> )
> }}}
>
> == Avoid Numeric Indices ==
> 1. You should provide names for command line arguments instead of
> accessing them by index. You had best use the `Command_Line` module.
> 1. You shall extend lists and tuples by meaningful names, not by index.
> '''Bad Example:'''
> {{{
> #!python
> for t in self.type_list :
> c_name = "%s_%s (%s)" % (t[0], t[1], t[2])
> }}}
> '''Good Example:'''
> {{{
> #!python
> for (t_name, t_def, t_len) in self.type_list :
> c_name = "%s_%s (%s)" % (t_name, t_len, t_def)
> }}}
>
> == Avoid Long Lines ==
> 1. You shall start with operators to avoid EOL quotes.
> '''Example:'''
> {{{
> #!python
> mc_y_min = \
> ( (r_map.mchange_clear_y_min * 100)
> / (100 - r_map.mchange_y_min_percent)
> + r_map.frame_border_y
> )
> }}}
> 1. You should precompute a value to shorten the subsequent function call
> or expression and improve its readability.
> '''Example:'''
> {{{
> #!python
> y_ui_0 = y + self.frame_y_m
> y_ui_1 = y_ui_0 + self.ui_y_b
> self.userints [0].insert (canvas, x, y_ui_0, bx, 0, typ_label, self)
> self.userints [1].insert (canvas, x, y_ui_1, bx, 0, typ_label, self)
> }}}
> 1. You shall use one format string to assemble strings from several parts.
> '''Bad Example:'''
> {{{
> #!python
> result = (result + ", tt = %d us, IFG = %d us, idle = %d us"
> % (ttime, ifg, idle))
> }}}
> '''Good Example:'''
> {{{
> #!python
> result = \
> ( "%s, tt = %d us, IFG = %d us, idle = %d us"
> % (result, ttime, ifg, idle)
> )
> }}}
>
> == Exceptions ==
> 1. No strings shall be used as exceptions.
> 1. All exceptions shall end with `_Error` and follow the naming guidelines
> for classes.
> 1. All exceptions shall be derived from `StandardError`.
> '''Example:'''
> {{{
> #!python
> class TGW_Error (StandardError) :
> pass
> # end class TGW_Error
> }}}
> 1. There should be a file `Errors.py` in every package which defines a
> significant number of package-specific errors. The `Errors.py` file shall
> define all the exceptions specific to this package.
> 1. You shall catch only the exceptions you really know. However, sometimes
> you have to catch all Python-related exceptions, for example, when
> interpreting a string entered by the user.
> 1. If you want to print a traceback and go on, you should do as shown
> below. The import statement should be at the top of the file (and should
> thus not be conditional).
> '''Example:'''
> {{{
> #!python
> def test_it_again ():
> try :
> x.run (cmd)
> except KeyboardInterrupt :
> raise
> except I_Expect_Error :
> # Do whatever you have to do.
> except StandardError :
> import traceback
> traceback.print_exc ()
> # end def test_it_again
> }}}
>
> == Performance gotchas ==
> 1. Strings shall not be concatened by the `+` operator. Its repeated use
> in a loop can result in major performance bottlenecks.
> * Implicit concatenation shall be used to concatenate string literals.
> * The `%` operator shall be used to concatenate a fixed set of variable
> strings.
> * The `join` method shall be used to concatenate a dynamic set of
> strings.
> '''Bad Example:'''
> {{{
> #!python
> lit_cat = "first" + "second"
> message = str (n) + "errors " + x + "detected"
>
> result = ""
> for x in some_list :
> result += str (x)
> }}}
> '''Good Example:'''
> {{{
> #!python
> lit_cat = \
> ( "first"
> "second"
> )
> message = "%d errors %s detected" % (n, x)
> r = []
> for x in some_list :
> r.append (str (x))
> result = "".join (r)
> }}}
> '''Even better Example:'''
> {{{
> #!python
> lit_cat = "firstsecond"
> result = "".join ([str (x) for x in some_list])
> }}}
> 1. The `in` operator shall not be used for repeated membership tests in
> lists.
> 1. The `keys` method of dictionaries shall not be used for membership
> tests.
> '''Bad Example:'''
> {{{
> #!python
> if x in d.keys () :
> do_something ()
> }}}
> '''Good Example:'''
> {{{
> #!python
> if x in d :
> do_something ()
> }}}
>
> = Revisions of these Coding Guidelines =
>
> If you encounter an error or would like to change or add something to these
> coding guidelines, the following process applies:
>
> * write an email to your team leader
> * your request will be discussed in the Teamleader Meeting
> * in the Teamleader Meeting it also will be decided if and how to apply
> the changes
> * the changes will be made by one of the maintainers of these guidelines
> (currently AloisGoller and GerhardKönighofer) and announced to the public
> * several change requestes might be grouped, and handled en-bloc by the
> Teamleader Meeting
>
> == Ideas for extension of these guidelines ==
> * guidelines on ''generators''
> * only use doctest, since U_Test is far too complex
> * no 'else' for unit tests:
> '''Bad Example:'''
> {{{
> if __name__ != "__main" :
> TGW._Export ("*")
> else :
> import U_Test
>
> def _doc_test () :
> return U_Test.run_module_doc_tests ("_TGW.Menu")
> # end def _doc_test
>
> def _test () :
> _doc_test ()
> # end def _test
>
> _test ()
>
> ### __END__ TGW.Menu
> }}}
> '''Good Example:'''
> {{{
> if __name__ != "__main" :
> TGW._Export ("*")
> ### __END__ TGW.Menu
> }}}
>
> * pass arguments with name and value if the name and/or position is
> different in the called method
>
>
> == Proposal for middle-requirements ==
>
> Coding guidelines help to:
>
> * '''ensure readability''' -- any programmer should feel "at home" when
> reading any source code. Therefore, any source code needs to have a uniform
> structure. Moreover, it is essential to avoid difficult-to-read code
> fragments requiring a lot of time to be understood.
>
> * self-explanatory names
> * well structured code
> * short functions and methods
>
> * '''ensure maintainability''' -- a programmer should be able to
> understand and change a code fragment quickly and without reading the
> complete code and understanding every single detail. Therefore, it is
> important to accurately and consistently represent the logical structure of
> the code and to keep things local and modular. In addition to readability,
> it is also important that the change can be made easily and does not require
> to change the whole file.
>
> * comments commenting the why, not the how
> * no complicated or complex expressions
> * simple formatting rules so that lines easily can be extended
> * comments about future changes
>
> * '''facilitate automatization''' -- so that one can automatically rewrite
> code and generate documentation, e.g., API documentations and reference
> manuals; and that there is no need to manually cleanup things afterwards.
>
> * '''ensure correctness''' -- as well as intended behavior. The programmer
> thus can avoid or circumvent common errors and pitfalls. Correct and
> supporting documentation and test cases inlined in the source code also help
> to avoid misunderstandings and thus errors.
>
> * use parantheses
> * align "," and parantheses in multi-line statements
> * describe the signature and functionality in docstrings
> * use (various kinds of) unit tests
>
> * '''ensure conciseness''' -- so that a programmer can see (and then
> comprehend) as much as possible without navigating around. Moreover, to
> improve performance of the code. Conciseness contributes to efficiency as
> well as maintainability.
>
> * few blank lines
> * 80 columns max, so that 2 pages can be displayed on one screen
> * short names
> * refactor where possible and meaningful (i.e. Don't Repeat Yourself)
> * use / harness the syntactic features of the language
> _______________________________________________
> Mailing list: https://launchpad.net/~openerp-expert-framework
> Post to : openerp-expert-framework@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~openerp-expert-framework
> More help : https://help.launchpad.net/ListHelp
>
>
--
Sharoon Thomas
Business Analyst & ERP Consultant
http://bit.ly/5FAJKU
Follow ups
References