Revision a41a1eec

b/Makefile.am
543 543
	doc/design-upgrade.rst \
544 544
	doc/design-virtual-clusters.rst \
545 545
	doc/design-x509-ca.rst \
546
	doc/dev-codestyle.rst \
546 547
	doc/devnotes.rst \
547 548
	doc/glossary.rst \
548 549
	doc/hooks.rst \
b/doc/dev-codestyle.rst
1
Code style guide
2
================
3

  
4
Python
5
------
6

  
7
.. highlight:: python
8

  
9
These are a few guidelines for Ganeti code and documentation.
10

  
11
In simple terms: try to stay consistent with the existing code. `PEP 8`_ says:
12

  
13
.. _PEP 8: http://www.python.org/dev/peps/pep-0008/
14

  
15
  A style guide is about consistency. Consistency with this style guide is
16
  important. Consistency within a project is more important. Consistency
17
  within one module or function is most important.
18

  
19
.. note::
20

  
21
  You might also want to take a look at the `Google style guide`_, since we
22
  have some things in common with it.
23

  
24
.. _Google style guide: http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
25

  
26
Indentation
27
~~~~~~~~~~~
28
In general, always indent using two (2) spaces and don't use tabs.
29

  
30
The two spaces should always be relative to the previous level of indentation,
31
even if this means that the final number of spaces is not a multiple of 2.
32

  
33
When going on a new line inside an open parenthesis, align with the content of
34
the parenthesis on the previous line.
35

  
36
Valid example::
37

  
38
  v = (somevalue,
39
       a_function([
40
         list_elem, # 7 spaces, but 2 from the previous indentation level
41
         another_elem,
42
       ]))
43

  
44
Formatting strings
45
~~~~~~~~~~~~~~~~~~
46
Always use double quotes (``""``), never single quotes (``''``), except for
47
existing code. Examples for formatting strings::
48

  
49
  var = "value"
50

  
51
  # Note: The space character is always on the second line
52
  var = ("The quick brown fox jumps over the lazy dog. The quick brown fox"
53
         " jumps over the lazy dog. The quick brown fox jumps over the lazy"
54
         " dog.")
55

  
56
  fn("The quick brown fox jumps over the lazy dog. The quick brown fox jumps"
57
     " over the lazy dog.")
58

  
59
  fn(constants.CONFIG_VERSION,
60
     ("The quick brown fox jumps over the lazy dog. The quick brown fox"
61
      " jumps over the lazy dog. The quick brown fox jumps over the lazy"
62
      " dog."))
63

  
64
Don't format strings like this::
65

  
66
  # Don't use single quotes
67
  var = 'value'
68

  
69
  # Don't use backslash for line continuation
70
  var = "The quick brown fox jumps over the lazy dog. The quick brown fox"\
71
        " jumps over the lazy dog."
72

  
73
  # Space character goes to the beginning of a new line
74
  var = ("The quick brown fox jumps over the lazy dog. The quick brown fox "
75
         "jumps over the lazy dog. The quick brown fox jumps over the lazy "
76
         "dog.")
77

  
78
Formatting sequences
79
~~~~~~~~~~~~~~~~~~~~
80
Built-in sequence types are list (``[]``), tuple (``()``) and dict (``{}``).
81
When splitting to multiple lines, each item should be on its own line and a
82
comma must be added on the last line. Don't write multiline dictionaries in
83
function calls, except when it's the only parameter. Always indent items by
84
two spaces.
85

  
86
::
87

  
88
  # Short lists
89
  var = ["foo", "bar"]
90
  var = ("foo", "bar")
91

  
92
  # Longer sequences and dictionary
93
  var = [
94
    constants.XYZ_FILENAME_EXTENSION,
95
    constants.FOO_BAR_BAZ,
96
    ]
97
  var = {
98
    "key": func(),
99
    "otherkey": None,
100
    }
101

  
102
  # Multiline tuples as dictionary values
103
  var = {
104
    "key":
105
      ("long value taking the whole line, requiring you to go to a new one",
106
       other_value),
107
  }
108

  
109
  # Function calls
