EDNA Coding Conventions
The naming convention is important in order to keep the code in the EDNA project homogeneous, and thus facilitate the reading of the code by other developers.
General rule: keep the name as descriptive as possible, unless they become too long.
Each file should contain an header with the licensing and copyrights information, for example looking like this:
# # Project: The EDNA Kernel # http://www.edna-site.org # # File: "$Id: EDPlugin.py 1194 2010-03-02 09:54:26Z svensson $" # # Copyright (C) 2008-2009 European Synchrotron Radiation Facility # Grenoble, France # # Principal authors: Marie-Francoise Incardona (email@example.com) # Olof Svensson (firstname.lastname@example.org) # Jerome Kieffer (Kieffer@esrf.fr) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 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 Lesser General Public License for more details. # # You should have received a copy of the GNU General Public License # and the GNU Lesser General Public License along with this program. # If not, see <http://www.gnu.org/licenses/>. #
For the moment, this is the copyright and licence statement of all the kernel source files and many plugins.
A plugin author can choose another copyright and/or licence statement, however a header must always exist.
It's also a good idea to add the following definitions:
__authors__ = ["Marie-Francoise Incardona", "Olof Svensson", "Jerome Kieffer"] __contact__ = "email@example.com" __license__ = "LGPLv3+" __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
Naming convention is important in any programming language but maybe especially so in Python due to its lack of needing to declare variables. Hence a Python variable can be of any type! When reading the code it is very often only possible to know the type of a variable by looking at its name, if the type is expressed by the name.
The class names should begin with ED (like 'EDNA') and should be explicit enough to have an idea of the class purpose and its hierarchy. Of course, this rule could have some limitations due to the length of class names. Examples:
- EDPluginExec extends the class EDPlugin
- EDPluginExecProcess extends the class EDPluginExec
- EDPluginExecProcessScript extends the class EDPluginExecProcess
- EDPluginMOSFLMv01 extends the class EDPluginExecProcessScript, however it is not called EDPluginExecProcessScriptMOSFLMv01 since it's too long.
The local variables names should be constructed with a prefix that represents the type of the variable. Examples:
- Instance of EDNA classes EDPlugin: edPluginName
- Integer variable: iNumberOfPoints
- Floating point variable: fTemperature (Floating point numbers are implemented using double in C, see the Python documentation about built-in types.)
- Boolean variable: bSuccess
- Python type variables: strName, dictHeader, listLines etc.
The variable names for methods should start with a "_", e.g.: def myMethod(self, _strName).
Class and instance variables
In order to make the code robust the best practise is to make all class and instance variables private, and grant access to these variables via setters and getters. This will make the class code easier to evolve without breaking code depending on the class. In Python a class variable is private if it starts with two "__", e.g. self.__strName. The same naming convention as for local variables should be used.
If the variable cannot be made private the name should begin with the prefix “m_” (like member), e.g. m_strName.
The doc strings are excellent sources of information - if used! Therefore it's important to write concise and accurate doc strings for all classes and class methods. Here's an example of a doc string (EDParallelExecute.watch_directories):
def watch_directories(self, _bNewerOnly=False): """ Continuously monitors the paths and their subdirectories for changes. If any files or directories are modified, the callable function ( here the method self.runEdnaFunction() ) is called with a list of the modified paths of both files and directories. This function can return a Boolean value for rescanning; if it returns True, the directory tree will be rescanned without calling the function for any found changes. (This is so this function can write changes into the tree and prevent itself from being immediately called again.) @param _bNewerOnly : Do you want to process only newer files @type _bNewerOnly : Boolean Basic principle: pyDictAllFiles is a dictionary mapping paths to modification times. We repeatedly crawl through the directory tree rooted at 'path', doing a stat() on each file and comparing the modification time. """
- The global imports (import *) should be avoided
A sub class should override methods from the superclass only if the subclass provides a specific implementation of the superclass method. Overriding a superclass method that simply calls the parent method is not necessary.
Setting up Eclipse PyDev for automatic code formatting
The Eclipse PyDev plugin has a very useful code formatter. In order to keep the coding style homogeneous in the EDNA project please set it to the following (Eclipse->Window->Preferences->PyDev->Editor->Code Style->Code Formatter):