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
"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
javascripting.com
USE THIRD-PARTY
orders.map('customer').unique().average('payment');
http://sugarjs.com
SMALL COMMITS
com
m
it!
BAD
com
m
it!
com
m
it!
com
m
it!
GOODcom
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
BEST
com
m
it!com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
it!
com
m
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 Gelman
ilya@500tech.com

The Human Linter