Name: coffeescript-style-guide
Owner: Topcoder
Description: null
Created: 2015-06-03 06:18:58.0
Updated: 2015-06-03 06:18:58.0
Pushed: 2015-06-04 00:43:58.0
Homepage: null
Size: 136
Language: null
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
This guide presents a collection of best-practices and coding conventions for the [CoffeeScript][coffeescript] programming language.
strict'
lineController = (TimelineService, $stateParams) ->
= this
.coPilotHandle = null
.members = []
.avatars = {}
.submissionHandle = null
.feedbackHandle = null
.feedback2Handle = null
pEvents = [
{ key: 'submitted', value: 'submitted' }
{ key: 'email', value: 'email-verified' }
{ key: 'quote', value: 'quote-created' }
{ key: 'payment', value: 'payment-accepted' }
{ key: 'coPilot', value: 'copilot-assigned' }
{ key: 'launched', value: 'launched' }
{ key: 'joined', value: 'challenge-member-registered' }
{ key: 'submissions', value: 'challenge-submission' }
{ key: 'feedback', value: 'challenge-feedback-provided' }
{ key: 'checkpoint1', value: 'checkpoint1' }
{ key: 'finalists', value: 'finalists' }
{ key: 'finalistsSelected', value: 'challenge-finalists-selected' }
{ key: 'finalDesign', value: 'final-design' }
{ key: 'winner', value: 'winner' }
{ key: 'finalFeedback', value: 'final-feedback' }
{ key: 'completed', value: 'completed' }
tivate = ->
for mapEvent in mapEvents
vm[mapEvent.key] =
passed : false
completed: false
params =
workId: $stateParams.workId
TimelineService.getEvents params, onChange
Change = (timeline) ->
setStatus timeline
vm.coPilotHandle = timeline.coPilot
vm.members = timeline.members
vm.avatars = timeline.avatars
vm.submissionHandle = timeline.submission
vm.submissionThumbs = timeline.submissionThumbs
vm.feedbackHandle = timeline.feedback
vm.feedback2Handle = timeline.feedback2
tStatus = (timeline) ->
for mapEvent in mapEvents
vm[mapEvent.key].completed = timeline.createdDates?[mapEvent.value]
for mapEvent, i in mapEvents
if mapEvents[i + 1]
vm[mapEvent.key].passed = vm[mapEvents[i + 1].key].completed
tivate()
lineController.$inject = [
imelineService'
stateParams'
lar.module('appirio-tech-timeline').controller 'TimelineController', TimelineController
Use spaces only, with 2 spaces per indentation level. Never mix tabs and spaces.
Limit all lines to a maximum of 79 characters.
No blank line for the first indentation in any case.
Blank line after unindenting.
Blank line before and after keyword blocks: if, unless, for
There should never be two consecutive blank lines.
Do not include trailing whitespace on any lines.
Avoid the use of commas before newlines when properties or elements of an Object or Array are listed on separate lines.
s
= [
ome'
tring'
alues'
bel: 'test'
lue: 87
= [
ome',
tring',
alues'
bel: 'test',
lue: 87
UTF-8 is the preferred source file encoding.
If using a module system (CommonJS Modules, AMD, etc.), require
statements should be placed on separate lines.
ire 'lib/setup'
bone = require 'backbone'
These statements should be grouped in the following order:
Avoid extraneous whitespace in the following situations:
Immediately inside parentheses, brackets or braces
$ 'body') # Yes
$ 'body' ) # No
Immediately before a comma
onsole.log x, y # Yes
onsole.log x , y # No
Additional recommendations:
Always surround these binary operators with a single space on either side
assignment: =
Note that this also applies when indicating default parameter value(s) in a function declaration
: (param = null) -> # Yes
: (param=null) -> # No
augmented assignment: +=
, -=
, etc.
comparisons: ==
, <
, >
, <=
, >=
, unless
, etc.
arithmetic operators: +
, -
, *
, /
, etc.
If modifying code that is described by an existing comment, update the comment such that it accurately reflects the new code. (Ideally, improve the code to obviate the need for the comment, and delete the comment entirely.)
The first word of the comment should be capitalized, unless the first word is an identifier that begins with a lower-case letter.
If a comment is short, the period at the end can be omitted.
Block comments apply to the block of code that follows them.
Each line of a block comment starts with a #
and a single space, and should be indented at the same level of the code that it describes.
Paragraphs inside of block comments are separated by a line containing a single #
.
This is a block comment. Note that if this were a real block
comment, we would actually be describing the proceeding code.
This is the second paragraph of the same block comment. Note
that this paragraph was separated from the previous paragraph
by a line containing a single comment character.
it()
art()
op()
Inline comments are placed on the line immediately above the statement that they are describing. If the inline comment is sufficiently short, it can be placed on the same line as the statement (separated by a single space from the end of the statement).
All inline comments should start with a #
and a single space.
The use of inline comments should be limited, because their existence is typically a sign of a code smell.
Do not use inline comments when they state the obvious:
No
= x + 1 # Increment x
However, inline comments can be useful in certain scenarios:
Yes
= x + 1 # Compensate for border
Use camelCase
(with a leading lowercase character) to name all variables, methods, and object properties.
Use CamelCase
(with a leading uppercase character) to name all classes. (This style is also commonly referred to as PascalCase
, CamelCaps
, or CapWords
, among [other alternatives][camel-case-variations].)
(The official CoffeeScript convention is camelcase, because this simplifies interoperability with JavaScript. For more on this decision, see [here][coffeescript-issue-425].)
For constants, use all uppercase with underscores:
TANT_LIKE_THIS
(These guidelines also apply to the methods of a class.)
When declaring a function that takes arguments, always use a single space after the closing parenthesis of the arguments list:
= (arg1, arg2) -> # Yes
= (arg1, arg2)-> # No
Do not use parentheses when declaring functions that take no arguments:
= -> # Yes
= () -> # No
In cases where method calls are being chained and the code does not fit on a single line, each call should be placed on a separate line and indented by one level (i.e., two spaces), with a leading .
.
3]
ap((x) -> x * x)
oncat([10..12])
ilter((x) -> x < 11)
educe((x, y) -> x + y)
Some time its better to avoid chaining in favor for readability.
yParams =
lter: 'sourceObjectId=' + params.workId
urce = TimelineAPIService.query queryParams
urce.$promise.then (response) ->
r item in resource
item.sourceObjectContent.handle += '1'
ildTimeline response, onChange
urce.$promise.catch ->
ODO: handle error
urce.$promise.finally ->
ODO: handle finally
When calling functions, choose to omit or include parentheses in such a way that optimizes for readability. Keeping in mind that “readability” can be subjective, the following examples demonstrate cases where parentheses have been omitted or included in a manner that the community deems to be optimal:
12
4).bar(8)
value(10, 20) / obj.value(20, 10)
t inspect value
Tag(new Value(a, b), new Arg(c))
Create meaningful variables when using object/array as arguments. This will help explain the code and reduce confusion with coffee conversion.
s
dinates =
10
20
h.ellipse coordinates
h.ellipse x: 10, y: 20
h.ellipse
10
20
You will sometimes see parentheses used to group functions (instead of being used to group function parameters). Examples of using this style (hereafter referred to as the “function grouping style”):
#selektor').addClass 'klass'
4).bar 8
This is in contrast to:
selektor').addClass 'klass'
4).bar 8
In cases where method calls are being chained, some adopters of this style prefer to use function grouping for the initial call only:
#selektor').addClass('klass').hide() # Initial call only
'#selektor').addClass 'klass').hide() # All calls
The function grouping style is not recommended. However, if the function grouping style is adopted for a particular project, be consistent with its usage.
Dont use string interpolation instead of string concatenation:
s is an #{adjective} string" # No
s is an ' + adjective + ' string' # Yes
Prefer single quoted strings (''
) instead of double quoted (""
) strings.
Favor unless
over if
for negative conditions.
Instead of using unless...else
, use if...else
:
Yes
true
...
se
...
No
less false
...
se
...
Multi-line if/else clauses should use indentation:
Yes
true
...
se
...
No
true then ...
se ...
Avoid complex comprehensions:
No
sult = (item.name for item in array)
Yes
sults = []
r item in array
results.push item.name
offeescript
lt = (item for item in array when item.name is "test")
ct = one: 1, two: 2
t("#{key} = #{value}") for key, value of object
Do not modify native objects.
For example, do not modify Array.prototype
to introduce Array#forEach
.
Do not suppress exceptions.
Use annotations when necessary to describe a specific action that must be taken against the indicated block of code.
Write the annotation on the line immediately above the code that the annotation is describing.
The annotation keyword should be followed by a colon and a space, and a descriptive note.
FIXME: The client's current state should *not* affect payload processing.
setClientState()
ocessPayload()
If multiple lines are required by the description, indent subsequent lines with two spaces:
TODO: Ensure that the value returned by this call falls within a certain
range, or throw an exception.
alyze()
Annotation types:
TODO
: describe missing functionality that should be added at a later dateFIXME
: describe broken code that must be fixedOPTIMIZE
: describe code that is inefficient and may become a bottleneckHACK
: describe the use of a questionable (or ingenious) coding practiceREVIEW
: describe code that should be reviewed to confirm implementationIf a custom annotation is required, the annotation should be documented in the project's README.
&&
is preferred over and``.
||
is preferred over or
.
==
is preferred over is
.
!=
is preferred over isnt
.
!
is preferred over not
.
||=
should be used when possible:
or= {} # No
= temp || {} # Yes
Dont use shorthand notation (::
) for accessing an object's prototype:
y::slice # No
y.prototype.slice # Yes
Prefer @property
over this.property
.
rn @property # Yes
rn this.property # No
However, avoid the use of standalone @
:
rn this # Yes
rn @ # No
Avoid return
where not required, unless the explicit return increases clarity.
Dont use splats (...
) when working with functions that accept variable numbers of arguments:
ole.log args... # No
b, c, rest...) -> # No