110
  var = frozenset([1, 2, 3])
111
  var = F({
112
    "xyz": constants.XYZ,
113
    "abc": constants.ABC,
114
    })
115

  
116
  # Wrong
117
  F(123, "Hello World",
118
    { "xyz": constants.XYZ })
119

  
120
We consider tuples as data structures, not containers. So in general please
121
use lists when dealing with a sequence of homogeneous items, and tuples when
122
dealing with heterogeneous items.
123

  
124
Passing arguments
125
~~~~~~~~~~~~~~~~~
126
Positional arguments must be passed as positional arguments, keyword arguments
127
must be passed as keyword arguments. Everything else will be difficult to
128
maintain.
129

  
130
::
131

  
132
  # Function signature
133
  def F(data, key, salt=None, key_selector=None):
134
    pass
135

  
136
  # Yes
137
  F("The quick brown fox", "123456")
138
  F("The quick brown fox", "123456", salt="abc")
139
  F("The quick brown fox", "123456", key_selector="xyz")
140
  F("The quick brown fox", "123456", salt="foo", key_selector="xyz")
141

  
142
  # No: Passing keyword arguments as positional argument
143
  F("The quick brown fox", "123456", "xyz", "bar")
144

  
145
  # No: Passing positional arguments as keyword argument
146
  F(salt="xyz", data="The quick brown fox", key="123456", key_selector="xyz")
147

  
148
Docstrings
149
~~~~~~~~~~
150

  
151
.. note::
152

  
153
  `PEP 257`_ is the canonical document, unless epydoc overrules it (e.g. in how
154
  to document the type of an argument).
155

  
156
For docstrings, the recommended format is epytext_, to be processed via
157
epydoc_. There is an ``apidoc`` target that builds the documentation and puts it
158
into the doc/api subdir. Note that we currently use epydoc version 3.0.
159

  
160
.. _PEP 257: http://www.python.org/dev/peps/pep-0257/
161
.. _epytext: http://epydoc.sourceforge.net/manual-epytext.html
162
.. _epydoc: http://epydoc.sourceforge.net/
163

  
164
Note that one-line docstrings are only accepted in the unittests.
165

  
166
Rules for writing the docstrings (mostly standard Python rules):
167

  
168
* the docstring should start with a sentence, with punctuation at the end,
169
  summarizing the the aim of what is being described. This sentence cannot be
170
  longer than one line
171
* the second line should be blank
172
* afterwards the rest of the docstring
173
* special epytext tags should come at the end
174
* multi-line docstrings must finish with an empty line
175
* do not try to make a table using lots of whitespace
176
* use ``L{}`` and ``C{}`` where appropriate
177

  
178
Here's an example::
179

  
180
  def fn(foo, bar):
181
    """Compute the sum of foo and bar.
182

  
183
    This functions builds the sum of foo and bar. It's a simple function.
184

  
185
    @type foo: int
186
    @param foo: First parameter.
187
    @type bar: float
188
    @param bar: The second parameter. This line is longer
189
      to show wrapping.
190
    @rtype: float
191
    @return: the sum of the two numbers
192

  
193
    """
194
    return foo + bar
195

  
196
Some rules of thumb which should be applied with good judgement on a case-to-
197
case basis:
198

  
199
* If the meaning of parameters is already obvious given its name and the
200
  methods description, don't document it again. Just add a ``@type`` tag.
201
* Refer to the base methods documentation when overwriting methods. Only
202
  document more if it applies to the current subclass only, or if you want to
203
  clarify on the meaning of parameters for the special subclass.
