Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Enforcing coding standards in a JS project
Search
Sebastiano Armeli
May 14, 2015
Programming
0
590
Enforcing coding standards in a JS project
Talk given at JSConf Budapest (Budapest, Hungary) - May 2015
Sebastiano Armeli
May 14, 2015
Tweet
Share
More Decks by Sebastiano Armeli
See All by Sebastiano Armeli
Cultivate Excellence In Engineering Teams through Continuous Software Engineering
sebarmeli
1
170
From Strategy Definition to Execution with OKRs and Roadmap
sebarmeli
0
160
From Mission to Strategy: going over OKRs and Roadmap
sebarmeli
0
280
Managing a software engineering team
sebarmeli
1
600
Enforcing Coding Standards
sebarmeli
1
120
ES6: The future is now
sebarmeli
2
480
EcmaScript 6 - the future is here
sebarmeli
5
7.3k
Dependency management and Package management in JavaScript
sebarmeli
0
740
Karma - JS Test Runner
sebarmeli
1
850
Other Decks in Programming
See All in Programming
チームの境界をブチ抜いていけ
tokai235
0
210
他言語経験者が Golangci-lint を最初のコーディングメンターにした話 / How Golangci-lint Became My First Coding Mentor: A Story from a Polyglot Programmer
uma31
0
330
EMこそClaude Codeでコード調査しよう
shibayu36
0
290
Pythonに漸進的に型をつける
nealle
1
100
One Enishi After Another
snoozer05
PRO
0
140
Claude CodeによるAI駆動開発の実践 〜そこから見えてきたこれからのプログラミング〜
iriikeita
0
320
大規模アプリのDIフレームワーク刷新戦略 ~過去最大規模の並行開発を止めずにアプリ全体に導入するまで~
mot_techtalk
1
470
なぜあの開発者はDevRelに伴走し続けるのか / Why Does That Developer Keep Running Alongside DevRel?
nrslib
3
410
釣り地図SNSにおける有料機能の実装
nokonoko1203
0
190
CSC305 Lecture 10
javiergs
PRO
0
220
あなたとKaigi on Rails / Kaigi on Rails + You
shimoju
0
170
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
370
Featured
See All Featured
The Pragmatic Product Professional
lauravandoore
36
7k
Building Applications with DynamoDB
mza
96
6.7k
For a Future-Friendly Web
brad_frost
180
10k
Building Adaptive Systems
keathley
44
2.8k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.6k
Gamification - CAS2011
davidbonilla
81
5.5k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Rails Girls Zürich Keynote
gr2m
95
14k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
KATA
mclloyd
PRO
32
15k
Automating Front-end Workflow
addyosmani
1371
200k
How to Ace a Technical Interview
jacobian
280
24k
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 <
[email protected]
> Date:
Tue Jan 6 11:48:59 2015 -0500 refactor(BaseAd): Removed addToStreamTime method from BaseAd commit 7bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb Author: Sebastiano Armeli <
[email protected]
> 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 <
[email protected]
> <…@gmail.com> Jason Palmer <
[email protected]
>
<
[email protected]
> Joseph Werle <
[email protected]
> <…@gmail.com> Olof Kihlberg <…@spotify.com> Sigfrido Chirinos <…@spotify.com> .mailmap
None
Sebastiano Armeli @sebarmeli