|
| 1 | +Style Guide |
| 2 | +=========== |
| 3 | + |
| 4 | +A guide for programming in style. |
| 5 | + |
| 6 | +Workflow |
| 7 | +-------- |
| 8 | + |
| 9 | +Start a [Trajectory](https://www.apptrajectory.com) story. |
| 10 | + |
| 11 | +Create a local feature branch off of master for development. |
| 12 | + |
| 13 | + git checkout master |
| 14 | + git pull |
| 15 | + git checkout -b feature-xyz |
| 16 | + |
| 17 | +Do work in your feature branch and commit the changes. |
| 18 | + |
| 19 | + git add -A |
| 20 | + git status |
| 21 | + git commit |
| 22 | + |
| 23 | +Write a [good commit message](http://goo.gl/w11us). |
| 24 | + |
| 25 | + Present-tense summary under 50 characters |
| 26 | + |
| 27 | + * More information about commit (under 72 characters) |
| 28 | + * More information about commit (under 72 characters) |
| 29 | + |
| 30 | +Make sure tests pass. Share your feature branch |
| 31 | + |
| 32 | + git push origin [branch] |
| 33 | + |
| 34 | +Submit a [Github pull request](http://goo.gl/Kmdee). |
| 35 | + |
| 36 | +Ask for a code review in Campfire. At least one person other than the author |
| 37 | +reviews the code before it is merged. |
| 38 | + |
| 39 | +Rebase frequently to incorporate upstream changes. |
| 40 | + |
| 41 | + git checkout master |
| 42 | + git pull |
| 43 | + git checkout [branch] |
| 44 | + git rebase master |
| 45 | + <resolve conflicts> |
| 46 | + |
| 47 | +Interactive rebase (squash) your commits (if necessary). |
| 48 | + |
| 49 | + git rebase -i master |
| 50 | + |
| 51 | +Make sure tests pass. Merge your branch back to master and push your changes. |
| 52 | + |
| 53 | + git checkout master |
| 54 | + git diff --stat master [branch] |
| 55 | + git merge [branch] --ff-only |
| 56 | + git push origin master |
| 57 | + |
| 58 | +Delete your remote feature branch. |
| 59 | + |
| 60 | + git push origin :[branch] |
| 61 | + |
| 62 | +Delete your local feature branch. |
| 63 | + |
| 64 | + git branch -d [branch] |
| 65 | + |
| 66 | +Merge master into the staging branch: |
| 67 | + |
| 68 | + git checkout staging |
| 69 | + git reset --hard origin/staging |
| 70 | + git log staging..master (view list of new commits) |
| 71 | + git diff --stat staging master (view changed files) |
| 72 | + git merge master |
| 73 | + git push origin staging |
| 74 | + |
| 75 | +Deploy to [Heroku](https://devcenter.heroku.com/articles/quickstart): |
| 76 | + |
| 77 | + git push <app> staging:master |
| 78 | + |
| 79 | +Run migrations (if necessary): |
| 80 | + |
| 81 | + heroku rake db:migrate --app <app> |
| 82 | + |
| 83 | +Restart the dynos if migrations were run: |
| 84 | + |
| 85 | + heroku restart --app <app> |
| 86 | + |
| 87 | +[Introspect](http://goo.gl/tTgVF) to make sure everything's ok: |
| 88 | + |
| 89 | + watch heroku ps --app <app> |
| 90 | + |
| 91 | +Smoke test in browser. Write acceptance criteria on the Trajectory story. |
| 92 | + |
| 93 | +Deliver story in Trajectory. |
| 94 | + |
| 95 | +Another team member reviews feature on staging based on acceptance criteria. |
| 96 | + |
| 97 | +When a batch (including a batch of one) of features have been accepted on |
| 98 | +staging, deploy to production using the same git workflow as staging. |
| 99 | + |
| 100 | +Formatting |
| 101 | +---------- |
| 102 | + |
| 103 | +* Delete trailing whitespace. |
| 104 | +* Don't include spaces after `(`, `[` or before `]`, `)`. |
| 105 | +* Don't vertically align tokens on consecutive lines. |
| 106 | +* Include spaces around infix method invocations like `+` and `-`. |
| 107 | +* Indent continued lines two spaces. |
| 108 | +* Indent private methods equal to public methods. |
| 109 | +* Limit lines to a maximum of 80 characters. |
| 110 | +* Order methods and attributes alphabetically where possible. |
| 111 | +* Use 2 space indentation (no tabs) unless otherwise noted. |
| 112 | +* Use an empty line between methods, blocks and conditionals. |
| 113 | +* Use spaces around operators, after commas, colons and semicolons, around `{` |
| 114 | + and before `}`. |
| 115 | +* Use Unix-style line endings (`\n`). |
| 116 | + |
| 117 | +Naming |
| 118 | +------ |
| 119 | + |
| 120 | +* Avoid abbreviations. |
| 121 | +* Avoid Hungarian notiation (`szName`). |
| 122 | +* Avoid types in names (`user_array`). |
| 123 | +* Name the enumeration parameter the singular of the collection. |
| 124 | +* Name variables, methods, and classes with intention-revealing names.. |
| 125 | +* Treat acronyms as words in names (`XmlHttpRequest` not `XMLHTTPRequest`), |
| 126 | + even if the acronym is the entire name (`class Html` not `class HTML`). |
| 127 | + |
| 128 | +Design |
| 129 | +------ |
| 130 | + |
| 131 | +* Aggressively DRY code during development. |
| 132 | +* Avoid comments. |
| 133 | +* Avoid global variables. |
| 134 | +* Avoid long parameter lists. |
| 135 | +* Be consistent. |
| 136 | +* Consider extracting `private` methods to their own object. |
| 137 | +* Don't duplicate the functionality of a built-in library. |
| 138 | +* Don't program defensively. |
| 139 | +* Don't swallow exceptions or "fail silently." |
| 140 | +* Don't write code that guesses at future functionality. |
| 141 | +* [Exceptions should be exceptional](http://rdd.me/yichhgvu). |
| 142 | +* [Keep the code simple](http://www.readability.com/articles/ko2aqda2). |
| 143 | +* Limit the number of collaborators of an object. |
| 144 | +* Prefer composition over inheritance. |
| 145 | +* Prefer small methods. One line is best. |
| 146 | +* Prefer small objects with a single, well-defined responsibility. |
| 147 | +* [Tell, don't ask](http://robots.thoughtbot.com/post/27572137956/tell-dont-ask). |
| 148 | + |
| 149 | +Ruby |
| 150 | +---- |
| 151 | + |
| 152 | +* Avoid `%q`, `%Q`, `%x`, `%s`, and `%W`. |
| 153 | +* Avoid conditional modifiers (lines that end with conditionals). |
| 154 | +* Avoid hashes as optional parameters. Does the method do too much? |
| 155 | +* Avoid including code and gems in source control that are specific to your |
| 156 | + development machine or process. Examples: `.rvmrc`, file watchers, debuggers. |
| 157 | +* Avoid meta-programming. |
| 158 | +* Avoid monkey-patching core classes. |
| 159 | +* Avoid `return` unless required. |
| 160 | +* Avoid superfluous parentheses when calling methods, but keep them when you |
| 161 | + assign the return value. |
| 162 | + x = Math.sin(y) |
| 163 | + array.delete e |
| 164 | +* Avoid ternary operators (`boolean ? true : false`). Use multi-line `if` |
| 165 | + instead to emphasize code branches. |
| 166 | +* Define the version of Ruby the project uses in the Gemfile. |
| 167 | +* Don't use `unless`. |
| 168 | +* Prefer classes to modules when designing functionality that is shared by |
| 169 | + multiple models. |
| 170 | +* Prefer `detect` over `find` and `select` over `find_all` to avoid confusion |
| 171 | + with ActiveRecord and keep `select`/`reject` symmetry. |
| 172 | +* Prefer `map` over `collect` and `reduce` over `inject` due to symmetry and |
| 173 | + familarity with mapping and reducing in other technologies. |
| 174 | +* Use `_` for unused block parameters. |
| 175 | + hash.map { |_, v| v + 1 } |
| 176 | +* Use `%{}` for single-line strings needing interpolation and double-quotes. |
| 177 | +* Use `%w()` over `['', '']` for an array of words. |
| 178 | +* Use `&&` and `||` for boolean expressions. |
| 179 | +* Use `||=` freely. |
| 180 | +* Use `{...}` over `do..end` for single-line blocks. |
| 181 | +* Use `!` suffix for dangerous methods (modifies `self`). |
| 182 | +* Use `?` suffix for predicate methods (return a boolean). |
| 183 | +* Use `CamelCase` for classes and modules, `snake_case` for variables and |
| 184 | + methods, `SCREAMING_SNAKE_CASE` for constants. |
| 185 | +* Use `def` with parentheses when there are arguments. |
| 186 | +* Use `do..end` over `{...}` for multi-line blocks. |
| 187 | +* Use `each`, not `for`, for iteration. |
| 188 | +* Use heredocs for multi-line strings. |
| 189 | +* Use `/(?:first|second)/` over `/(first|second)/` when you don't need the |
| 190 | + captured group. |
| 191 | +* Use `private` over `protected` to indicate scope. |
| 192 | +* Use `def self.method` over `def Class.method` or `class << self`. |
| 193 | +* Use `Set` over `Array` for arrays with unique elements. The lookup is faster. |
| 194 | +* Use single-quotes for strings unless interpolating. |
| 195 | +* Use `unless boolean?` instead of `if !boolean?`. |
| 196 | +* Use [Factory Girl](https://github.com/thoughtbot/factory_girl) for setting up |
| 197 | + complicated test data. |
| 198 | + |
| 199 | +Rails |
| 200 | +----- |
| 201 | + |
| 202 | +* Avoid the `:except` option in routes. |
| 203 | +* Avoid `member` and `collection` routes. |
| 204 | +* Avoid Single Table Inheritance. |
| 205 | +* Deploy to [Heroku](http://heroku.com). |
| 206 | +* Don't invoke a model's class directly from a view. |
| 207 | +* Don't use SQL or SQL fragments (`where('inviter_id is not null')`) outside of |
| 208 | + models. |
| 209 | +* Set `config.action_mailer.raise_delivery_errors = true` in the development |
| 210 | + environment. |
| 211 | +* Keep the `db/schema.rb` under version control. |
| 212 | +* Limit the number of instance variables shared between controller and view. |
| 213 | +* Name initializers for their gem name. Example: `paperclip.rb` |
| 214 | +* Order controller contents: filters, public methods, private methods. |
| 215 | +* Order model contents: constants, attributes, associations, nested attributes, |
| 216 | + named scopes, validations, callbacks, public methods, private methods. |
| 217 | +* Prefer presenters (Ruby objects responsible for presentation) over view |
| 218 | + helpers. |
| 219 | +* Put all copy text in models, views, controllers, and mailers in |
| 220 | + `config/locales`. |
| 221 | +* Set `config.action_mailer.delivery_method = :test` in the test environment. |
| 222 | +* Use `_path` over `_url` for named routes everywhere except mailer views. |
| 223 | +* Use `def self.method` over the `named_scope :method` DSL. |
| 224 | +* Use [Foreman](https://github.com/ddollar/foreman) to run Rails apps in |
| 225 | + development mode. |
| 226 | +* Use `I18n.t 'dot.separated.key'` over |
| 227 | + `I18n.t :key, :scope => [:dot, :separated]`. |
| 228 | +* Use [Haml](http://haml-lang.com) for view templates. |
| 229 | +* Use `has_and_belongs_to_many` if all you need is a join table. Start simple. |
| 230 | +* Use namespaced locale lookup in the views by prefixing a period: `t '.title'`. |
| 231 | +* Use nested routes to express `belongs_to` relationships between resources. |
| 232 | +* Use one `ActionMailer` for the app. Name it `Mailer`. |
| 233 | +* Use [single recipient SMTP](https://gist.github.com/2042496) in the staging |
| 234 | + environment. |
| 235 | +* Use the default `render 'partial'` syntax over `render :partial => 'partial'`. |
| 236 | +* Use the `:only` option to explicitly state exposed routes. |
| 237 | + |
| 238 | +Database |
| 239 | +-------- |
| 240 | + |
| 241 | +* Create [indexes concurrently](https://gist.github.com/3186117) to avoid table |
| 242 | + locks and [reduced performance](http://goo.gl/fi5ER) during deploys. |
| 243 | +* Consider a [partial index](http://goo.gl/YC8Jt) for queries on booleans. |
| 244 | +* Constrain most columns as [`NOT NULL`](http://goo.gl/0GeBr). |
| 245 | +* Create a read-only [Heroku Follower](http://goo.gl/xWDMx) for your |
| 246 | + production database. If a Heroku database outage occurs, Heroku can use the |
| 247 | + follower to get your app back up and running faster. |
| 248 | +* Use the Heroku Follower database for analytics to limit reads on the primary |
| 249 | + database. |
| 250 | + |
| 251 | +Javascript |
| 252 | +---------- |
| 253 | + |
| 254 | +* Define functions that operate on `window` or DOM in scope of `window`. |
| 255 | +* Initialize arrays using `[]`. |
| 256 | +* Initialize empty objects and hashes using `{}`. |
| 257 | +* Use `CamelCase` for prototypes, `mixedCase` for variables and functions, |
| 258 | + `SCREAMING_SNAKE_CASE` for constants, `_single_leading_underscore` for |
| 259 | + private variables and functions. |
| 260 | +* Use `data-` attributes to bind event handlers. |
| 261 | +* Use the [module pattern](http://yuiblog.com/blog/2007/06/12/module-pattern) |
| 262 | + to control method visibility. |
| 263 | + |
| 264 | +Testing |
| 265 | +------- |
| 266 | + |
| 267 | +* Avoid `its`, `let`, `let!`, `specify`, `subject`, and other DSLs. Prefer |
| 268 | + explicitness and consistency. |
| 269 | +* Disable real HTTP requests to external services. |
| 270 | +* Don't prefix `it` blocks with 'should'. |
| 271 | +* Name outer `describe` blocks after the method under test. Use `.method` |
| 272 | + for class methods and `#method` for instance methods. |
| 273 | +* Order factories.rb: sequences, traits, factory definitions. |
| 274 | +* Order factory definitions alphabetically by factory name. |
| 275 | +* Order factory attributes: implicit attributes, newline, explicit attributes, |
| 276 | + child factory definitions. Each section's attributes are alphabetical. |
| 277 | +* Prefix `context` blocks names with 'given' when receiving input. Prefix with |
| 278 | + 'when' in most other cases. |
| 279 | +* Run specs with `--format documentation`. |
| 280 | +* Use a `context` block for each execution path through the method. |
| 281 | +* Use a [Fake](http://robots.thoughtbot.com/post/219216005/fake-it) to stub |
| 282 | + requests to external services. |
| 283 | +* Use `before` blocks to clearly define the 'setup' phase of the |
| 284 | + [Four Phase Test](http://xunitpatterns.com/Four%20Phase%20Test.html). |
| 285 | +* Use integration tests to execute the entire app. |
| 286 | +* Use literal strings or non-[SUT](http://xunitpatterns.com/SUT.html) methods |
| 287 | + in test expectations when possible. |
| 288 | +* Use one expection per `it` block. |
| 289 | +* Use stubs and spies (not mocks) in isolated tests to test only the object |
| 290 | + under test. |
0 commit comments