204

  
205
Rules for classes and modules
206
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207
As `PEP 257`_ says, the docstrings of classes should document their attributes
208
and the docstrings of modules should shortly document the exported
209
functions/variables/etc.
210

  
211
See for example the pydoc output for the ``os`` or ``ConfigParser`` standard
212
modules.
213

  
214
Haskell
215
-------
216

  
217
.. highlight:: haskell
218

  
219
The most important consideration is, as usual, to stay consistent with the
220
existing code.
221

  
222
As there's no "canonical" style guide for Haskell, this code style has been
223
inspired from a few online resources, including the style guide for the
224
`Snap framework`_, `this style guide`_ and `this other style guide`_.
225

  
226
.. _Snap framework: http://snapframework.com/docs/style-guide
227
.. _this style guide: https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md
228
.. _this other style guide: http://www.cs.caltech.edu/courses/cs11/material/haskell/misc/haskell_style_guide.html
229

  
230
Files
231
~~~~~
232
Use ordinary, non-`literate`_ Haskell ``.hs`` files.
233

  
234
.. _literate: http://www.haskell.org/haskellwiki/Literate_programming
235

  
236
Use proper copyright headers, and proper Haddock style documentation headers::
237

  
238
  {-| Short module summary.
239

  
240
  Longer module description.
241

  
242
  -}
243

  
244
  {-
245

  
246
  Copyright (C) ...
247

  
248
  This program is free software ...
249

  
250
  -}
251

  
252
If there are module-level pragmas add them right at the top, before the short
253
summary.
254

  
255
Imports
256
~~~~~~~
257
Imports should be grouped into the following groups and inside each group they
258
should be sorted alphabetically:
259

  
260
1. standard library imports
261
2. third-party imports
262
3. local imports
263

  
264
It is allowed to use qualified imports with short names for:
265

  
266
* standard library (e.g. ``import qualified Data.Map as M``)
267
* local imports (e.g. ``import qualified Ganeti.Constants as C``), although
268
  this form should be kept to a minimum
269

  
270
Indentation
271
~~~~~~~~~~~
272
Use only spaces, never tabs. Indentation level is 2 characters. For Emacs,
273
this means setting the variable ``haskell-indent-offset`` to 2.
274

  
275
Line length should be at most 78 chars, and 72 chars inside comments.
276

  
277
Use indentation-based structure, and not braces/semicolons.
278

  
279
.. note::
280

  
281
  Special indendation of if/then/else construct
282

  
283
  For the ``do`` notation, the ``if-then-else`` construct has a non-intuitive
284
  behaviour. As such, the indentation of ``if-then-else`` (both in ``do``
285
  blocks and in normal blocks) should be as follows::
286

  
287
    if condition
288
      then expr1
289
      else expr2
290

  
291
  i.e. indent the then/else lines with another level. This can be accomplished
292
  in Emacs by setting the variable ``haskell-indent-thenelse`` to 2 (from the
293
  default of zero).
294

  
295
If you have more than one line of code please newline/indent after the "=". Do
296
`not` do::
297

  
298
  f x = let y = x + 1
299
        in  y
300

  
301
Instead do::
302

  
303
  f x =
304
    let y = x + 1
305
    in  y
306

  
307
or if it is just one line::
308

  
309
  f x = x + 1
310

  
311
Multiline strings
312
~~~~~~~~~~~~~~~~~
313
Multiline strings are created by closing a line with a backslash and starting
314
the following line with a backslash, keeping the indentation level constant.
315
Whitespaces go on the new line, right after the backslash.
316

  
317
::
318

  
319
  longString :: String
320
  longString = "This is a very very very long string that\
321
               \ needs to be split in two lines"
322

  
323
Data declarations
324
~~~~~~~~~~~~~~~~~
325
.. warning::
326
  Note that this is different from the Python style!
327

  
328
When declaring either data types, or using list literals, etc., the columns
329
should be aligned, and for lists use a comma at the start of the line, not at
330
the end. Examples::
331

  
332
  data OpCode = OpStartupInstance ...
333
              | OpShutdownInstance ...
334
              | ...
335

  
336
  data Node = Node { name :: String
337
                   , ip   :: String
338
                   , ...
339
                   }
340

  
341
  myList = [ value1
342
           , value2
343
           , value3
344
           ]
345

  
346
The choice of whether to wrap the first element or not is up to you; the
347
following is also allowed::
348

  
349
  myList =
350
    [ value1
351
    , value2
352
    ]
353

  
354
White space
355
~~~~~~~~~~~
356
Like in Python, surround binary operators with one space on either side. Do no
357
insert a space after a lamda::
358

  
359
  -- bad
360
  map (\ n -> ...) lst
