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
430
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
From Mission to Strategy: going over OKRs and Roadmap
sebarmeli
0
40
Managing a software engineering team
sebarmeli
1
330
Enforcing Coding Standards
sebarmeli
1
94
ES6: The future is now
sebarmeli
2
420
EcmaScript 6 - the future is here
sebarmeli
5
6.7k
Dependency management and Package management in JavaScript
sebarmeli
0
510
Karma - JS Test Runner
sebarmeli
1
650
RequireJS
sebarmeli
5
320
Lazy Load Everything!
sebarmeli
3
280
Other Decks in Programming
See All in Programming
Ruby Pattern Matching
bkuhlmann
0
610
Cloudflare WorkersでGoを動かすライブラリを作っている話
syumai
1
300
コンピュータビジョンセミナー2 / computer_vision_seminar_libSGM
fixstars
0
310
2023年にクル(かもしれない)通信ミドルウェア技術(仮)
s_hosoai
0
120
Makuakeの認証基盤とRe-Architectureチーム
bmf_san
0
330
Enumを自動で網羅的にテストしてみた
estie
0
1.2k
jq at the Shortcuts
cockscomb
1
400
Writing Greener Java Applications
hollycummins
0
330
Most Valuable Bug(?) ~インシデント未遂から得た学び~
tatsumiakahori
0
140
Zynq MP SoC で楽しむエッジコンピューティング ~RTLプログラミングのススメ~
ryuz88
0
280
ipa-medit: Memory search and patch tool for IPA without Jailbreaking/ipa-medit-bh2022-europe
tkmru
0
130
xarray-Datatree: Hierarchical Data Structures for Multi-Model Science
tomnicholas
0
210
Featured
See All Featured
Learning to Love Humans: Emotional Interface Design
aarron
263
38k
Intergalactic Javascript Robots from Outer Space
tanoku
261
26k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
217
21k
GitHub's CSS Performance
jonrohan
1020
430k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
270
12k
In The Pink: A Labor of Love
frogandcode
132
21k
VelocityConf: Rendering Performance Case Studies
addyosmani
317
22k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
182
15k
No one is an island. Learnings from fostering a developers community.
thoeni
12
1.5k
Writing Fast Ruby
sferik
613
58k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
224
50k
Testing 201, or: Great Expectations
jmmastey
25
5.7k
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