Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Enforcing coding standards in a JS project
Sebastiano Armeli-Battana
May 14, 2015
Programming
0
370
Enforcing coding standards in a JS project
Talk given at JSConf Budapest (Budapest, Hungary) - May 2015
Sebastiano Armeli-Battana
May 14, 2015
Tweet
Share
More Decks by Sebastiano Armeli-Battana
See All by Sebastiano Armeli-Battana
sebarmeli
1
250
sebarmeli
1
83
sebarmeli
2
390
sebarmeli
5
6.5k
sebarmeli
0
320
sebarmeli
1
450
sebarmeli
5
270
sebarmeli
3
230
sebarmeli
0
44
Other Decks in Programming
See All in Programming
takapy
0
110
manfredsteyer
PRO
0
120
ryosukes
0
1.4k
rarous
0
170
grapecity_dev
0
180
afilina
PRO
0
150
larsrh
0
110
osyo
0
330
manfredsteyer
PRO
0
220
manfredsteyer
PRO
0
110
christianweyer
PRO
0
290
mehowte
0
180
Featured
See All Featured
edds
56
9.4k
bryan
100
11k
holman
461
280k
addyosmani
1346
190k
pauljervisheath
195
15k
geeforr
332
29k
reverentgeek
167
7.3k
frogandcode
128
20k
jnunemaker
PRO
40
4.6k
dotmariusz
94
5.5k
marcelosomers
221
15k
akmur
252
19k
Transcript
ENFORCING CODING STANDARDS in a JS PROJECT
Sebastiano Armeli @sebarmeli 14/05/2015 - JSConf BD
to enforce verb (used with object), enforced, enforcing. to put
or keep in force; to compel obedience to: “to enforce a rule; Traffic laws will be strictly enforced.”
None
None
standard noun a rule or principle that is used as
a basis for judgment: “They tried to establish standards for a new approach.”
None
commit 111111 Author: Sebastiano Armeli Date: Sun Dec 21 22:08:00
2014 -0500 adding something commit 2222222 Author: Sebastiano Armeli Date: Thu Dec 18 15:35:39 2014 -0500 it will work, trust me
myProject | |— module1.js |— module2.js |— module_3.js |— module_4.js
|— module5.js |— package.json
None
defined by your team Automate
http://facilitationjapan.com/wp-content/uploads/2013/09/consensus_building.jpg
AD LIBRARY
None
None
! IDE (Editorconfig) ! Quality & Style tools (JSHint, JSCS,
ESLint) ! Git commits standards ! Build tools (Grunt, Gulp) ! Language - Transpiler (ES6 - Babel) ! Complexity tool (Plato) Summary 1/2
! Testing (Mocha, Karma) ! Automated Release Flow (Jenkins, NPM)
! Setup script ! Documentation Summary 2/2
None
root = true [*] indent_style = space indent_size = 2
end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true .editorconfig
Coding Style & Quality Tools
Prevent bugs Improve code maintainability & readability Easy to
use
function increment(a) { return a + 1; } increment(1); //
undefined BUG!!
var x = y = z = "example"; Leaking Variables!!
None
{ "curly": true, "eqeqeq": false, "latedef": true, "newcap": true, "noarg":
true, "sub": true, "boss": true, "indent": 2, "noempty": true, "expr": true, "eqnull": true, "esnext": true, "browser": true, "white": true, "undef": true, "predef": [ “require”, "module", “exports", "CustomEvent"] } .jshintrc
{ "curly": true, "eqeqeq": false, "latedef": true, "newcap": true, "noarg":
true, "sub": true, "boss": true, "indent": 2, "noempty": true, "expr": true, "eqnull": true, "esnext": true, "browser": true, "white": true, "undef": true, "predef": [ “require”, "module", “exports", "CustomEvent"] } .jshintrc
{ "curly": true, "eqeqeq": false, "latedef": true, "newcap": true, "noarg":
true, "sub": true, "boss": true, "indent": 2, "noempty": true, "expr": true, "eqnull": true, "esnext": true, "browser": true, "white": true, "undef": true, "predef": [ “require”, "module", “exports", "CustomEvent"] } .jshintrc
JSCS
{ "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try"],
"disallowImplicitTypeConversion": ["string"], "disallowMultipleLineBreaks": true, "disallowMixedSpacesAndTabs": true, "disallowKeywords": ["with"], "disallowMultipleVarDecl": true, "disallowTrailingComma": true, "disallowTrailingWhitespace": true, "maximumLineLength": 80, "esnext": true } .jscsrc
{ "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try"],
"disallowImplicitTypeConversion": ["string"], "disallowMultipleLineBreaks": true, "disallowMixedSpacesAndTabs": true, "disallowKeywords": ["with"], "disallowMultipleVarDecl": true, "disallowTrailingComma": true, "disallowTrailingWhitespace": true, "maximumLineLength": 80, "esnext": true } .jscsrc
{ "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try"],
"disallowImplicitTypeConversion": ["string"], "disallowMultipleLineBreaks": true, "disallowMixedSpacesAndTabs": true, "disallowKeywords": ["with"], "disallowMultipleVarDecl": true, "disallowTrailingComma": true, "disallowTrailingWhitespace": true, "maximumLineLength": 80, "esnext": true } .jscsrc
None
--- parser: babel-eslint env: browser: true node: true mocha: true
es6: true .eslintrc
rules: space-before-blocks: 2 eqeqeq: [2, 'smart'] curly: [2, 'multi-line'] quotes:
[2, 'single'] space-after-keywords: 2 no-unused-vars: [2, args: none] no-comma-dangle: 2 no-unused-expressions: 0 no-multi-spaces: 2 …
rules: space-before-blocks: 2 eqeqeq: [2, 'smart'] curly: [2, 'multi-line'] quotes:
[2, 'single'] space-after-keywords: 2 no-unused-vars: [2, args: none] no-comma-dangle: 2 no-unused-expressions: 0 no-multi-spaces: 2 …
no-unused-vars: [2, args: none] function test1(a, b) { var c,
d = 2; return a + d; } test1(1, 2); Error!! function test2(a, b, c) { return a + b; } test2(1, 2); Ok
no-trailing-spaces: 2 no-mixed-spaces-and-tabs: 2 quotes: [2, ‘single’] indent: [2, 2]
"use strict”; module.exports = function(context) { return { "NewExpression": function(node)
{ if (node.callee.name === "Object") { context.report(node, “Error …”); } } }; }; no-new-object.js let obj = new Object(); let obj = {};
"use strict”; module.exports = function(context) { return { "NewExpression": function(node)
{ if (node.callee.name === "Object") { context.report(node, “Error …”); } } }; }; no-new-object.js let obj = {};
None
Git Commits (feat | fix | docs | style |
refactor | test | chore)(<scope>): <description> E.g. doc(readme): update with additional links.
Changelog conventional-changelog Changelog.md commit 7aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Author: Sebastiano Armeli <xxx@yyy.com> Date:
Tue Jan 6 11:48:59 2015 -0500 refactor(BaseAd): Removed addToStreamTime method from BaseAd commit 7bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb Author: Sebastiano Armeli <xxx@yyy.com> Date: Tue Jan 6 00:04:49 2015 -0500 style(gpt): rearrange for better readability
CHANGELOG.md
Build tool gulp test / gulp dev
var gulp = require('gulp'); var plugins = require(‘gulp-load-plugins')(); … gulp.task('eslint',
function() { return gulp.src(['src/**/*.js']) .pipe(plugins.eslint()) .pipe(plugins.eslint.format()) .pipe(plugins.eslint.failOnError()); }); … gulpfile.js
None
gulp es6 /src /dist ES6 ES5
Plato gulp plato
Testing
describe('#_onContainerResume', function() { it('should call play when container resumes', function()
{ videoAd.views.set(mockedVideoAdMetadata.id, { play: function() {}, hasBeenPlayed: true }); sinon.stub(videoAd.views.get(mockedVideoAdMetadata.id), 'play'); videoAd._onContainerResume(); expect(videoAd.views.get(mockedVideoAdMetadata.id).play).to.have .been.called; }); });
module.exports = function(config) { config.set({ basePath: '../', frameworks: ['mocha', 'fixture'],
files: [ …. ], browsers: ‘Chrome’, singleRun: false, preprocessors: { '**/*.html': ['html2js'], '**/*.json': ['html2js'] }, sauceLabs: { … } }); }; karma.conf.js
module.exports = function(config) { config.set({ basePath: '../', frameworks: ['mocha', 'fixture'],
files: [ …. ], browsers: ‘Chrome’, singleRun: false, preprocessors: { '**/*.html': ['html2js'], '**/*.json': ['html2js'] }, sauceLabs: { … } }); }; karma.conf.js
module.exports = function(config) { config.set({ basePath: '../', frameworks: ['mocha', 'fixture'],
files: [ …. ], browsers: ‘Chrome’, singleRun: false, preprocessors: { '**/*.html': ['html2js'], '**/*.json': ['html2js'] }, sauceLabs: { … } }); }; karma.conf.js
Automated Release flow gulp test:ci gulp bump:path gulp bump:minor gulp
bump:major Changelog.md
./setup.sh pre-commit hook + npm i && gulp test
Documentation README.md CONTRIBUTING.md
Documentation README.md CONTRIBUTING.md
/doc
Sebastiano Armeli <…@spotify.com> Brice Lin <..@spotify.com> <…@gmail.com> Jason Palmer <..@spotify.com>
<..@spotify.com> Joseph Werle <..@spotify.com> <…@gmail.com> Olof Kihlberg <…@spotify.com> Sigfrido Chirinos <…@spotify.com> .mailmap
None
Sebastiano Armeli @sebarmeli