-
Notifications
You must be signed in to change notification settings - Fork 5
Style Guide
If you tell a typical programmer that a style convention is optional, they will never use it. Therefore nothing is optional.
Common sense is not common, intuition is not intuitive, and nothing is self-documenting. Therefore document everything.
Comments should provide an outline of what the code does. Additional comments should be put in whenever something was hard to figure out, to explain your solution or the need for it.
As per PEP 8, comments should be complete sentences.
All code must be runnable in Python 2.7 and the latest 3.x, using only the Standard Library Modules (or t_games modules).
PEP 8 is in effect except as specified in this section.
Maximum line length is 108 characters. Maximum line length for docstrings is 79 characters, not counting spaces used for indentation.
There should be double blank lines between sections within a module (imports, constants, classes, functions) and between classes and functions (but not methods within a class).
Line continuations for class and def statements have normal four space indentation. Note that this does cause confusion with the associated code block, as class and def statements will always be followed by a docstring. Other line continuations should be avoided by using multiple lines instead of continued lines.
Do not use blank lines to indicate logical sections within functions. Use comments.
Comments for attributes may be noun phrases instead of complete sentences, if they are not callable.
Use single quotes for string literals, unless the string contains single quotes or are multi-line strings.
Use one space around all binary operators.
When writing English, use the most recent AP Stylebook. Aim for high school level writing, not undergraduate or graduate level. Yes, most programmers have a college degree. No, they didn't all get them in English speaking countries. Additionally, I would like to think this project is good for younger programmers. So keep it simple and keep it clean. Oxford commas, 'they' for third person singular, and data as a collective noun are in effect.
Game names in comments and other documentation should always be capitalized.
Every game needs a __repr__. It should return a string such that eval(repr(obj)) == obj (or at least equivalent, if not actually ==). If this is not possible, or if the length of that string will average over 35 characters, instead give a debugging text representation. The debugging text representation should be of the form '<ClassName [info]>' where [info] is replace with any information that would be useful while debugging.
Never use singly letter variable names except for standard math variables in a math context. Even if you are never going to use the looping variable, you are looping over something. Name the looping variable over what you are looping over. If you just can't think of anything, name your variable dummy.
Always use underscores between words in constant, function, variable, and package names. That is, always use underscores in non-Camel Case names.
PEP 257 is used except as specified here. Note that docstrings for do_foo methods are used for help text, and follow different conventions (see Programming Games for details)
Docstrings should have the starting and ending """ characters on their own lines. The exception is docstrings with only one line of text, which should have the starting and ending """ characters on the same line.
The summary line of classes should end with the parent class in parenthesis. The summary line of functions should end with the return type in parenthesis. If there is space, details on the return type should be given. That is, use (list of str) instead of (list) as appropriate. (float) assumes (float or int), (complex) assumes (complex, float, or int). Although, why you would be using complex numbers in this package is beyond me. {{{#!comment Yes, that should be considered as a challenge.}}}
After the summary line and description as specified in PEP 257, the docstring should be followed by lists specific to the type of docstring. If the list would have no items, it should be omitted. The lists are of the following format:
List Name:
list_item: summary line
list_item: summary line
...
The summary lines in the list items should match summary lines elsewhere in the program. That is, the docstring for a module will have a list of classes in the module. The summary lines in that list should match the summary lines in the docstrings of the classes. The idea here is for the list to be an outline of what goes on in the module, class, or function. Note that the summary lines for constants and class attributes should be in comments before they are defined.
Module docstrings should have the lists Constants, Global Variables, Classes, and Functions, unless those lists would be empty. Class docstrings should have the lists Class Attributes, Attributes, Methods, and Overridden Methods (overridden attributes do not need to be specified). Note that the Overridden Methods list should not include summary lines, just the method names (without colons). Function and method docstrings should just include the parameter list. All parameters (except self and cls) should be included, and they should be followed by the expected type in parentheses.
Types in parameter, method, and function summary lines should be stated without namespace qualifiers. That is, if you just did a straight 'import collections', you would still use (Counter) in the docstring. While collections.Counter would certainly be clearer, space is at a premium in summary lines.
In general, items in docstring lists should be alphabetical, with dunders before non-dunders. This should match the order of the presentation in the module. That means that in a module, Constants should come first, and should be in alphabetical order. Exceptions to this include:
- Parameters: Should be in the order given in the def statement. The self and cls parameters do not need to be listed.
- Class Attributes: Should be in alphabetical order, but the code is not expected to define them in that order.
- Classes: The classes should be listed in a hierarchy. The parent (top-level) classes should be in alphabetical order. Each top-level class should be followed by its sub-classes (second-level) in alphabetical order. Each second-level class should be followed by its sub-classes (third-level) in alphabetical order. And so on. This prevents spaghetti code.
- Necessity: If the program requires things to be in a different order, do them in that order, but alphabetical as much as possible. But the list in the docstring should be in the order the items are in the program.
-
__init__always comes first in the Overridden Methods list. - Except for
__init__, which comes first, all methods should be in alphabetical order whether they are overridden or not. Dunders come before non-dunders.
The docstring for the __repr__ method is """Generate a computer readable text representation. (str)""" if eval(repr(obj)) == obj, and is """Generate a debugging text representation. (str)""" otherwise. The docstring for the __str__ method is always """Generate a human readable text representation. (str)"""
Do not use attribute docstrings for class attributes or constants. Class attributes and constants do not need comments unless there was something hard or tricky to get them to work right.
The first line of each commit message should be no more than 70 characters long, should start with 'Issue #XXX: ', where XXX is the (primary) issue being dealt with, and should include either the game class name or the name of the primary file being modified, along with a synopsis of what was done. Further lines should be no longer than 79 characters long, with a blank line after the first line and between paragraphs. If more than one issue is involved in the commit, the others should be mentioned with #YYY markdown links in the later lines of the commit messages.
Type hints should not be used.
Special methods for binary operators should use other as the parameter.
If a function or method is more than 55 lines long (not counting the declaration and the docstring), refactor it.