361
  -- good
362
  foldl (\x y -> ...) ...
363

  
364
Use a blank line between top-level definitions, but no blank lines between
365
either the comment and the type signature or between the type signature and
366
the actual function definition.
367

  
368
.. note::
369
  Ideally it would be two blank lines between top-level definitions, but the
370
  code only has one now.
371

  
372
As always, no trailing spaces. Ever.
373

  
374
Spaces after comma
375
******************
376

  
377
Instead of::
378

  
379
  ("a","b")
380

  
381
write::
382

  
383
  ("a", "b")
384

  
385
Naming
386
~~~~~~
387
Functions should be named in mixedCase style, and types in CamelCase. Function
388
arguments and local variables should be mixedCase.
389

  
390
When using acronyms, ones longer than 2 characters should be typed capitalised,
391
not fully upper-cased (e.g. ``Http``, not ``HTTP``).
392

  
393
For variable names, use descriptive names; it is only allowed to use very
394
short names (e.g. ``a``, ``b``, ``i``, ``j``, etc.) when:
395

  
396
* the function is trivial, e.g.::
397

  
398
    sum x y = x + y
399

  
400
* we talk about some very specific cases, e.g.
401
  iterators or accumulators in folds::
402

  
403
    map (\v -> v + 1) lst
404

  
405
* using ``x:xs`` for list elements and lists, etc.
406

  
407
In general, short/one-letter names are allowed when we deal with polymorphic
408
values; for example the standard map definition from Prelude::
409

  
410
  map :: (a -> b) -> [a] -> [b]
411
  map _ []     = []
412
  map f (x:xs) = f x : map f xs
413

  
414
In this example, neither the ``a`` nor ``b`` types are known to the map
415
function, so we cannot give them more explicit names. Since the body of the
416
function is trivial, the variables used are longer.
417

  
418
However, if we deal with explicit types or values, their names should be
419
descriptive.
420

  
421
.. todo: add a nice example here.
422

  
423
Finally, the naming should look familiar to people who just read the
424
Prelude/standard libraries.
425

  
426
Naming for updated values
427
*************************
428

  
429
.. highlight:: python
430

  
431
Since one cannot update a value in Haskell, this presents a particular problem
432
on the naming of new versions of the same value. For example, the following
433
code in Python::
434

  
435
  def failover(pri, sec, inst):
436
    pri.removePrimary(inst)
437
    pri.addSecondary(inst)
438
    sec.removeSecondary(inst)
439
    sec.addPrimary(inst)
440

  
441
.. highlight:: haskell
442

  
443
becomes in Haskell something like the following::
444

  
445
  failover pri sec inst =
446
    let pri'  = removePrimary pri inst
447
        pri'' = addSecondary pri' inst
448
        sec'  = removeSecondary sec inst
449
        sec'' = addPrimary sec' inst
450
    in (pri'', sec'')
451

  
452
When updating values, one should add single quotes to the name for up to three
453
new names (e.g. ``inst``, ``inst'``, ``inst''``, ``inst'''``) and otherwise
454
use numeric suffixes (``inst1``, ``inst2``, ``inst3``, ..., ``inst8``), but
455
that many updates is already bad style and thus should be avoided.
456

  
457
Type signatures
458
~~~~~~~~~~~~~~~
459

  
460
Always declare types for functions (and any other top-level bindings).
461

  
462
If in doubt, feel free to declare the type of the variables/bindings in a
463
complex expression; this usually means the expression is too complex, however.
464

  
465
Similarly, provide Haddock-style comments for top-level definitions.
466

  
467
Parentheses, point free style
468
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
469

  
470
Prefer the so-called point-free style to extra parentheses::
471

  
472
  -- bad
473
  let a = f ( g ( h x) )
474
  -- better
475
  let b = f $ g $ h x
476
  -- best
477
  let c = f . g . h $ x
478

  
479
Language features
480
~~~~~~~~~~~~~~~~~
481

  
482
Extensions
483
**********
484

  
485
It is recommended to keep the use of extensions to a minimum, so that the code
486
can be understood even if one is familiar with just Haskel98/Haskell2010. That
487
said, some extensions are very common and useful, so they are recommended:
488

  
489
* `Bang patterns`_: useful when you want to enforce strict evaluation (and better
490
  than repeated use of ``seq``)
