- Fairness
- Joy
- Kaizen
- SCSS: Structure is based on RSCSS
- Vanila JavaScript: Strucutre is based on RSJS
- Other common structure of JavaScript Page logic: https://github.com/tastejs/todomvc/blob/gh-pages/examples/jquery/js/app.js
Base styles guides:
- Ruby - bbatsov/ruby-style-guide
- CSS - JT CSS Style Guide
- JavaScript - airbnb/javascript
Our updates:
- Limit lines to 110 characters, in order to remove horizontal scrolling on GitHub when we are doing code review
- Align parameters like:
# good (normal indent) PREFERABLE
def send_mail(source)
Mailer.deliver(
to: '[email protected]',
from: '[email protected]',
subject: 'Important message',
body: source.text
)
end
# not so bad
def send_mail(source)
Mailer.deliver(
to: '[email protected]', from: '[email protected]'
)
end
# good, but DEPRECATED
def send_mail(source)
Mailer.deliver(to: '[email protected]',
from: '[email protected]',
subject: 'Important message',
body: source.text)
end
- Use prefix
_
for memo variables:
class TestObject
attr_reader :attr_name
def attr_name
@attr_name ||= lazy_calculation_for_attr_name
end
def public_method_with_memo
@_public_method_with_memo ||= public_method_with_memo_calculcations
end
end
- Stick to Newlines section of Airbnb's Ruby style guide for grouping the code within methods.
- Confirm on the master, the staging and finally on development environment.
- Add tests with reproduced bugs before add fixes
- We use Decorators (in code we called them
Carrier
) as View and Form objects: introduction how to use them - We do not use full Presenters (TODO: add link to first post about them) with any tag generations
- We do not overuse of Concerns
- We do not overuse (in 99% of our code we do not see such stuff):
send
,&.
,**
. To prevent misusage of Ruby Syntax Sugars [link]
- TDD
- Clarity means that a test should serve as readable documentation for humans, describing the code being tested in terms of its public APIs.
- A test is complete when its body contains all of the information you need to understand it, and concise when it doesn't contain any other distracting information.
Ref: Testing on the Toilet: What Makes a Good Test?
- Tests First[link]
-
Use Black Box testing strategy (there is no other way to support TDD)[link]
By ignoring the code (Black box testing), it demonstrates a different value system - the tests are valuable alone.
-
- We use the meaningful names in the test cases. It makes easier to understand the business logic.[link]
# bad
def test_email_is_normalized
user = User.create! email: '[email protected]'
assert_equal '[email protected]', user.email
end
# good
def test_email_is_normalized
user = User.create! email: ' [email protected]'
assert_equal '[email protected]', user.email
end
-
The test is building or referencing a larger fixture than is needed to verify the functionality in question. Do not load more data than needed to test your code. For each test create exactly what it needs and not more. More variations provides more complexities. More details could be found on http://xunitpatterns.com/Obscure%20Test.html#General%20Fixture [link]
Message for reviewer:
Each check must be isolated and shouldn't depend or interfere with others. This will make your tests clear and well organized and help to clearly see the cause of the failure. Please check https://github.com/jetthoughts/how-we-work/blob/master/README.md#big-fixtures-in-tests
# BAD
let!(:user_with_big_name) { ... }
let!(:user_with_small_name) { ... }
it 'this test use only user_with_big_name' { expects(response).to have(user_with_big_name) }
it 'this test use only user_with_small_name' { expects(response).to have(user_with_small_name) }
# GOOD
context 'with big name' do
let(:user) { ... }
it 'this test use only user_with_big_name' { expects(response).to have(user) }
end
context 'with small name' do
let(:user) { ... }
it 'this test use only user_with_small_name' { expects(response).to have(user) }
end
# BAD
setup do
big_file_with_all_users = compile_file_from_users(User.all)
end
test 'this test use only user_with_big_name' { assert_includes big_file_with_all_users, 'magic string with all big letter' }
test 'this test use only user_with_small_name' { assert_includes big_file_with_all_users, 'magic string with all small letter' }
# GOOD
test 'this test use only user_with_big_name' do
result = compile_file_from_users(User.new(name: 'Big Name'))
assert_includes result, 'Big Name'
end
test 'this test use only user_with_small_name' do
result = compile_file_from_users(User.new(name: 'Samll Name'))
assert_includes result, 'Small Name'
end
- No Dynamic Test generation.[link]
# BAD
{ string: 'zone_id', array: %w[zone_id], hash: { "0" => "zone_id" } }.each do |type, group_by|
it "returns valid json if group_by is #{type}" do
end
end
# GOOD
it "returns zone_id json if group_by is string" { }
it "returns [zone_id] json if group_by is array" { }
it "returns { '0' => 'zone_id' } json if group_by is hash" { }
-
Irrelevant Information[link]
Message for reviewer:
The test is exposing a lot of irrelevant details about the fixture that distract the test reader from what really affects the behavior of the subject under test.
describe 'PUT Update' do
let!(:user) { create :user }
# Bad
it 'updates user' do
attributes = { first_name: '..', last_name: '..', role: '..', email: '..' }
put: :update, params: { attributes }
expects(response.body).to eq attributes
end
# Good
it 'updates first_name' do
put: :update, params: { first_name: 'John Dou' }
expects(response.body).to have_attribute { first_name: 'John Dou' }
end
it 'updates email' do
put: :update, params: { email: '[email protected]' }
expects(response.body).to have_attribute { email: '[email protected]' }
end
bin/setup
- cold setupbin/update
- update environment on new code updates
Our flow is based on GitHub flow with Heroku Review
- create PR (we convert issues into PR)
- deploy PR to Heroku (we use Heroku Review to do this automatically)
- verify on Heroku yourselves
- ask verify, to code review and to merge (we have Code Review)
- add issue on GitHub per each note
- create TODO/FIXME note in the code
- add in code's note link to GitHub's issue
-
Basic git crash course for minimum git commands enough to work on the project
-
Prefix feature branch names with issue number: 123-issue-name;
-
Do not mess with cosmetics changes. Move them in separate commit or pr;
-
Squash multiple trivial commits into a single commit;
-
Convert an existing issue into a pull request:
hub pull-request -i 123
; -
Write a good commit message based on http://chris.beams.io/posts/git-commit/ with some requirements[link]:
Capitalized, the imperative mood, short (50 chars or less) subject (#<github_id>) Body after space line. Wrap the body at 72 characters. Use the body to explain what and why. Closes #<other_github_issue_id>, fixes #<another_github_issue_id>
Also some examples:
-
Create Issue Template[link]
-
Title: Jobs to be done
-
Body:
1. Acceptance Criteria
Acceptance criteria is that a developer knows they need to complete before that issue can be considered 'done'. They are the points against which the issue will be tested.
2. A screenshot or mock up of a new design
A picture which illustrates what the issue should be creating or a screenshot of an existing page showing where a bug is occurring. Remember to include mock ups of both mobile and desktop views.
-
-
Tutorials:
- Exceptions should be exceptional
- KISS ... your ARSE :P
- Stub/Mock only external services or code with hard simulation: https://www.youtube.com/watch?v=z9quxZsLcfo&feature=youtu.be&t=21m00s
- Four-Phase Test
- HTML/CSS3:
- Web Performance:
- ES6: https://www.eventbrite.com/engineering/tag/learning-es6/
- React.js/Redux: https://egghead.io/browse/frameworks/react
- 2 days per PR
- 2 Issues/PR per Developer
- 1000/100/6 performance model
- 5 min to pass all test suites
- 20 sec to run one test
- 20 sec to boot
- Collaboration:
- CI:
- Server Configuation: Ansible
- Deployments: Capistrano
- Assets and File Uploads CDN hosting: AWS, CloudFront, Cloudinary (Images Uploads)
- PAAS for Isolated Staging Testing: Heroku (Ruby on Rails apps), surge.sh (Static HTML)
- Cache: Memcached/Redis Cloud from Redis Lab
- JavaScript Base Frameworks: Stimulus, Vanilla JS, Vue.js, React
- SCM: GitHub