Latest commit 8075083 Jan 26, 2016 @drapergeek drapergeek Recommend against `toggleProperty`
Using `toggleProperty` makes tracking down interactions a lot harder. Using explicit actions for what you expect to happens make code easier to maintain and debug.
Permalink
..
Failed to load latest commit information.
samples Use blocks when declaring date and time attributes Nov 3, 2015
README.md Recommend against `toggleProperty` Feb 26, 2016

README.md

Best Practices

A guide for programming well.

General

  • These are not to be blindly followed; strive to understand these and ask when in doubt.
  • Don't duplicate the functionality of a built-in library.
  • Don't swallow exceptions or "fail silently."
  • Don't write code that guesses at future functionality.
  • Exceptions should be exceptional.
  • Keep the code simple.

Object-Oriented Design

  • Avoid global variables.
  • Avoid long parameter lists.
  • Limit collaborators of an object (entities an object depends on).
  • Limit an object's dependencies (entities that depend on an object).
  • Prefer composition over inheritance.
  • Prefer small methods. Between one and five lines is best.
  • Prefer small classes with a single, well-defined responsibility. When a class exceeds 100 lines, it may be doing too many things.
  • Tell, don't ask.

Ruby

  • Avoid optional parameters. Does the method do too much?
  • Avoid monkey-patching.
  • Generate necessary Bundler binstubs for the project, such as rake and rspec, and add them to version control.
  • Prefer classes to modules when designing functionality that is shared by multiple models.
  • Prefer private when indicating scope. Use protected only with comparison methods like def ==(other), def <(other), and def >(other).

Ruby Gems

  • Declare dependencies in the <PROJECT_NAME>.gemspec file.
  • Reference the gemspec in the Gemfile.
  • Use Appraisal to test the gem against multiple versions of gem dependencies (such as Rails in a Rails engine).
  • Use Bundler to manage the gem's dependencies.
  • Use Travis CI for Continuous Integration, indicators showing whether GitHub pull requests can be merged, and to test against multiple Ruby versions.

Rails

  • Add foreign key constraints in migrations.
  • Avoid bypassing validations with methods like save(validate: false), update_attribute, and toggle.
  • Avoid instantiating more than one object in controllers.
  • Avoid naming methods after database columns in the same class.
  • Don't change a migration after it has been merged into master if the desired change can be solved with another migration.
  • Don't reference a model class directly from a view.
  • Don't return false from ActiveModel callbacks, but instead raise an exception.
  • Don't use instance variables in partials. Pass local variables to partials from view templates.
  • Don't use SQL or SQL fragments (where('inviter_id IS NOT NULL')) outside of models.
  • Generate necessary Spring binstubs for the project, such as rake and rspec, and add them to version control.
  • If there are default values, set them in migrations.
  • Keep db/schema.rb or db/development_structure.sql under version control.
  • Use only one instance variable in each view.
  • Use SQL, not ActiveRecord models, in migrations.
  • Use the .ruby-version file convention to specify the Ruby version and patch level for a project.
  • Use _url suffixes for named routes in mailer views and redirects. Use _path suffixes for named routes everywhere else.
  • Use a class constant rather than the stringified class name for class_name options on ActiveRecord association macros.
  • Validate the associated belongs_to object (user), not the database column (user_id).
  • Use db/seeds.rb for data that is required in all environments.
  • Use dev:prime rake task for development environment seed data.
  • Prefer cookies.signed over cookies to prevent tampering.
  • Prefer Time.current over Time.now
  • Prefer Date.current over Date.today
  • Prefer Time.zone.parse("2014-07-04 16:05:37") over Time.parse("2014-07-04 16:05:37")
  • Use ENV.fetch for environment variables instead of ENV[]so that unset environment variables are detected on deploy.
  • Use blocks when declaring date and time attributes in FactoryGirl factories.
  • Use touch: true when declaring belongs_to relationships.

Testing

  • Avoid any_instance in rspec-mocks and mocha. Prefer dependency injection.
  • Avoid its, specify, and before in RSpec.
  • Avoid let (or let!) in RSpec. Prefer extracting helper methods, but do not re-implement the functionality of let. Example.
  • Avoid using subject explicitly inside of an RSpec it block. Example.
  • Avoid using instance variables in tests.
  • Disable real HTTP requests to external services with WebMock.disable_net_connect!.
  • Don't test private methods.
  • Test background jobs with a Delayed::Job matcher.
  • Use stubs and spies (not mocks) in isolated tests.
  • Use a single level of abstraction within scenarios.
  • Use an it example or test method for each execution path through the method.
  • Use assertions about state for incoming messages.
  • Use stubs and spies to assert you sent outgoing messages.
  • Use a Fake to stub requests to external services.
  • Use integration tests to execute the entire app.
  • Use non-SUT methods in expectations when possible.

Bundler

  • Specify the Ruby version to be used on the project in the Gemfile.
  • Use a pessimistic version in the Gemfile for gems that follow semantic versioning, such as rspec, factory_girl, and capybara.
  • Use a versionless Gemfile declarations for gems that are safe to update often, such as pg, thin, and debugger.
  • Use an exact version in the Gemfile for fragile gems, such as Rails.

Postgres

  • Avoid multicolumn indexes in Postgres. It combines multiple indexes efficiently. Optimize later with a compound index if needed.
  • Consider a partial index for queries on booleans.
  • Constrain most columns as NOT NULL.
  • Index foreign keys.
  • Use an ORDER BY clause on queries where the results will be displayed to a user, as queries without one may return results in a changing, arbitrary order.