491
* CPP: a few modules need this in order to account for configure-time options;
492
  don't overuse it, since it breaks multi-line strings
493
* `Template Haskell`_: we use this for automatically deriving JSON instances and
494
  other similar boiler-plate
495

  
496
.. _Bang patterns: http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html
497
.. _Template Haskell: http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html
498

  
499
Such extensions should be declared using the ``Language`` pragma::
500

  
501
  {-# Language BangPatterns #-}
502

  
503
  {-| This is a small module... -}
504

  
505
Comments
506
********
507

  
508
Always use proper sentences; start with a capital letter and use punctuation
509
in top level comments::
510

  
511
  -- | A function that does something.
512
  f :: ...
513

  
514
For inline comments, start with a capital letter but no ending punctuation.
515
Furthermore, align the comments together with a 2-space width from the end of
516
the item being commented::
517

  
518
  data Maybe a = Nothing  -- ^ Represents empty container
519
               | Just a   -- ^ Represents a single value
520

  
521
The comments should be clear enough so that one doesn't need to look at the
522
code to understand what the item does/is.
523

  
524
Use ``-- |`` to write doc strings rather than bare comment with ``--``.
525

  
526
Tools
527
*****
528

  
529
We generate the API documentation via Haddock, and as such the comments should
530
be correct (syntax-wise) for it. Use markup, but sparingly.
531

  
532
We use hlint_ as a lint checker; the code is currently lint-clean, so you must
533
not add any warnings/errors.
534

  
535
.. _hlint: http://community.haskell.org/~ndm/darcs/hlint/hlint.htm
536

  
537
Use these two commands during development::
538

  
539
  make hs-apidoc
540
  make hlint
541

  
542
QuickCheck best practices
543
*************************
544

  
545
If you have big type that takes time to generate and several properties to
546
test on that, by default 500 of those big instances are generated for each
547
property. In many cases, it would be sufficient to only generate those 500
548
instances once and test all properties on those. To do this, create a property
549
that uses ``conjoin`` to combine several properties into one. Use
550
``printTestCase`` to add expressive error messages. For example::
551

  
552
  prop_myMegaProp :: myBigType -> Property
553
  prop_myMegaProp b =
554
    conjoin
555
      [ printTestCase
556
          ("Something failed horribly here: " ++ show b) (subProperty1 b)
557
      , printTestCase
558
          ("Something else failed horribly here: " ++ show b)
559
          (subProperty2 b)
560
      , -- more properties here ...
561
      ]
562

  
563
  subProperty1 :: myBigType -> Bool
564
  subProperty1 b = ...
565

  
566
  subProperty2 :: myBigType -> Property
567
  subProperty2 b = ...
568

  
569
  ...
570

  
571
Maybe Generation
572
''''''''''''''''
573

  
574
Use ``genMaybe genSomething`` to create ``Maybe`` instances of something
575
including some ``Nothing`` instances.
576

  
577
Use ``Just <$> genSomething`` to generate only ``Just`` instances of
578
something.
579

  
580
String Generation
581
'''''''''''''''''
582

  
583
To generate strings, consider using ``genName`` instead of ``arbitrary``.
584
``arbitrary`` has the tendency to generate strings that are too long.
b/doc/devnotes.rst
116 116
PYTHONPATH is customised correctly). As such, in general it's
117 117
recommended to use a "clean" machine for ganeti development.
118 118

  
119
Style guide
120
-----------
121

  
122
Please adhere to the :doc:`dev-codestyle` while writing code for Ganeti.
123

  
119 124
Haskell development notes
120 125
-------------------------
121 126

  
b/doc/index.rst
137 137
   design-upgrade.rst
138 138
   design-virtual-clusters.rst
139 139
   devnotes.rst
140
   dev-codestyle.rst
140 141
   glossary.rst
141 142
   hooks.rst
142 143
   iallocator.rst

Also available in: Unified diff