[MERGE] trunk
[odoo/odoo.git] / doc / project.rst
1 The OpenERP Web open-source project
2 ===================================
3
4 Getting involved
5 ----------------
6
7 Translations
8 ++++++++++++
9
10 Bug reporting
11 +++++++++++++
12
13 Source code repository
14 ++++++++++++++++++++++
15
16 Merge proposals
17 +++++++++++++++
18
19 Coding issues and coding conventions
20 ++++++++++++++++++++++++++++++++++++
21
22 Javascript coding
23 ~~~~~~~~~~~~~~~~~
24
25 These are a number of guidelines for javascript code. More than coding
26 conventions, these are warnings against potentially harmful or sub-par
27 constructs.
28
29 Ideally, you should be able to configure your editor or IDE to warn you against
30 these kinds of issues.
31
32 Use ``var`` for *all* declarations
33 **********************************
34
35 In javascript (as opposed to Python), assigning to a variable which does not
36 already exist and is not explicitly declared (via ``var``) will implicitly
37 create a global variable. This is bad for a number of reasons:
38
39 * It leaks information outside function scopes
40 * It keeps memory of previous run, with potentially buggy behaviors
41 * It may conflict with other functions with the same issue
42 * It makes code harder to statically check (via e.g. IDE inspectors)
43
44 .. note::
45     It is perfectly possible to use ``var`` in ``for`` loops:
46
47     .. code-block:: javascript
48
49         for (var i = 0; i < some_array.length; ++i) {
50             // code here
51         }
52
53     this is not an issue
54
55 All local *and global* variables should be declared via ``var``.
56
57 .. note:: generally speaking, you should not need globals in OpenERP Web: you
58           can just declare a variable local to your top-level function. This
59           way, if your widget/addon is instantiated several times on the same
60           page (because it's used in embedded mode) each instance will have its
61           own internal but global-to-its-objects data.
62
63 Do not leave trailing commas in object literals
64 ***********************************************
65
66 While it is legal to leave trailing commas in Python dictionaries, e.g.
67
68 .. code-block:: python
69
70     foo = {
71         'a': 1,
72         'b': 2,
73     }
74
75 and it's valid in ECMAScript 5 and most browsers support it in Javascript, you
76 should *never* use trailing commas in Javascript object literals:
77
78 * Internet Explorer does *not* support trailing commas (at least until and
79   including Internet Explorer 8), and trailing comma will cause hard-to-debug
80   errors in it
81
82 * JSON does not accept trailing comma (it is a syntax error), and using them
83   in object literals puts you at risks of using them in literal JSON strings
84   as well (though there are few reasons to write JSON by hand)
85
86 *Never* use ``for … in`` to iterate on arrays
87 *********************************************
88
89 :ref:`Iterating over an object with for…in is a bit tricky already
90 <for-in-iteration>`, it is far more complex than in Python (where it Just
91 Works™) due to the interaction of various Javascript features, but to iterate
92 on arrays it becomes downright deadly and errorneous: ``for…in`` really
93 iterates over an *object*'s *properties*.
94
95 With an array, this has the following consequences:
96
97 * It does not necessarily iterate in numerical order, nor does it iterate in
98   any kind of set order. The order is implementation-dependent and may vary
99   from one run to the next depending on a number of reasons and implementation
100   details.
101 * If properties are added to an array, to ``Array.prototype`` or to
102   ``Object.prototype`` (the latter two should not happen in well-behaved
103   javascript code, but you never know...) those properties *will* be iterated
104   over by ``for…in``. While ``Object.hasOwnProperty`` will guard against
105   iterating prototype properties, they will not guard against properties set
106   on the array instance itself (as memoizers for instance).
107
108   Note that this includes setting negative keys on arrays.
109
110 For this reason, ``for…in`` should **never** be used on array objects. Instead,
111 you should use either a normal ``for`` or (even better, unless you have
112 profiled the code and found a hotspot) one of Underscore's array iteration
113 methods (`_.each`_, `_.map`_, `_.filter`_, etc...).
114
115 Underscore is guaranteed to be bundled and available in OpenERP Web scopes.
116
117 .. _for-in-iteration:
118
119 Use ``hasOwnProperty`` when iterating on an object with ``for … in``
120 ********************************************************************
121
122 ``for…in`` is Javascript's built-in facility for iterating over and object's
123 properties.
124
125 `It is also fairly tricky to use`_: it iterates over *all* non-builtin
126 properties of your objects [#]_, which includes methods of an object's class.
127
128 As a result, when iterating over an object with ``for…in`` the first line of
129 the body *should* generally be a call to `Object.hasOwnProperty`_. This call
130 will check whether the property was set directly on the object or comes from
131 the object's class:
132
133 .. code-block:: javascript
134
135     for(var key in ob) {
136         if (!ob.hasOwnProperty(key)) {
137             // comes from ob's class
138             continue;
139         }
140         // do stuff with key
141     }
142
143 Since properties can be added directly to e.g. ``Object.prototype`` (even
144 though it's usually considered bad style), you should not assume you ever know
145 which properties ``for…in`` is going to iterate over.
146
147 An alternative is to use Underscore's iteration methods, which generally work
148 over objects as well as arrays:
149
150 Instead of
151
152 .. code-block:: javascript
153
154     for (var key in ob) {
155         if (!ob.hasOwnProperty(key)) { continue; }
156         var value = ob[key];
157         // Do stuff with key and value
158     }
159
160 you could write:
161
162 .. code-block:: javascript
163
164     _.each(ob, function (value, key) {
165         // do stuff with key and value
166     });
167
168 and not worry about the details of the iteration: underscore should do the
169 right thing for you on its own [#]_.
170
171 Writing documentation
172 +++++++++++++++++++++
173
174 The OpenERP Web project documentation uses Sphinx_ for the literate
175 documentation (this document for instance), the development guides
176 (for Python and Javascript alike) and the Python API documentation
177 (via autodoc_).
178
179 For the Javascript API, documentation should be written using the
180 `JsDoc Toolkit`_.
181
182 Guides and main documentation
183 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184
185 The meat and most important part of all documentation. Should be
186 written in plain English, using reStructuredText_ and taking advantage
187 of `Sphinx's extensions`_, especially `cross-references`_.
188
189 Python API Documentation
190 ~~~~~~~~~~~~~~~~~~~~~~~~
191
192 All public objects in Python code should have a docstring written in
193 RST, using Sphinx's `Python domain`_ [#]_:
194
195 * Functions and methods documentation should be in their own
196   docstring, using Sphinx's `info fields`_
197
198   For parameters types, built-in and stdlib types should be using the
199   combined syntax:
200
201   .. code-block:: restructuredtext
202
203       :param dict foo: what the purpose of foo is
204
205   unless a more extensive explanation needs to be given (e.g. the
206   specification that the input should be a list of 3-tuple needs to
207   use ``:type:`` even though all types involved are built-ins). Any
208   other type should be specified in full using the ``:type:`` field
209
210   .. code-block:: restructuredtext
211
212       :param foo: what the purpose of foo is
213       :type foo: some.addon.Class
214
215   Mentions of other methods (including within the same class), modules
216   or types in descriptions (of anything, including parameters) should
217   be cross-referenced.
218
219 * Classes should likewise be documented using their own docstring, and
220   should include the documentation of their construction (``__init__``
221   and ``__new__``), using the `info fields`_  as well.
222
223 * Attributes (class and instance) should be documented in their
224   class's docstring via the ``.. attribute::`` directive, following
225   the class's own documentation.
226
227 * The relation between modules and module-level attributes is similar:
228   modules should be documented in their own docstring, public module
229   attributes should be documented in the module's docstring using the
230   ``.. data::`` directive.
231
232 Javascript API documentation
233 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234
235 Javascript API documentation uses JsDoc_, a javascript documentation
236 toolkit with a syntax similar to (and inspired by) JavaDoc's.
237
238 Due to limitations of JsDoc, the coding patterns in OpenERP Web and
239 the Sphinx integration, there are a few peculiarities to be aware of
240 when writing javascript API documentation:
241
242 * Namespaces and classes *must* be explicitly marked up even if they
243   are not documented, or JsDoc will not understand what they are and
244   will not generate documentation for their content.
245
246   As a result, the bare minimum for a namespace is:
247
248   .. code-block:: javascript
249
250       /** @namespace */
251       foo.bar.baz = {};
252
253   while for a class it is:
254
255   .. code-block:: javascript
256
257       /** @class */
258       foo.bar.baz.Qux = [...]
259
260 * Because the OpenERP Web project uses `John Resig's Class
261   implementation`_ instead of direct prototypal inheritance [#]_,
262   JsDoc fails to infer class scopes (and constructors or super
263   classes, for that matter) and has to be told explicitly.
264
265   See :ref:`js-class-doc` for the complete rundown.
266
267 * Much like the JavaDoc, JsDoc does not include a full markup
268   language. Instead, comments are simply marked up in HTML.
269
270   This has a number of inconvenients:
271
272   * Complex documentation comments become nigh-unreadable to read in
273     text editors (as opposed to IDEs, which may handle rendering
274     documentation comments on the fly)
275
276   * Though cross-references are supported by JsDoc (via ``@link`` and
277     ``@see``), they only work within the JsDoc
278
279   * More general impossibility to integrate correctly with Sphinx, and
280     e.g. reference JavaScript objects from a tutorial, or have all the
281     documentation live at the same place.
282
283   As a result, JsDoc comments should be marked up using RST, not
284   HTML. They may use Sphinx's cross-references as well.
285
286 .. _js-class-doc:
287
288 Documenting a Class
289 *******************
290
291 The first task when documenting a class using JsDoc is to *mark* that
292 class, so JsDoc knows it can be used to instantiate objects (and, more
293 importantly as far as it's concerned, should be documented with
294 methods and attributes and stuff).
295
296 This is generally done through the ``@class`` tag, but this tag has a
297 significant limitation: it "believes" the constructor and the class
298 are one and the same [#]_. This will work for constructor-less
299 classes, but because OpenERP Web uses Resig's class the constructor is
300 not the class itself but its ``init()`` method.
301
302 Because this pattern is common in modern javascript code bases, JsDoc
303 supports it: it is possible to mark an arbitrary instance method as
304 the *class specification* by using the ``@constructs`` tag.
305
306 .. warning:: ``@constructs`` is a class specification in and of
307     itself, it *completely replaces* the class documentation.
308
309     Using both a class documentation (even without ``@class`` itself)
310     and a constructor documentation is an *error* in JsDoc and will
311     result in incorrect behavior and broken documentation.
312
313 The second issue is that Resig's class uses an object literal to
314 specify instance methods, and because JsDoc does not know anything
315 about Resig's class, it does not know about the role of the object
316 literal.
317
318 As with constructors, though, JsDoc provides a pluggable way to tell
319 it about methods: the ``@lends`` tag. It specifies that the object
320 literal "lends" its properties to the class being built.
321
322 ``@lends`` must be specified right before the opening brace of the
323 object literal (between the opening paren of the ``#extend`` call and
324 the brace), and takes the full qualified name of the class being
325 created as a parameter, followed by the character ``#`` or by
326 ``.prototype``. This latter part tells JsDoc these are instance
327 methods, not class (static) methods..
328
329 Finally, specifying a class's superclass is done through the
330 ``@extends`` tag, which takes a fully qualified class name as a
331 parameter.
332
333 Here are a class without a constructor, and a class with one, so that
334 everything is clear (these are straight from the OpenERP Web source,
335 with the descriptions and irrelevant atttributes stripped):
336
337 .. code-block:: javascript
338
339     /**
340      * <Insert description here, not below>
341      *
342      * @class
343      * @extends openerp.base.search.Field
344      */
345     openerp.base.search.CharField = openerp.base.search.Field.extend(
346         /** @lends openerp.base.search.CharField# */ {
347             // methods here
348     });
349
350 .. code-block:: javascript
351
352     openerp.base.search.Widget = openerp.base.Controller.extend(
353         /** @lends openerp.base.search.Widget# */{
354         /**
355          * <Insert description here, not below>
356          *
357          * @constructs
358          * @extends openerp.base.Controller
359          *
360          * @param view the ancestor view of this widget
361          */
362         init: function (view) {
363             // construction of the instance
364         },
365         // bunch of other methods
366     });
367
368 OpenERP Web over time
369 ---------------------
370
371 Release process
372 +++++++++++++++
373
374 OpenSUSE packaging: http://blog.lowkster.com/2011/04/packaging-python-packages-in-opensuse.html
375
376 Roadmap
377 +++++++
378
379 Release notes
380 +++++++++++++
381
382 .. [#] More precisely, it iterates over all *enumerable* properties. It just
383        happens that built-in properties (such as ``String.indexOf`` or
384        ``Object.toString``) are set to non-enumerable.
385
386        The enumerability of a property can be checked using
387        `Object.propertyIsEnumeable`_.
388
389        Before ECMAScript 5, it was not possible for user-defined properties
390        to be non-enumerable in a portable manner. ECMAScript 5 introduced
391        `Object.defineProperty`_ which lets user code create non-enumerable
392        properties (and more, read-only properties for instance, or implicit
393        getters and setters). However, support for these is not fully complete
394        at this point, and they are not being used in OpenERP Web code anyway.
395
396 .. [#] While using underscore is generally the preferred method (simpler,
397        more reliable and easier to write than a *correct* ``for…in``
398        iteration), it is also probably slower (due to the overhead of
399        calling a bunch of functions).
400
401        As a result, if you profile some code and find out that an underscore
402        method adds unacceptable overhead in a tight loop, you may want to
403        replace it with a ``for…in`` (or a regular ``for`` statement for
404        arrays).
405
406 .. [#] Because Python is the default domain, the ``py:`` markup prefix
407        is optional and should be left out.
408
409 .. [#] Resig's Class still uses prototypes under the hood, it doesn't
410        reimplement its own object system although it does add several
411        helpers such as the ``_super()`` instance method.
412
413 .. [#] Which is the case in normal Javascript semantics. Likewise, the
414        ``.prototype`` / ``#`` pattern we will see later on is due to
415        JsDoc defaulting to the only behavior it can rely on: "normal"
416        Javascript prototype-based type creation.
417
418 .. _reStructuredText:
419     http://docutils.sourceforge.net/rst.html
420 .. _Sphinx:
421     http://sphinx.pocoo.org/index.html
422 .. _Sphinx's extensions:
423     http://sphinx.pocoo.org/markup/index.html
424 .. _Python domain:
425     http://sphinx.pocoo.org/domains.html#the-python-domain
426 .. _info fields:
427     http://sphinx.pocoo.org/domains.html#info-field-lists
428 .. _autodoc:
429     http://sphinx.pocoo.org/ext/autodoc.html
430         ?highlight=autodoc#sphinx.ext.autodoc
431 .. _cross-references:
432     http://sphinx.pocoo.org/markup/inline.html#xref-syntax
433 .. _JsDoc:
434 .. _JsDoc Toolkit:
435     http://code.google.com/p/jsdoc-toolkit/
436 .. _John Resig's Class implementation:
437     http://ejohn.org/blog/simple-javascript-inheritance/
438 .. _\_.each:
439     http://documentcloud.github.com/underscore/#each
440 .. _\_.map:
441     http://documentcloud.github.com/underscore/#map
442 .. _\_.filter:
443     http://documentcloud.github.com/underscore/#select
444 .. _It is also fairly tricky to use:
445     https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in#Description
446 .. _Object.propertyIsEnumeable:
447     https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable
448 .. _Object.defineProperty:
449     https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
450 .. _Object.hasOwnProperty:
451     https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/hasOwnProperty