Styleguide
Table of Contents
1.0 General
- Avoid unnecessary else statements
# bad
if a_true_thing:
return True
else:
return False
# good
if a_true_thing:
return True
return False
- Avoid nested if statements
# bad
if a_true_thing:
if another_true_thing:
return 'foo'
else:
return 'bar'
# good
if a_true_thing and another_true_thing:
return 'foo'
elif a_true_thing:
return 'bar'
- Avoid aligning groups of vars and keys in objects
- Caveat: Legacy files that are already aligned. Keep it consistent with what is in place.
# bad
foo = 'foo'
foobar = 'foobar'
stuff = {
'foo' : 'foo',
'foobar': 'foobar,'
}
# good
foo = 'foo'
foobar = 'foobar'
stuff = {
'foo': 'foo',
'foobar': 'foobar',
}
2.0 Angular / Coffeescript
2.1 Basics
- 2 space indent
hello = ->
console.log('hi')
return
hello()
- Commas should have a space after them
# bad
list = [1,2,3,4]
foo = (bar,baz) -> ...
# good
list = [1, 2, 3, 4]
foo = (bar, baz) -> ...
- CamelCase when naming variables and functions
# bad
some_function = (foo, bar) -> ...
some_var = 'Hello world'
# good
someFunction = (foo, bar) -> ...
someVar = 'Hello world'
- No quotes on keys in key value pairs
# bad
obj = {'key': 'value'}
obj = {'key-with-dash': 'value'} # this requires quotes, therefore avoid dashes in key names
# good
obj = {key: 'value'}
obj = {key_name: 'value'} # exception for data to be consumed by the backend that expects snake case
- Space between colon and value in key value pairs
# bad
obj = {key : 'value'}
obj = {key :'value'}
obj = {key:'value'}
# good
obj = {key: 'value'}
2.2 Strings
- Single quotes for strings
- Caveat: String interpolation requires double strings
- Caveat: Strings containing single quotes should be double quotes
# bad
aString = "Hello World"
anotherString = 'Hello #{ aString }' # this won't work at all
someString = 'Hello World\'s'
# good
aString = 'Hello World'
anotherString = "Hello #{ aString }"
someString = "Hello World's"
- Multi-line strings should be broken up with +
# bad
firstPiece = 'the first piece goes here'
secondPiece = ' the second piece goes here'
thirdPiece = ' the third piece goes here'
aReallyLongString = firstPiece + secondPiece + thirdPiece
# good
aReallyLongString = 'the first piece goes here' +
' the second piece goes here' +
' the third piece goes here'
2.3 Angular specifics
- Components over directives unless specific directive functionality is required
app.component 'componentName',
bindings:
someObject: '<'
someFunction: '&'
controller: 'ComponentNameController'
templateUrl: '/app/views/component/componentname.html'
app.controller 'ComponentNameController', ->
return
- Put controller initialization code in
$onInit
rather than on the top level of the controller
# bad
app.controller 'myCtrl', ->
this.foo = 'bar'
# good
app.controller 'myCtrl', ->
this.$onInit = =>
this.foo = 'bar'
- Multi-line injects should linebreak with no additional indent
angular.module('foo').service 'AServiceWithManyInjects', ($bar, $baz, $foo, CustomService,
MoreCustomService, NewService) ->
...
- Only declare controller variables on
this
if they are used in the respective HTML
# used in HTML
this.myVar1 = 1
# only used in controller
myVar2 = 2
- One way binding and functions passed down over two way binding
# TODO
2.4 Coffeescript specifics
- Always use strict
# bad
app = angular.module 'ngApp'
app.component '...', ...
# good
'use strict'
app = angular.module 'ngApp'
app.component '...', ...
- Multi-line function definitions should linebreak with no additional indent
someFn = (foo, bar, baz,
qux, etc) ->
console.log('Hello World')
3.0 Django / Python
3.1 Basics
- 4 space indent
def hello():
print 'hi'
hello()
- Snake_case when naming variables and functions
# bad
def someFunction(foo, bar): ...
someVar = 'Hello World'
# good
def some_function(foo, bar): ...
some_var = 'Hello World'
- CamelCase when naming classes
# bad
class some_class_view(): ...
class someclassview(): ...
# good
class SomeClassView(): ...
3.2 Strings
- Single quotes for strings
- Caveat: Strings containing single quotes should be double quotes
# bad
a_string = "Hello World"
another_string = 'Hello World\'s'
# good
a_string = 'Hello World'
another_string = "Hello World's"
- Multi-line strings should be wrapped in ()
# bad
first_piece = 'the first piece goes here'
second_piece = ' the second piece goes here'
third_piece = ' the third piece goes here'
a_really_long_string = first_piece + second_piece + third_piece
# good
a_really_long_string = ('the first piece goes here'
' the second piece goes here'
' the third piece goes here')
- Prefer % style string interpolation
world = 'World'
a_string = 'Hello %s' % world
hello = 'Hello'
world = 'World'
a_string = '%s %s' % (hello, world)
3.3 Lists
- Collections (list, tuple, dictionary) or parameter lists should be single line when within the character limit
# bad
first_list = [1,
2,
3]
second_dict = {
1: 'one',
2: 'two',
3: 'three'
]
def third_function(
one, two=2, three=3
):
...
# good
first_list = [1, 2, 3]
second_dict = {1: 'one', 2: 'two', 3: 'three'}
def third_function(one, two=2, three=3):
...
- If the list is longer than a line, then break all entries onto their own lines and end each with a comma, even the last entry
- YAPF will recognize the last dangling comma and format multi-line collections properly
# bad
first_list = [
1,
2,
3 # missing final comma
]
second_dict = {
1: 'one',
2: 'two',
3: 'three' # missing final comma
}
def third_function(
one,
two=2,
three=3 # missing final comma
):
...
# good
first_list = [
1,
2,
3, # has a dangling comma
]
second_dict = {
1: 'one',
2: 'two',
3: 'three', # has a dangling comma
}
def third_function(
one,
two=2,
three=3, # has a dangling comma
):
...
3.4 Tests
- Tests that assert query counts should include a comment that explains what is causing the queries. The comment should be able to explain, for each query, which table and for what purpose it was made.
- Tip 1: Grab the raw SQL and understand/explain each query.
- Tip 2: If updating a num queries test, get the SQL for what it used to be and for what you changed it to and diff the two to get to the bottom of exactly which query your change added/removed and update the comment.
# 1 - get template
# 1 - get conversation
# 2 - get employee, manager questions
# 2 - get employee, manager
with self.assertNumQueries(6):
SomeConversationSerializer(conversation, many=True).data
4.0 HTML
- Double quotes for attribute values
<!--bad-->
<my-component class='my-class'></my-component>
<!--good-->
<my-component class="my-class"></my-component>
- The order of element attributes is as follows
- HTML attributes
- Angular attributes
- data-ptor
<my-great-component
class="class1 class2"
ng-if="someBool"
data-ptor="great-component">
</my-great-component>
5.0 Styleguide
- Main headers should be 3 hash symbols and sentence case, starting with a number in format x.0
> bad
#### 1.0 A main section header
### 1.0 a main section header
### 1.0 A Main Section Header
### 1.1 A main section header
### A main section header
> good
### 1.0 A main section header
- Sub-section headers should be “minor version” increments
### 1.0 A main section header
> bad
#### 1.5 A sub section header
### 1.1 A sub section header
> good
#### 1.1 A sub section header
#### 1.2 A second sub section header
- If code examples can be shown with a bad and good example, bad goes first, prepended with comments
> bad
```python
some_good_example = True
some_bad_example = True
```
> good
```python
# bad
some_bad_example = True
# good
some_good_example = True
```