Skip to content
Lance Pollard edited this page Apr 22, 2012 · 2 revisions

Design Principles

Avoid CoffeeScript Keywords

  • Don't use any "JS_KEYWORDS" words that CoffeeScript allows you to use, because even though you can do user.delete() in CoffeeScript, you'd have to write user["delete"]() in JavaScript. These words are:
true
false
null
this
new
delete
typeof
in
instanceof
return
throw
break
continue
debugger
if
else
switch
for
while
do
try
catch
finally
class
extends
super

Use camelCase, not snake_case

Keep consistent line breaks

  • Maximum of 1 blank line between chunks of code.
  • First line of indented code should not have a blank line above it in most cases.

Do this:

class App.User extends Tower.Model
  @field "email"
  
  @hasMany "posts"
  @hasMany "comments"
  
  activate: (callback) ->
    @updateAttributes activatedAt: new Date, callback

Not this:

class App.User extends Tower.Model

  @field "email"
  
  @hasMany "posts"
  
  @hasMany "comments"
  
  
  
  activate: (callback) ->
    @updateAttributes activatedAt: new Date, callback

Don't abbreviate method names

  • Use the full word for the method name (width instead of w)
  • Only use abbreviations if the abbreviation is the preferred way of expressing the term in the industry. But even then, if the spelled out version is easier to read, use that.
"width" > "w"
"height" > "h"
"x"
"y"
"JSON" > "JavaScriptObjectNotation"
"src" == "source"
"directory" > "dir"
"createDirectory" > "mkdir"
"background" > "bg"

Remove trailing whitespace

Use 2 soft spaces , not 1 tab \t

Use coffeescript array assignments

Do this:

[one, two] = [1, 2]

Over this:

array = [1, 2]
one   = array[0]
two   = array[1]

Use the => operator instead of _this, _self, etc.

Group public/private methods

Put private methods at the bottom of the file, even if they're named after a public method. Reason: it's easier to read the code, you get the API first, then the implementation.

Correct:

set: ->

get: ->

_set: ->

_get: ->

Incorrect:

set: ->

_set: ->

get: ->

_get: ->

Align = and :

  • align semicolons on the left
  • align equal signs on the right, 2n tabs in (falls on an even number of whitespaces)

Minimize the number of methods

  • less code to manage
  • fewer methods to memorize
  • smaller footprint (less code for the browser to download)
  • differs from Rails
  • opt-in helper method generation
model.buildRelation("user") # can opt into
# vs.
model.buildUser()

Convert model.store() to a store() method on the class ONLY IF the number of times you use the method is such that creating the "wrapper" method would save on the number of characters in the js/coffee file (so when it's minimized, it's maximally minimized). That is, if you only call the long method once, don't wrap it, just deal with it. Or, if the method is sufficiently complex and needs to be tested, and is still only used once, then make it a method and test it. Better to test than to not.

Use single underscore for Ruby-ish bang! methods: create_().

Organize the code so it can be compiled for the client

  • put module.exports = X at the bottom of each file so it can be stripped with a regular expression.

Create Underscore.js Compatible Helpers

  • write helpers so they are independent of underscore but can be swapped.

Tips

Create a namespace for your app.

This makes it so you don't have to use require everywhere on the client, setting the same variable over and over again.

class MyApp.User
  @include Tower.Model

or

class User
  @include Tower.Model

MyApp.User = User

Instead of

# user.coffee
class User
  @include Tower.Model

module.exports = User

# somewhere else
User = require('../app/models/user')

Because of the naming/folder conventions, you can get away with this without any worries. It also decreases the final output code :)

CoffeeScript Cheat Sheet

=> vs ->

key in object

return true if key of object
return true if object.hasOwnProperty(key)

{key1, key2}

{@key1}

@render "action", locals: {post: @post}
@render "action", locals: {@post}

OR=

a ?= true

b ||= true

c or= true
if (typeof a === "undefined" || a === null) a = true;

b || (b = true);

c || (c = true);

Tower.js

Everything here will be reflected on http://towerjs.org/guides.

Clone this wiki locally