All too often front-end JavaScript code has been considered a second class citizen, and when treated without due care and attention it can be buggy and hard to maintain. This attitude is changing though, and thanks to the rapid growth in popularity of JavaScript as a first-class language, there is a large and expanding ecosystem of tools that a developer should know to make their client-side code as “clean” as the rest of their stack.
This talk aims to introduce and discuss how to implement modularisation, functional idioms and testing in JavaScript in an idiomatic way, to allow you to code JavaScript to a higher quality and, ultimately, more sustainably.
2. W H O A M I ?
• David Simons
• @SwamWithTurtles
• swamwithturtles.com
• Technical Lead on a
range of projects
• Mostly JS or Java around
data visualisation
• Open-source contributor
• Background in Statistics
& Simulation
3. W H O A M I ?
• Softwire
• Software Consultancy in
London & Bristol
• We work on a lot of
projects
What you see today is
knowledge gained
through hard-won
experience.
4. W H AT A R E W E TA L K I N G A B O U T
T O D AY ?
PA S T P R E S E N T F U T U R E
JavaScript’s
Legacy
The Modern
Ecosystem &
Solutions
Practical Next
Steps
5. W H AT A R E W E TA L K I N G A B O U T
T O D AY ?
• Some of the problems of JavaScript - and the impacts
of them
• Native, languages and third party solutions to these
problems
6. W H AT W E ’ R E N O T TA L K I N G A B O U T
• HTML/CSS
• Server-side JavaScript
• (In-Depth) Discussions of ES6/ES2015
• In-Depth Discussions of any JavaScript library
8. A ( B R I E F ) H I S T O RY O F
J AVA S C R I P T
T I M E F O R A
9. H I S T O RY O F
J AVA S C R I P T
• First developed in 1995 by
Brendan Eich to provide
and support user-
interaction
• Much maligned, but the
only real way to run
interactive scripts on the
browser-side code
10. B A S I C S O F
J AVA S C R I P T
• Interpreted by browsers*
according to a set of rules
(ECMAScript)
• Combination of scripting
language, functional
language and object-
oriented language
11. W H Y J AVA S C R I P T WA S S O M A L I G N E D ?
12. H O W J AVA S C R I P T
U S E D T O W O R K
• Swathes of code from sites
like DynamicDrive and
then tinkered and added.
13. H O W J AVA S C R I P T
U S E D T O W O R K
• In more professional
outfits…
• Things may have been
done better, but if so,
people were fighting the
ecosystem
14. W H AT P R O B L E M S A R E
T H E R E ?
S O …
15. O N E B I G
‘ L U M P ’ O F
F I L E S
W E D O N ’ T L I K E
16. O N E B I G ‘ L U M P ’
O F F I L E S
• One big, long script with
loads of global variables
was added to page that
had the potential to
conflict
• No easy way to
encapsulate code
17. O N E B I G ‘ L U M P ’
O F F I L E S
• Very hard to unit test well
18. L A C K O F
C L A S S E S
W E D O N ’ T L I K E
19. P R O T O T Y PA L
I N H E R I TA N C E
• No Classes
• No Classical Inheritance
21. J AVA S C R I P T ’ S
S C O P E
• JavaScript has “functional”
scope
22. var func = function() {
var localVar = 7;
console.log(localVar);
}
console.log(localVar);
23. I M P L I C AT I O N S
• No such thing as “private
variable” - if we want to
make sure that a variable is
not accessible everywhere
we have to embed it in a
function
24. I T S T Y P E
S Y S T E M
W E D O N ’ T L I K E …
25. J AVA S C R I P T ’ S
“ U N D E F I N E D ”
T Y P E S
• null
• undefined
• NaN
26. T Y P E
C A S T I N G
• 1 + true =
• {} + 1 =
• 1 + {} =
• 2 + false =
• “2” + false =
27. T Y P E
C A S T I N G
• 1 + true = 2
• {} + 1 = 1
• 1 + {} =
“1[object Object]”
• 2 + false = 2
• “2” + false = “2false”
28. T R U T H Y A N D
FA L S E
• Every variable gets cast to
either true or false
• Falsey variables:
• 0, “”, false,
null, undefined,
NaN
• Every other value is truth -
that is, cast to true
29. W H Y D O W E C A R E
A B O U T T H I S * ?
B U T I N E E D T O K N O W
*aka… How do we sell this to the business?
31. W H Y C L E A N
C O D E ?
• There are many good
books written extolling the
virtues of clean code
32. R E A D A B L E
• You aren’t the only person
working on your code.
• Readable code eases
learning (including future
you) of what you are doing
on the project
• Including use of standard
patterns
33. E N C A P S U L AT E D
• Layered or encapsulated
architectures make code
more understandable
• If these are driven by
business or functional
concerns, they are
swappable
• Enhancements are broken
into smaller bits
34. T E S T E D
• Testing provides assurance
that changes don’t break
old functionality
• Ensuring code is unit-
testable enforces good
design decisions
• It provides running
documentation of your
code
40. T H E B O T T O M
L I N E
• Poorly tested code is error-
prone, likely to regress and
like to need correction
• Poorly written code increases
the cost of software
maintenance, software
enhancement and team
changes.
• Poor tooling decreases
productivity and increases
employee churn.
41. T H E B O T T O M
L I N E
• Bad software is more
expensive.
• Lots of legacy JavaScript is
bad.
42. R E C A P
1
2
3
JavaScript is the only (modern) language that
can be run on browsers
Due to historical context, it’s unpleasant to
work with and lacking in modern features
These problems significantly impact the cost,
quality and timescales of a project.
44. B E T T E R J AVA S C R I P T
W E C A N W R I T E …
45. A B A D
W O R K M A N
• “A bad workman blames
his tools”
• Sometimes you work
against the idioms of
the language
• “Transliterated” C#
code is not always
good JavaScript
46. A P R O V I S O
• “A good workman knows
when his tools are
inadequate, and is always
seeking to find better more
effective tools.”
• Sometimes a language
sets up a ridiculous
paradigm to adhere
to.
• *ahemXSLTahem*
47. S O B E F O R E W E
M O V E O N …
• A few things that make me
want to bang JavaScript
code against a brick wall.
48. U N D E R S TA N D
I T S L A N G U A G E
F E AT U R E S
50. I T ’ S J U S T
J AVA S C R I P T
• Lots of misunderstanding
about JavaScript
• (I blame jQuery)
• It’s not as featureless as
you may think!
51. Y O U ’ R E
W R I T I N G
J AVA S C R I P T.
N O T C #
52. Y O U ’ R E W R I T I N G
J AVA S C R I P T. N O T
C #
• You don’t have classes.
You don’t have (classical)
inheritance.
• You don’t have strong
types
• You can use prototypes, or
take advantage of the
dynamically typed nature
of the language
53. Y O U ’ R E W R I T I N G
J AVA S C R I P T. N O T
C #
• JavaScript is very
functional, and has many
patterns revolving around
(e.g.) callbacks.
• You can’t avoid them.
54. J AVA S C R I P T I S
A F U N C T I O N A L
L A N G U A G E
55. J AVA S C R I P T I S A
F U N C T I O N A L
L A N G U A G E
• We can use functional
idioms like “map” and
“filter” and
“reduce” (post-IE8)
• So stop iterating through
for loops
56. R E I N V E N T I N G T H E
W H E E L
A V O I D
57. T H E
J AVA S C R I P T
E C O S Y S T E M
J A VA S C R I P T L I B R A R I E S
58. T H E
E C O S Y S T E M
• JavaScript doesn’t have a
load of stuff built in - it’s
fairly bare bones.
• But - because of the
prevalence (and quality) of
it, a lot of people have
supplemented it.
• Plug and Play Ecosystem
59. T H E
E C O S Y S T E M
• These modules are hosted
on repositories centrally (or
private versions if you have
private code)
• The big ones are
bower (more client-
side) and npm (more
server-side)
• (Think of NuGet, Maven
Central)
61. B O W E R
• Bower manages a central
repository of JavaScript
libraries
• Bower manages a
bower.json file in your
codebase that teaches it
what dependency you need.
• Typically use the CLI
• bower install --
save [moduleName]
62. I N T E R E S T I N G
J AVA S C R I P T
L I B R A R I E S
E X A M P L E S O F
63. G R A P H I C S ,
C H A R T I N G A N D
R E N D E R I N G
• D3.js (& wrappers)
• “Data-Driven
Documents” i.e. styling
the DOM conditionally
on value
• Wrapped by Chart.js, C3
and NVD3 to provide
charting libraries
64. F O R M AT T I N G
L I B R A R I E S
• NumeralJS/Moment
• Take raw strings and
format them as dates or
numbers using format
strings (“DDMMYY” or
“$0.00”
• Provide lots of domain-
specific methods
65. P R O M I S E S &
F U N C T I O N S
• Q
• Adds promises to
JavaScript, to get rid of
callback hell.
• Lodash
• Provides lots of
functional idioms for
object and array
manipulation
67. M O D U L A R I S AT I O N :
W H AT A N D W H Y ?
M O D U L A R J A VA S C R I P T
68. W H AT I S A M O D U L E ?
A self-contained piece of code, that doesn’t
expose internal dealings
69. H O W T O M A K E
M O D U L E S
• JavaScript has no in-built
way of creating modules
(yet!) so we have to do it
ourself.
• JavaScript design patterns
has an example of how this
could work…
70. T H E S A N D B O X PAT T E R N
var module = function() {
var foo = “private”;
return {
getVar: function() {
return foo;
},
setVar: function(newFoo) {
foo = newFoo;
}
}
}
74. R E Q U I R E J S
M O D U L A R J A VA S C R I P T
75. R E Q U I R E . J S
• Require.JS is a “module
loader” framework
• You define one or more
“entry points”
• Require.JS will encapsulate
your modules by default,
and allow you to define
dependencies between
the modules.
76. M O D U L E S
C A N B E …
• Your own code
• or Third party libraries
downloaded through (e.g.)
Bower
• Most will now support
RequireJS and other
module loaders by
default.
77. D E F I N I N G A M O D U L E
define([dependencies], function(depNames)
{
//stuff you want to keep “private”
return module;
})
78. D E F I N I N G A M O D U L E
define([“lodash”], function(_) {
var array = [1, 2, 3];
var addOne = function(x) { return x + 1; }
return _.map(array, addOne);
})
79. N O T J U S T J AVA S C R I P T
F R O N T- E N D C O D E T H A T ’ S
80. W H Y D O N ’ T W E J U S T
D U M P J AVA S C R I P T ?
81. W H Y D O N ’ T W E
J U S T D U M P
J AVA S C R I P T ?
• The alternatives:
• Flash
• Java Applets
• Server-side Rendering
(JSPs, Razor)
• For complex client
interaction, JavaScript is
the only option
83. T H E J V M
W R I T T E N
J AVA
J AVA B Y T E
C O D E
J V M
( “ J AVA V I RT U A L
M A C H I N E ” )
U N I X W I N D O W S
84. T H E J V M
W R I T T E N
J AVA
J AVA B Y T E
C O D E
J V M
( “ J AVA V I RT U A L
M A C H I N E ” )
U N I X W I N D O W S
G R O O V Y
S C A L A
85. S O W H E N W E S E E T H I S PAT T E R N …
J AVA S C R I P T
J AVA S C R I P T
R U N T I M E
C H R O M E S A FA R I
86. … W E S TA R T T O T H I N K
J AVA S C R I P T
J AVA S C R I P T
R U N T I M E
C H R O M E S A FA R I
“ C O M P I L E D T O J S ”
L A N G U A G E S
87. C O M P I L E D T O J S L A N G U A G E S
https://github.com/jashkenas/coffeescript/wiki/List-of-languages-that-compile-to-JS
Early Adopters: Different languages with
to-JS compilers
89. T Y P E S C R I P T
• Strongly typed
• Adds missing features (e.g.
classes, modules, package
manager)
• Strict superset of Javascript
• Backwards compatible with
other libraries due to Open
Source type mappings
90. T Y P E S C R I P T
class Node {
labels:string[] = [];
constructor() {
}
getLabels():string[] {
return this.labels;
}
addLabel(label:string) {
if(this.labels.indexOf(label) < 0) {
this.labels.push(label);
}
}
}
92. W H Y T E S T
C O D E ?
T E S T I N G J A VA S C R I P T
93. W H Y T E S T ?
• Reduce Regressions
• Reduce bugs in new
and old features
94. W H Y T E S T ?
• Make code more
maintainable
• Aids understanding
through
documentation
• Reduce the cost of
change
95. W H Y T E S T ?
• Improve Design
• Untestable code is
bad code
• Forces you to think
and plan
96. H O W T O T E S T
Y O U R F R O N T- E N D ?
• Functional testing with
Selenium
• Unit testing
• Ideally both!
97. W E ’ R E G O I N G T O
TA L K A B O U T U N I T
T E S T I N G
• But some great references
to functional testing
• https://code.google.com/p/
robotframework/wiki/
HowToWriteGoodTestCases
• http://www.seleniumhq.org/docs/
01_introducing_selenium.jsp
• http://martinfowler.com/bliki/
PageObject.html
• https://www.youtube.com/watch?
v=FSWGVh5qJ4k
98. U N I T T E S T I N G
J A VA S C R I P T T E S T I N G
99. W H AT I S A
U N I T T E S T ?
• Testing isolated parts of
functionality
• Allows you to test simple,
small parts of the system
• Significantly easier when
modules are involved!
100. H O W D O W E D O
T H I S I N
J AVA S C R I P T ?
• It can be hard
• JavaScript testing isn’t as
prevalent part of the native
language as NUnit/JUnit
are.
• There are loads of libraries
for it though.
101. T H E J AVA S C R I P T
U N I T T E S T I N G
L I F E C Y C L E
• Writing a test
• Creating any necessary
test doubles
• Making any relevant
assertions
• Running the tests
102. W R I T I N G A
T E S T
• We don’t have classes any
more, so tests are nested
functions.
• JS test frameworks
encourage a full “BDD”
style test description:
• describe what unit your
testing, and
• say what it should do
103. M O C H A
describe('Array', function() {
describe('#indexOf()', function () {
it('should return -1 if value isn’t present', function () {
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});
104. M O C H A
• Mocha is a lightweight test
framework
• ‘describe’ and ‘it’
callbacks to get nicely
rendered test suites
• Basic assertions
• Before/After hooks
• Support for
asynchronous tests
105. T E S T D O U B L E S
I N J AVA S C R I P T
T E S T I N G J A VA S C R I P T
106. W H AT I S A
T E S T D O U B L E ?
• When unit testing, a way
to isolate dependencies
using a simplified object
under your control
107. W H AT I S A
T E S T D O U B L E ?
• Stub - source of controlled data
• Mock - set up to acted on as
expected
• Spy - Record information and
respond to questions
• Dummy - based around but not
used
• Fake - Mostly working, with
dangerous or complex logic
stripped out
108. D I Y T E S T D O U B L E S
var stubGateway = {
save: function() {
return [1, 2, 3];
}
}
describe(“The Data User”, function() {
it(“should give you the data count”, function() {
var dataUser = dataUser(stubGateway);
assert.equal(dataUser.dataCount.length, 2);
})
})
109. T H I S I S E A S I E R
I N J AVA S C R I P T
• Dynamic typing means we
don’t need any
overcomplicated interfaces
or types
• But libraries do exist for
more complex use cases.
110. T E S T D O U B L E S W I T H S I M O N
describe(“The Data User”, function() {
it(“should give you the data count”, function() {
var spyCallback = sinon.spy();
var dataUser = dataUser(spyCallback);
dataUser.saveData();
assert(spyCallback.calledOnce);
})
})
111. A S S E R T I O N S
• Often, default assertion
libraries are harder to read
and limited in functionality
• There’s a JS library for
that!
112. C H A I
tea.should.have.property('flavors')
.with.length(3);
doc.should.be.an(‘object');
expect(answer, 'topic [answer]’)
.to.equal(42);
assert.lengthOf(foo, 3,
‘foo should has a length of 3');
113. T E S T
R U N N E R S
• The tests need to be run
somewhere
• Either in a browser or on a
client-side “JavaScript
runtime” (typically
Node.js)
114. T E S T
R U N N E R S
• Third party ‘test runners’
exist to manage this
process for you and give
you nice outputs.
• Karma is a stable, well-
supported runner
• Wallaby.JS integrates
with your IDE to provide
in-line coverage and
continuous test running.
115. B U I L D I N G Y O U R C O D E
W H E N I T C O M E S T O
116. W H AT W E ’ V E
TA L K E D A B O U T S O
FA R
• Third party libraries
• Modules
• Languages that compile to
JavaScript
• Testing
117. W H AT W E ’ V E
TA L K E D A B O U T S O
FA R
• These all require external
processes to the
JavaScript
• It’s no longer good
enough to just statically
serve files
118. B U I L D T O O L S
• We need build tools to
ensure that any steps are
run in an automated and
deterministic manner
120. W H AT T H E Y
D O
• Automate necessary build
steps
• Compile Code
• Fetch Dependencies
• Run Tests
• Produce Executables
121. T H E J AVA S C R I P T
B U I L D T O O L S
• Like everything else,
there’s loads out there at
the moment
• We favour the relative
maturity of Grunt
122. G R U N T
• Grunt stores its config in a
“Gruntfile” (think .csproj or
pom.xml)
• These contain its
dependencies and
descriptions of the
processes you may want it
to run
• Most of what it can do is
third party
123. G R U N T
• Can be made to run from
other build tools (inc.
MSBuild and Maven)
• This means you only have
to “build” your project
once to have it run.
124. E X A M P L E O F A G R U N T F I L E
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
globals: {
jQuery: true
}
}
},
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint']
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['jshint']);
};
125. E X A M P L E O F A G R U N T F I L E
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
globals: {
jQuery: true
}
}
},
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint']
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['jshint']);
};
126. E X A M P L E O F A G R U N T F I L E
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
globals: {
jQuery: true
}
}
},
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint']
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['jshint']);
};
127. E X A M P L E O F A G R U N T F I L E
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
globals: {
jQuery: true
}
}
},
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint']
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['jshint']);
};
128. G R U N T TA S K S
grunt.loadNpmTasks('grunt-karma');
grunt.initConfic({
karma: {
unit: {
configFile: 'karma.conf.js'
}
}
});
grunt.registerTask('test', [‘jshint’, ’karma’]);
129. G R U N T ’ S
P L U G I N
A R C H I T E C T U R E
130. S A M P L E
P L U G I N S
• Test runners for all major
testing ecosystems
• Compilers for most third
party libraries
• Test Coverage (with Istanbul)
• Pre-compilers for SASS/LESS
• Rerun tasks when certain
“watched” files are changed
133. S E R V E R - S I D E
C O D E I S A R E A L
O P T I O N
• Razor for .NET and JSPs/
Thymeleaf for Java
• Keep all logic in the server-
side, and only send
rendered content
134. B U T F O R S O M E
P R O B L E M S …
• Can be very slow, since all
computation must be
done before sending the
response
• Forces a page refresh
every time new data
appears
• Limits ways clients can
interact
136. J Q U E RY I S G O O D
F O R S O M E T H I N G S
• DOM Manipulation
• Ajax Requests
• Very specific visual/UI
concerns
137. B U T I T ’ S
B L O AT E D
• Early JavaScript was hard
to maintain and add to, so
most libraries
bootstrapped ‘$’.
• It contained everything,
and people assumed
jQuery was native JS.
138. A N D M I X E S
C O N C E R N
• jQuery had visual/DOM
manipulation and data
processing libraries
• Everyone forgot their clean
code principles
139. S O W H AT D O W E
D O W I T H J Q U E RY ?
• Use it for DOM
manipulation and Ajax
requests…
• … but encapsulate these
parts to provide better
structure to your code.
140. T H E R E ’ S
P L U G I N S F O R
T H AT !
E N C A P S U L A T I N G U I S H A P I N G
C O D E ?
141. T H E M V *
PAT T E R N
• Separate the concerns of
getting and storing the
data (model) with how this
affects the visual aspects
of the page
• Like the MVC pattern in
web servers.
142. E X A M P L E S :
K N O C K O U T J S
• “MVVM” - model-view-
view model
var viewModel = {
age: ko.observable(12)
}
<input data-bind=”value: age” />
ko.applyBindings(viewModel)
143. E X A M P L E S :
A N G U L A R J S
• “MVW” - model-view-
whatever
function controller($scope) {
$scope.names = [‘Sally’, ‘Sam’]
}
<div ng-controller=”controller”>
<ul>
<li ng-repeat="name in names">
{{ name }}
</li>
</ul>
</div>
144. M V *
F R A M E W O R K S
• There are loads of good
client-side frameworks to
use - Ember, Backbone as
well as others.
• They all have a common
purpose in separating the
concerns of the data and
displaying it
145. W H I C H
F R A M E W O R K
S H O U L D I U S E ?
146. W H I C H
F R A M E W O R K
S H O U L D I U S E ?
• Our experience is focused
on the relative maturity of
KnockoutJS and
AngularJS.
• We’re keeping our eye on
React and Ember
147. A N G U L A R J S
V S . K N O C K O U T
• Set-Up Costs: Knockout
• Browser Support: Knockout
• Community Support:
Angular
• Ease of Learning: Knockout
• Testability: Angular
• Features: Angular
http://www.softwire.com/blog/2015/
09/15/angularjs-vs-knockoutjs-part-3/
148. T L ; D R
• We like AngularJS on
larger greenfield projects
where up-front costs will
pay dividends
• The small size of
KnockoutJS makes it
better to start migrating
legacy projects, and on
small projects.
149. R E C A P
1
2
3
4
Many of JS’s failings are solved by discipline,
libraries or using higher-level languages
Modules organise code and exist in ES2015+,
TypeScript and third party libraries
JavaScript should be tested, and frameworks
(Mocha, Jasmine…) exist to make this painless
UI-shaping code should be encapsulated with
MV* frameworks (Knockout, Angular)
151. G R E E N F I E L D P R O J E C T…
S O I ’ M O N A
152. A R C H I T E C T
Y O U R F R O N T-
E N D C O D E
153. A R C H I T E C T Y O U R
F R O N T- E N D C O D E
• Don’t abandon ‘evolving
design’ but do future proof
your architecture
• Plan the libraries and
frameworks you’ll use
• Structure your application
• Encapsulate concerns
154. O U R I D E A L
F R O N T- E N D
T E C H S TA C K
155. A P R O V I S O
• Every project is different
• This is what we think in the
abstract, but a range of
different project concerns
may change your mind.
156. L A N G U A G E
• TypeScript
• Built-in module system
and package manager
• Strongly typed
• Can use JS’s significant
ecosystem with types
157. B U I L D T O O L
• Grunt
• Compiles and minimises
TypeScript
• Will run tests and
provide coverage
158. T E S T I N G
E C O S Y S T E M
• Mocha, for the framework
• Chai for assertions
• Sinon (if needed) for
mocking/stubbing
• Karma to run tests, plus
WallabyJS for in-IDE
coverage.
159. M V *
F R A M E W O R K S
• AngularJS for projects that
will run for a while
• KnockoutJS for smaller or
less complex projects
160. M I G R AT I N G L E G A C Y
J AVA S C R I P T
I ’ M S T U C K …
161. O N L E G A C Y
C O D E
• It’s rarely feasible or cost-
effective to do everything
in one big go.
• So we present some
tactical “quick wins”
162. B O Y S C O U T
R U L E
• “Leave the codebase
cleaner than how you
found it.”
• Migrate away from old or
bad language features,
and towards third party
libraries and functional
paradigms where possible
163. A D D A B U I L D
T O O L
• Early on it will provide little
value, but is also cheap
• But doing this early
maximises the value of
other changes…
• … and prevents a costly
big migration in the future.
164. M I G R AT E T O
M O D U L E S
G R A D U A L LY
• Modularisation will
significantly improve your
code’s maintainability and
reuse.
• Add Require.js
• Whenever you work on a
piece of functionality in the
‘ball of mud’, extract it.
165. T E S T I N G
• Once modularised, unit
tests can be added.
• These are often hard
to write due to the
lack of testing in mind
• Functional Selenium tests
can test the underlying
user journeys to guard
against regressions.
166. A D D
K N O C K O U T
• Knockout can be migrated
to gradually, without
requiring significant up-
front investment.
• Best targeted tactically at
any place with significant
DOM manipulation based
on data.
167. W H AT W E D O N ’ T
R E C O M M E N D
• Quarantining the old ‘bad’
code and starting from
scratch moving forward
• Prohibits code re-use
• JS has a nasty habit of
using global variables or
randomly changing things
• Leads to poor
understanding and no
ownership of the old code.
168. W H AT W E D O N ’ T
R E C O M M E N D
• Attempting to adopt
codebase-shaping
frameworks in an
incremental manner
(where there are smaller
alternatives)
• AngularJS
• TypeScript
169. R E C A P
1
2
3
Your front-end code should be a first-class
consideration of any architecture
We recommend a stack of TypeScript, Grunt,
Mocha, Chai, Karma and an MV* package
There are tactical steps you can make to
migrate legacy JS - it’s not “all or nothing”.
171. T H E PA S T
1
2
3
JavaScript is the only (modern) language that
can be run on browsers
Due to historical context, it’s unpleasant to
work with and lacking in modern features
These problems significantly impact the cost,
quality and timescales of a project.
172. T H E P R E S E N T
1
2
3
4
Many of the failings are solved by discipline,
libraries or using higher-level languages
Modules organise code and exist in ES2015+,
TypeScript and third party libraries
JavaScript should be tested, and frameworks
(Mocha, Jasmine…) exist to make this painless
Integrating with HTML should be
encapsulated with MV* frameworks
173. T H E F U T U R E
1
2
3
Your front-end code should be a first-class
consideration of any architecture
We recommend a stack of TypeScript, Grunt,
Mocha, Chai, Karma and an MV* package
There are tactical steps you can make to
migrate legacy JS - it’s not “all or nothing”.