Front-End Code Quality @ Panaya
In Client side we code in ?
LET'S FOCUS ON
In shorts
used to create interactive websites
SOME FACTS
- Was written in 1997 over the span of 10 days by Brenden Eich
- Intends to take us a step beyond static HTML
-
IT'S NOT JAVA
- an implementation of the ECMAScript SPEC
- each browser implements the engine as it sees fit
-
NO COMPILER
- oh what fun...
SO JAVASCRIPT
- lacks conformity between browsers
- has no compiler to help us
- full of "gotchas" that silently introduce bugs
- Is not java... yet most programmers code like it is...
EXAMPLES
DAMN BROwSER
(function() {
var a = "initial";
if(a) {
function f() { console.log("1") };
} else {
function f() { console.log("2") };
}
f();
})()
What would be printed
1 ?
2 ?
Internet Explorer
1
Chrome
2
Opera
MORE TO FEAR FROM
console.log(typeof greet);
greet();
var greet = function() {
alert("hello!");
}
console.log(typeof greet);
greet();
function greet() {
alert("hello!");
}
VS.
EQUALITY using == operatrtor
> 0 == false
true
> 1 == true
true
> 2 == true
false
> 2 ? true : false
true // because 2 !== 0
'' == '0' // false
0 == '' // true
0 == '0' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true
Let's focus on these
Let's see
'0' == 0 == ''
true
true
Remember "Transitivity" property?
X = Y and Y = Z than X = Z
You'd expect:
'0' == ''
So ?
'0' == ''
false
DO YOU WANT TO REMEMBER THIS ?
SILENT FAILURES
if(undefined = "foo") {
...
}
//OH NO YOU DIDN'T!!
WE JUST RAN OVER "undefined" !!!
NO EXCEPTION WILL BE RAISED
IE8
And So MANY MORE...
USE A "LINTER" :)
STATIC CODE ANALYSIS
"Lint" tools read your source code and look for common mistakes...
It will not make you a better coder ;)
(function() {
var a = "initial";
if(a) {
function f() { console.log("1") };
} else {
function f() { console.log("2") };
}
f();
})()
LINT WILL GENERATE AN ERROR DURING BUILD
(compile time)
"NO INNER FUNCTION DECLARATION"
Remember this ?
CONTENDERS
- JS-LINT
- JS-HINT
- Closure Linter
WINNER: ES-LINT
TREND
SO WHY ESLINT
- It's more flexible (~140 Rules, all can be turned off)
- We are currently monitoring ~40
- It's blazing fast
- It's actively maintained and developed
- AND IT'S EXTENSIBLE
- Soon - angularJS rules !
SHOW ME THE MONEY
Let's go over Rules
eqeqeq
NEVER USE == or != operator
USE === or !=== operators
if (x == 42) { ... }
if ("" == text) { ... }
if (obj.getStuff() != undefined) { ... }
no-use-before-define
// NO !
alert(a);
var a = 10;
// NO !!
foo();
var foo = function() { alert('foo') }
// This is OK
bar();
function bar() { alert('bar') }
variable & function declarations are "hoisted"
HOISTED ?
HOISTING
// SCOPE START HERE
foo();
var foo = function() {
alert('bar');
}
// SCOPE START HERE
var foo;
foo();
foo = function() {
alert('bar');
}
Is actually this
JavaScript use (mysterious) "declaration hoisting"
All function and variable declarations are moved to the top of their containing scope :\
curly
if (a === b) return;
while(bar)
baz();
if (foo) {
baz();
} else qux();
Agreed - this is a "stylistic" rule
Yet - it is well established that common style increase readability and decreases errors
if (a === b) {
return;
}
while(bar) {
baz();
}
if (foo) {
baz();
} else {
qux();
}
NO
YES
Despite a population of over a billion, China has only about 200 family names.
strict
if(undefined = true) {
...
}
// OMG - you did it again
someVariable = "some string"
// notice - I forgot to add var - THIS IS GLOBAL !
delete Object.prototype;
// throws a TypeError
'use strict'
and many more - silent failures / security considerations / etc...
How do we invoke ?
Just put 'use strict' at the top of scope
function foo() {
'use strict'
if(undefined = 10) { // generates error :)
...
}
}
function foo() {
'use strict'
if(undefined = 10) { // generates error :)
...
}
function bar () {
// no need to put an extra 'use strict'
...
}
}
No need to use in inner scopes...
AND IF I...
// this is a dummy util file :|
var Utils = {
foo: function() {
'use strict'
},
bar: function() {
'use strict'
},
baz: function() {
'use strict'
},
}
in GLOBAL SCOPE
'use strict'
var Utils = {
foo: function() {
},
bar: function() {
},
baz: function() {
},
}
Not a good idea
As JS code is concatenated...
Basically - this is forcing every JS file to respect 'use strict'
ALSO - 3rd party libs :\
in OBJECT DEFINITION
// Like this than ?
var Utils = {
'use strict'
foo: function() {
},
bar: function() {
},
baz: function() {
},
}
NOPE
In JS - scope is by "function"
So in fact this is the same as global scope
Use this Pattern
// :)
var Utils = function() {
'use strict'
return {
foo: function() {
},
bar: function() {
},
baz: function() {
}
}
}() // <- PAY ATTENTION TO THIS !
This pattern also enabled to add "private" members in Utils object
// :)
var Utils = function() {
'use strict'
var lookAtMe = "I'm Private";
return {
foo: function() {
},
bar: function() {
},
baz: function() {
}
}
}() // <- PAY ATTENTION TO THIS !
You KNOW THIS - ng
angular.module('panaya.common.directives')
.directive('horizontalDateProgressBar', [function () {
'use strict';
return {
restrict: 'A',
templateUrl: 'sometemplate.html',
scope: {
injectedItem: '='
},
link: function (scope) {
...
function bar() {
// no need for use strict
}
var baz = function() {
// no need for use strict
}
}
};
}]);
no-console
console.log("Made it here.");
console.error("That shouldn't have happened.");
Why not ?
Use of console is considered for debugging purposes only
not suitable to be shipped to customer
no-redeclare
var a = 3;
// code code code
var a = 10;
No need to explain these
no-unused-expressions
"Hello world";
0
if(0) 0
{0}
f(0), {}
The international telephone dialing code for Antarctica is 672.
no-array-constructor
Array(500)
Array(500, 1, 2)
What's the differance
So - these are confusing notations...
Again - Stylistic rule - but considered almost a universal opinion
Actually - use of the Array constructor is considered bad practice unless for sparse matrix
// Build Array of 500 objects
// Build Array of 3 and init with values
consistent-return
function doSomething(condition) {
if (condition) {
return true; // return boolean
} else {
return; // return undefined
}
}
no-unreachable
function foo() {
return "bar"
var baz = "Oh No"; // Will we reach this point ?!
}
Yeah - you can write this in JavaScript
There are 293 ways to make change for a dollar.
JAVASCRIPT
Has alloooot of pitfalls
Yet - it's a really cool language, still evovling
FORMALITIES
Currently - during "Compile" stage
- LINT is turned on as warnings
From "Day after 10.3 branch" (End of April?)
- LINT will FAIL THE BUILD
I am sending list of errors every Sunday to TL
Thank you
PANAYA - DEV - LINTING PREVIEW
By Amir Gal-Or
PANAYA - DEV - LINTING PREVIEW
Describing "Front-End" code quality tool in Panaya
- 761