Background Jobs

  • Store IDs, not ActiveRecord objects for cleaner serialization, then re-find the ActiveRecord object in the perform method.

Email

  • Use SendGrid or Amazon SES to deliver email in staging and production environments.
  • Use a tool like ActionMailer Preview to look at each created or updated mailer view before merging. Use MailView gem unless using Rails version 4.1.0 or later.

Web

  • Avoid a Flash of Unstyled Text, even when no cache is available.
  • Avoid rendering delays caused by synchronous loading.
  • Use https instead of http when linking to assets.

JavaScript

  • Use the latest stable JavaScript syntax with a transpiler, such as babel.
  • Include a to_param or href attribute when serializing ActiveRecord models, and use that when constructing URLs client side, rather than the ID.

HTML

  • Don't use a reset button for forms.
  • Prefer cancel links to cancel buttons.
  • Use <button> tags over <a> tags for actions.

CSS

  • Use Sass.
  • Use Autoprefixer to generate vendor prefixes based on the project-specific browser support that is needed.

Sass

  • Prefer overflow: auto to overflow: scroll, because scroll will always display scrollbars outside of OS X, even when content fits in the container.
  • Use image-url and font-url, not url, so the asset pipeline will re-write the correct paths to assets.
  • Prefer mixins to @extend.

Browsers

  • Avoid supporting versions of Internet Explorer before IE10.

Objective-C

  • Setup new projects using Liftoff and follow provided directory structure.
  • Prefer categories on Foundation classes to helper methods.
  • Prefer string constants to literals when providing keys or key paths to methods.

Shell

  • Don't parse the output of ls. See here for details and alternatives.
  • Don't use cat to provide a file on stdin to a process that accepts file arguments itself.
  • Don't use echo with options, escapes, or variables (use printf for those cases).
  • Don't use a /bin/sh shebang unless you plan to test and run your script on at least: Actual Sh, Dash in POSIX-compatible mode (as it will be run on Debian), and Bash in POSIX-compatible mode (as it will be run on OSX).
  • Don't use any non-POSIX features when using a /bin/sh shebang.
  • If calling cd, have code to handle a failure to change directories.
  • If calling rm with a variable, ensure the variable is not empty.
  • Prefer "$@" over "$*" unless you know exactly what you're doing.
  • Prefer awk '/re/ { ... }' to grep re | awk '{ ... }'.
  • Prefer find -exec {} + to find -print0 | xargs -0.
  • Prefer for loops over while read loops.
  • Prefer grep -c to grep | wc -l.
  • Prefer mktemp over using $$ to "uniquely" name a temporary file.
  • Prefer sed '/re/!d; s//.../' to grep re | sed 's/re/.../'.
  • Prefer sed 'cmd; cmd' to sed -e 'cmd' -e 'cmd'.
  • Prefer checking exit statuses over output in if statements (if grep -q ...;, not if [ -n "$(grep ...)" ];).
  • Prefer reading environment variables over process output ($TTY not $(tty), $PWD not $(pwd), etc).
  • Use $( ... ), not backticks for capturing command output.
  • Use $(( ... )), not expr for executing arithmetic expressions.
  • Use 1 and 0, not true and false to represent boolean variables.
  • Use find -print0 | xargs -0, not find | xargs.
  • Use quotes around every "$variable" and "$( ... )" expression unless you want them to be word-split and/or interpreted as globs.
  • Use the local keyword with function-scoped variables.
  • Identify common problems with shellcheck.

Bash

In addition to Shell best practices,

  • Prefer ${var,,} and ${var^^} over tr for changing case.
  • Prefer ${var//from/to} over sed for simple string replacements.
  • Prefer [[ over test or [.
  • Prefer process substitution over a pipe in while read loops.
  • Use (( or let, not $(( when you don't need the result

Haskell

  • Avoid partial functions (head, read, etc).
  • Compile code with -Wall -Werror.

Ember

  • Avoid using $ without scoping to this.$ in views and components.
  • Prefer to make model lookup calls in routes instead of controllers (find, findAll, etc.).
  • Prefer adding properties to controllers instead of models.
  • Don't use jQuery outside of views and components.
  • Prefer to use predefined Ember.computed.* functions when possible.
  • Use href="#" for links that have an action.
  • Prefer dependency injection through Ember.inject over initializers, globals on window, or namespaces. (sample)
  • Prefer sub-routes over maintaining state.
  • Prefer explicit setting of boolean properties over toggleProperty.
  • Prefer testing your application with QUnit.

Testing

  • Prefer findWithAssert over find when fetching an element you expect to exist

Angular

  • Avoid manual dependency annotations. Disable mangling or use a pre-processor for annotations.
  • Prefer factory to service. If you desire a singleton, wrap the singleton class in a factory function and return a new instance of that class from the factory.
  • Prefer the translate directive to the translate filter for performance reasons.
  • Don't use the jQuery or $ global. Access jQuery via angular.element.

Ruby JSON APIs

  • Review the recommended practices outlined in Heroku's HTTP API Design Guide before designing a new API.
  • Use a fast JSON parser, e.g. oj
  • Write integration tests for your API endpoints. When the primary consumer of the API is a JavaScript client maintained within the same code base as the provider of the API, write feature specs. Otherwise write request specs.