the human linter — ilya gelman
TRANSCRIPT
THE HUMAN LINTER
Ilya Gelman
Ilya Gelman
- Organizer of AngularJS-IL - Organizer of ReactJS-Israel - Passionate about design and UX
Sr. Developer & Consultant @ 500Tech
BAD CODE
Had to deploy fast
Didn’t read the documentation
Hoped to refactor later
It wasn’t me
New technology
'use strict'; const React = require('react'); const BaseMixin = require('mixins/base'); const ChildrenMixin = require('mixins/children'); const ComponentUtils = require('utils/component'); const Config = require('lib/config'); const Notification = require('components/notifications'); modure.exports = React.createClass({ displayName:'Form', mixins:[BaseMixin,ChildrenMixin], propTypes: {metadata: React.PropTypes.object.isRequired, notifications: React.PropTypes.array }, getChildContext(){ return { action: this._handleAction, formId: this.props.id}},
⌥ ⌘ L
'use strict'; const React = require('react'); const BaseMixin = require('mixins/base'); const ChildrenMixin = require('mixins/children'); const ComponentUtils = require('utils/component'); const Config = require('lib/config'); const Notification = require('components/notifications'); modure.exports = React.createClass({ displayName: 'Form', mixins: [BaseMixin, ChildrenMixin], propTypes: { metadata: React.PropTypes.object.isRequired, notifications: React.PropTypes.array }, getChildContext() { return { action: this._handleAction, formId: this.props.id } }
EXAMPLES FROM REAL WORLD
?if (connected) { return true; } else { return false; }
return connected;
?if (connected) { return true; } else { return false; }
return connected;!!
?if (!isActive) { isActive = true; } else { isActive = false; }
isActive = !isActive;
?if (!grade) { grade = 100; }
grade = grade || 100;
?if (books) { books.map(fn); } else { return []; }
(books || []).map(fn);
?let point = {}; point.x = 10; point.y = 29;
const point = { x: 10, y: 29 };
?while (processing) { const config = { option1: 123, option2: 456 }; // ...}
const config = { option1: 123, option2: 456}; while (processing) { // ...}
?.sort((a, b) => { return a > b; });
.sort((a, b) => a > b);
ES6
?{ email: email, password: password}
{ email, password }
ES6
1 == "1"TRUE
1 === "1"FALSE
http://codepen.io/borisd/pen/jbNory
Async Actions
$http.get(API_URL).then(function () { redirectTo(profileUrl)});
function perimeter(top, right, bottom, left) { return Math.sum(top, right, bottom, left); } perimeter(20, 15, 23, 12);
ES6
function perimeter(options = {}) { const opt = options; return Math.sum(opt.top, opt.right, opt.bottom, opt.left); } perimeter({ top: 20, bottom: 23, left: 12, right: 15 });
ES6
* Not the best code, only shows options hash example
function perimeter(top, right, bottom, left) { return Math.sum(top, right, bottom, left); } perimeter(/* top */ 20, /* right */ 15, /* bottom */ 23, /* left */ 12);
ES6
element.addEventListener('click', listener, false); element.removeEventListener('click', listener, false);
Clean Listeners
Useless Comments
// Clicks the edit icon T.simulate.click(editBtn);
Unreadable Variable Names
.map((b, i) => { return { catalogId: i, description: getDescription(b.isbn), }; });
Unreadable Variable Names
.map((book, index) => { return { catalogId: index, description: getDescription(book.isbn), }; });
Unreadable Variable Names
const getBook = (book, index) => { return { catalogId: index, description: getDescription(book.isbn), }; }
.map(getBook);
// TODO: Implement later
// FIXME: Change later
Technical Debt
WHAT TO DO
if (viewLoading) { element.classList.add('active'); } else { element.classList.remove('active'); }
element.classList.toggle('active', viewLoading);
READ THE DOCS
RE-READ THE DOCS
ESLint
https://github.com/500tech/code-style
.eslintrc
"generators": true, "modules": true, "objectLiteralComputedProperties": true, "objectLiteralDuplicateProperties": false, "objectLiteralShorthandMethods": true, "objectLiteralShorthandProperties": true, "restParams": true, "spread": true, "superInFunctions": true, "templateStrings": true, "jsx": true, "regexYFlag": true, "regexUFlag": true, }, "rules": { // Disabled rules "complexity": 0, "no-extend-native": 0, "no-process-env": 0, "init-declarations": 0, "no-restricted-modules": 0, "no-sync": 0, "no-undef-init": 0, "linebreak-style": 0, "no-inline-comments": 0, "no-new-object": 0, "no-ternary": 0, "padded-blocks": 0, "no-inner-declarations": 0, "id-length": 0, "id-match": 0, "no-underscore-dangle": 0, "sort-vars": 0, "max-statements": 0, // Warning level "comma-dangle": [1, "always-multiline"], "no-console": 1, "no-control-regex": 1, "no-empty": 1, "no-func-assign": 1, "consistent-return": 1, "curly": [1, "all"], "default-case": 1, "dot-notation": 1, "no-alert": 1, "no-multi-spaces": 1, "no-param-reassign": 1, "no-warning-comments": [1, { "terms": ["todo", "radix": 1, "no-path-concat": 1, "no-process-exit": 1, "lines-around-comment": [1, { "beforeBlockComment": "constructor-super": 1, "prefer-template": 1,
free for open-source projects
SMALL COMMITS
comm
it!
BAD
comm
it!
comm
it!
comm
it!
GOOD
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
BEST
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
comm
it!
Also, review "on-the-fly" to save time
http://www.osnews.com/story/19266/WTFs_m
js best practices
top programming mistakes
http://amzn.to/1bSAYsh http://amzn.to/1ydGaoB http://amzn.to/1K93J6h
WE ARE HIRING
Read our blog:http://blog.500tech.com
Ilya [email protected]