SlideShare a Scribd company logo
1 of 49
codecentric d.o.o
Jovan Vidić, IT Consultant @ codecentric
Refactoring Java Script Applications
Motivation
Should We Refactor JavaScript?
Refactoring Sample Application
Beyond Refactoring
Agenda
~ 6 years of development
Java + DWR
732 JavaScript files
~ 20 000 lines of javascript code
Motivation - Legacy project
What was wrong?
- JavaScript in HTML
- Global functions
- Inline styles
- No coding style guidelines
- No tests
MOTIVATION - Legacy project
What was OK?
- OOP
- Throwing own errors
- Wrapping third party libraries
- Prototype.js
MOTIVATION - Legacy project
Should We Refactor JavaScript ?
“It is not necessary to change.
Survival is not mandatory”
W. Edwards Deming
W E Deming
What is Refactoring?
What is Refactoring?
a change made to the internal structure of software
to make it easier to understand and cheaper to modify
without changing its observable behavior
M. Fowler
This is not refactoring
agile manifesto 8th principle
Agile processes promote sustainable development.
The sponsors, developers, and users should be able
to maintain a constant pace indefinitely.
Refactoring Sample Application – v1 – index.html
</head>!
<body>!
<ul class="nav nav-pills">!
<li class="active"><a href="../../v1/client/index.html">V1</a></
li>!
<li><a href="../../v2/client/index.html">V2</a></li>!
<li><a href="../../v3/client/index.html">V3</a></li>!
<li><a href="../../v4/client/index.html">V4</a></li>!
<li><a href="../../v5/client/index.html">V5</a></li>!
</ul>!
<div class="page-header">!
<h1>Coding Serbia <small> Refactoring JavaScript Applications -
V1</small></h1>!
</div>!
<!-- Button trigger modal -->!
<button class="btn btn-primary btn-lg" data-toggle="modal"
onclick="createSpeaker()">!
Add Speaker!
</button>!
<script src="js/jquery.min.js"></script>!
<script src="js/bootstrap.min.js"></script>!
<script src="js/speakers.js"></script>!
!
<script type="text/javascript">!
load();!
</script>!
</body>!
Refactoring Sample Application – v1 – index.html
Refactoring Sample Application – v1 – speakers.js
function add() {!
var speakerId = $('#speakerId').val();!
!
$.ajax({!
type: speakerId == '' ? "POST" : "PUT",!
url: speakerId == '' ? "http://localhost:4730/speakers" : "http:/!
data: JSON.stringify({id: speakerId, firstName: $('#firstName').v!
contentType: "application/json; charset=utf-8",!
dataType: "json",!
success: function(data){ $('#speakerId').val(''); $('#firstName’)!
failure: function(errMsg) {alert(errMsg);}!
!
function load() {!
$.getJSON( "http://localhost:4730/speakers", function( data ) {!
var newRows = "";!
$.each(data, function(i,item) {!
var sessionTime = new Date(Date.parse(item.sessionTime));!
!
newRows += "<tr><td>" + sessionTime.toLocaleString() +"</td><!
});!
$(".table-striped tbody").html("");!
$(".table-striped tbody").append(newRows);!
});!
};!
Refactoring Sample Application – v1
It is a complete mess!
How should I start?
Refactoring Sample Application – v1 – selenium
Refactoring Sample Application – v1
What about JSLint/JSHIT?
It will scream at you!
Refactoring Sample Application – v2
Invert dependencies
Refactoring Sample Application – v2 - REQUIREJS
requirejs.config({!
paths: {!
"jquery": "lib/jquery.min",!
"bootstrap": "lib/bootstrap.min"!
},!
shim: {!
"bootstrap": {!
deps: ["jquery"]!
}!
}!
});!
!
require(["app/speakers","bootstrap"], function (speakers) {!
!
$("#btnSaveSpeaker").click(function() {!
speakers.save();!
});!
!
speakers.loadAll();!
});!
<script data-main="scripts/main" src="scripts/lib/require.js"></script>!
Refactoring Sample Application – V2 – SPEAKERS.JS & THEME.jS
define(["jquery","app/theme"], function ($, theme) {!
"use strict";!
!
var SpeakerControler = {!
loadAll : function () {!
$.getJSON("http://localhost:4730/speakers", function (data) {!
var speakersTable = $("." + theme.SPEAKERS_TABLE +" tbody")
define([], function () {!
"use strict";!
!
return {!
DELETE_BUTTON : "btn btn-danger glyphicon glyphicon-remove",!
EDIT_BUTTON : "btn btn-default glyphicon glyphicon-pencil",!
SPEAKERS_TABLE : "table-striped"!
};!
});!
Refactoring Sample Application – SPEAKERS.JS
define(["jquery","app/theme"], function ($, theme) {!
"use strict";!
!
var SpeakerControler = {!
loadAll : function () {!
cell.append($("<button class='"+theme.DELETE_BUTTON+"'></button>”)!
SpeakerControler.remove(item.id);!
}));
remove : function(id) {!
$.ajax({!
type: "DELETE",!
url: "http://localhost:4730/speaker/" + id,!
success: function() {!
SpeakerControler.loadAll();!
}!
});!
}!
return SpeakerControler;!
});
My code is isolated now
Can I write unit tests?
Refactoring Sample Application – v3
Manage dependencies
Refactoring Sample Application – v3 – bower.json
{!
"name": "javascript-refactoring",!
"version": "1.0",!
"authors": [!
"Jovan Vidic
<jovan.vidic@codecentric.de>"!
],!
"private": true,!
"ignore": [!
"node_modules",!
"bower_components",!
"test",!
"tests"!
],!
"dependencies": {!
"jquery": "1.11.1",!
"bootstrap" : "3.2.0",!
"requirejs" : "2.1.15"!
},!
!
"devDependencies": {!
!
}!
}!
Refactoring Sample Application – v4
Improve design
Introduce model objects & unit tests
Refactoring Sample Application – v4 – MODEL.JS
function Speaker(id, firstName, lastName, topic, sessionTime, track) {!
this.id = id;!
this.firstName = firstName;!
this.lastName = lastName;!
this.topic = topic;!
this.sessionTime = sessionTime;!
this.track = track;!
!
this.hasId = function () {!
return (this.id !== undefined) && (this.id !== null) !
&& (this.id !== "");!
};!
!
this.getFullName = function () {!
return this.firstName + " " + this.lastName;!
};!
}!
!
return {!
"Agenda" : {!
"Speaker" : Speaker!
}!
};!
Refactoring Sample Application – v4 – Speakers.JS
define(["jquery", "app/model", "app/theme"], function ($, model, theme) {!
"use strict";!
var SpeakerControler = {!
editSpeaker : function(id) {!
$.getJSON( "http://localhost:4730/speaker/" + id, !
function(speakerData) {!
if(speakerData) {!
var speaker = convertToModel(speakerData);!
showEditSpeakerPopup(speaker);!
}!
});!
}!
function showEditSpeakerPopup(speaker) {!
$('#myModalLabel').html('Edit speaker <strong>' !
+ speaker.getFullName() + "</strong>");!
}!
function convertToModel(speakerData) {!
return new model.Agenda.Speaker(speakerData.id,
speakerData.firstName, speakerData.lastName, speakerData.topic,
speakerData.sessionTime, speakerData.track);!
}
Refactoring Sample Application – v4 – jasmine
describe("Test model objects", function() {!
"use strict";!
!
var Model;!
!
beforeEach(function(done) {!
require(["app/model"], function (model) {!
Model = model;!
done();!
});!
});
it("should return Jovan Vidic when firstName is Jovan and lastName is
Vidic", function() {!
!
var speaker = new Model.Agenda.Speaker(1, "Jovan", "Vidic");!
!
expect(speaker.getFullName()).toBe("Jovan Vidic");!
});!
Refactoring Sample Application – v4
That's all cool but my code still stinks?!
Trust me I've been there
Refactoring Sample Application – v5
Improve design
&
automate
Refactoring Sample Application – v5 – SPEAKERS AJAX CLIENT
define(["jquery", "app/model"], function ($, model) {!
"use strict";!
!
var baseURL = requirejs.s.contexts._.config.cs["api-url"],!
speakersURL = baseURL + "speakers/",!
speakerURL = baseURL + "speaker/";!
!
function convertToModel(speakerData) {!
return new model.Agenda.Speaker(speakerData.id, speakerData.firstNa
}!
return {!
loadAllSpeakers : function (callbackHandle) {!
$.getJSON(speakersURL, function (speakersData) {!
var speakers = [];!
$.each(speakersData, function (index, speakerData) {!
var speaker = convertToModel(speakerData);!
speakers.push(speaker);!
});!
callbackHandle.success(speakers);!
});!
},
Refactoring Sample Application – v5 – Backend FACADE
define(["app/client/speakers_ajax_client"], function (speakersClient) {!
"use strict";!
!
return {!
loadAllSpeakers : function (callbackHandle) {!
speakersClient.loadAllSpeakers(callbackHandle);!
},!
!
saveSpeaker : function (speaker, callbackHandle) {!
speakersClient.saveSpeaker(speaker, callbackHandle);!
}!
Refactoring Sample Application – v5 - TesTS
define(["squire"], function (Squire) {!
"use strict";!
!
var injector = new Squire(),!
client = jasmine.createSpyObj("client", ["loadAllSpeakers",
"saveSpeaker", "removeSpeaker"]),!
callbackHandle = jasmine.createSpy("callback"),!
builder = injector.mock("app/client/speakers_ajax_client”, client);
!
describe("Test backend facade", function() {!
!
var backend;!
!
beforeEach(function(done) {!
builder.require(["app/backend_facade"], function(backendFacade)
backend = backendFacade;!
done();!
});!
});!
it("should loadAllSpeakers", function() {!
backend.loadAllSpeakers(callbackHandle);!
expect(client.loadAllSpeakers)!
.toHaveBeenCalledWith(callbackHandle);!
});!
!
!
Refactoring Sample Application – v5 - MVP
http://warren.chinalle.com/2010/12/18/model-view-presenter/
Refactoring Sample Application – v5 – speakers PRESENTER
define(["app/backend_facade", "app/speakers/speakers_view", !
"app/events"], function (backend, SpeakersView, events) {!
!
"use strict";!
!
var EventManager = events.EventManager,!
Actions = events.Actions;!
!
function SpeakerPresenter() { !
var view = new SpeakersView(),!
self;!
!
return {!
init : function () {!
self = this;!
EventManager.register(Actions.LOAD_ALL_SPEAKERS, this.loadAll);!
},!
loadAll : function () {!
backend.loadAllSpeakers({!
"success" : function (speakers) {!
view.showAll(speakers);!
}!
});!
},!
Refactoring Sample Application – v5 – Speakers view
define(["app/events", "app/components", "app/speakers/speakers_popup"], !
"use strict”;!
var EventManager = events.EventManager;!
!
function SpeakersView() {!
var speakersTable = new components.SpeakersTable(),!
createButton = new components.Button("btnAddSpeaker"),!
popup = new SpeakersPopup();!
!
function showCreateSpeakerDialog() {!
EventManager.fire(events.Actions.SHOW_CREATE_SPEAKER);!
}!
function init() {!
createButton.addClickListener(showCreateSpeakerDialog);!
}!
init();!
return {!
showAll : function (speakers) {!
var i, len;!
speakersTable.clear();!
for (i = 0, len = speakers.length; i < len; i += 1) {!
speakersTable.addSpeaker(speakers[i]);!
}!
}!
Refactoring Sample Application – v5 – SPEAKERS POPUP
define(["app/model", "app/events", "app/components"], function (model, even
!
function SpeakersPopup() {!
var speaker,!
popup = new components.Popup("myModal"),!
firstNameInput = new TextField("firstName"),!
!
function saveSpeaker() {!
speaker.firstName = firstNameInput.val();!
speaker.lastName = lastNameInput.val();!
speaker.topic = topicInput.val();!
!
if (speaker.hasId()) {!
EventManager.fire(events.Actions.EDIT_SPEAKER, speaker);!
} else {!
EventManager.fire(events.Actions.SAVE_SPEAKER, speaker);!
}!
}!
return {!
openAndSet : function (speakerToUpdate) {!
speaker = speakerToUpdate;!
firstNameInput.val(speaker.firstName);!
lastNameInput.val(speaker.lastName);!
!
Refactoring Sample Application – v5 – components
http://warren.chinalle.com/2010/12/18/model-view-presenter/
define(["jquery", "app/events", "app/theme"], function ($, events, theme)
!
function TextField(id) {!
var textField = $("#" + id);!
return {!
val : function (value) {!
if (value !== undefined) {!
textField.val(value);!
} else {!
return textField.val();!
}!
}!
};!
}!
!
function SimpleButton(id) {!
var button = $("#" + id);!
return {!
addClickListener : function (listener) {!
button.click(listener);!
}!
};!
}!
!
For the win
Refactoring Sample Application – v5 - GRUNT
grunt.initConfig({!
!
jslint: {!
src: [!
"scripts/**/*.js"!
],!
!
},!
!
karma: {!
unit: {!
configFile: "karma.conf.js"!
}!
},!
!
copy: {!
main: {!
files: [!
{expand: true, src: ["lib/bootstrap/dist/css/**"], dest: "dist/"},!
{expand: true, src: ["lib/bootstrap/dist/fonts/**"], dest: "dist/"}
{expand: true, src: ["lib/requirejs/require.js"], dest: "dist/"}!
]!
}!
}!
Refactoring Sample Application – v5 - GRUNT
requirejs: {!
compile: {!
options: {!
baseUrl: "scripts/",!
name: "main",!
out: "dist/app-built.js”,!
paths: {!
app: "app/",!
"jquery": "../lib/jquery/dist/jquery.min",!
"bootstrap": "../lib/bootstrap/dist/js/bootstrap"!
}!
}!
}!
},!
processhtml: {!
options: {!
data: { !
}!
},!
dist: {!
files: {!
"dist/index.html": ["index.html"]!
}!
}!
BEYOND REFACTORING
Coffeescript
define [], () ->!
!
class Speaker!
constructor: (@id, @firstName, @lastName, @topic, @sessionTime, @track)
->!
!
hasId: ->!
@id?.length != 0!
!
fullName: ->!
@firstName + " " + @lastName!
!
return {"Agenda": {"Speaker" : Speaker}} !
Literature
QUESTIONS
https://github.com/jovanvidic/javascript-refactoring
vidicj@gmail.com
@_yowan_
?

More Related Content

What's hot

Diseño de APIs con Ruby
Diseño de APIs con RubyDiseño de APIs con Ruby
Diseño de APIs con RubySoftware Guru
 
The Art and Science of Shipping Ember Apps
The Art and Science of Shipping Ember AppsThe Art and Science of Shipping Ember Apps
The Art and Science of Shipping Ember AppsJesse Cravens
 
Modern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on RailsModern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on RailsJonathan Johnson
 
A tour of React Native
A tour of React NativeA tour of React Native
A tour of React NativeTadeu Zagallo
 
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...Applitools
 
The Gist of React Native
The Gist of React NativeThe Gist of React Native
The Gist of React NativeDarren Cruse
 
Apache Cordova In Action
Apache Cordova In ActionApache Cordova In Action
Apache Cordova In ActionHazem Saleh
 
Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...
Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...
Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...JAX London
 
[English version] JavaFX and Web Integration
[English version] JavaFX and Web Integration[English version] JavaFX and Web Integration
[English version] JavaFX and Web IntegrationKazuchika Sekiya
 
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon RitterJava Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon RitterJAX London
 
Angularjs Tutorial for Beginners
Angularjs Tutorial for BeginnersAngularjs Tutorial for Beginners
Angularjs Tutorial for Beginnersrajkamaltibacademy
 
Continuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.io
Continuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.ioContinuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.io
Continuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.ioMike Fotinakis
 
Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011Jacob Kaplan-Moss
 
Creating books app with react native
Creating books app with react nativeCreating books app with react native
Creating books app with react nativeAli Sa'o
 
BPM-2 Introduction to Advanced Workflows
BPM-2 Introduction to Advanced WorkflowsBPM-2 Introduction to Advanced Workflows
BPM-2 Introduction to Advanced WorkflowsAlfresco Software
 
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Matt Raible
 

What's hot (20)

Diseño de APIs con Ruby
Diseño de APIs con RubyDiseño de APIs con Ruby
Diseño de APIs con Ruby
 
React Native
React NativeReact Native
React Native
 
The Art and Science of Shipping Ember Apps
The Art and Science of Shipping Ember AppsThe Art and Science of Shipping Ember Apps
The Art and Science of Shipping Ember Apps
 
Modern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on RailsModern JavaScript, without giving up on Rails
Modern JavaScript, without giving up on Rails
 
A tour of React Native
A tour of React NativeA tour of React Native
A tour of React Native
 
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...
*Webinar* Learn from the Experts: How to Boost Test Coverage with Automated V...
 
How to React Native
How to React NativeHow to React Native
How to React Native
 
The Gist of React Native
The Gist of React NativeThe Gist of React Native
The Gist of React Native
 
Apache Cordova In Action
Apache Cordova In ActionApache Cordova In Action
Apache Cordova In Action
 
Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...
Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...
Spring Day | WaveMaker - Spring Roo - SpringSource Tool Suite: Choosing the R...
 
[English version] JavaFX and Web Integration
[English version] JavaFX and Web Integration[English version] JavaFX and Web Integration
[English version] JavaFX and Web Integration
 
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon RitterJava Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
Java Core | JavaFX 2.0: Great User Interfaces in Java | Simon Ritter
 
Agile toolkit present 2012
Agile toolkit present 2012Agile toolkit present 2012
Agile toolkit present 2012
 
Angularjs Tutorial for Beginners
Angularjs Tutorial for BeginnersAngularjs Tutorial for Beginners
Angularjs Tutorial for Beginners
 
Continuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.io
Continuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.ioContinuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.io
Continuous Visual Integration - RailsConf 2016 - Mike Fotinakis - Percy.io
 
Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011
 
Creating books app with react native
Creating books app with react nativeCreating books app with react native
Creating books app with react native
 
BPM-2 Introduction to Advanced Workflows
BPM-2 Introduction to Advanced WorkflowsBPM-2 Introduction to Advanced Workflows
BPM-2 Introduction to Advanced Workflows
 
React native
React nativeReact native
React native
 
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
Comparing Hot JavaScript Frameworks: AngularJS, Ember.js and React.js - Sprin...
 

Viewers also liked

Redefining Projects For an Age of Complexity
Redefining Projects For an Age of ComplexityRedefining Projects For an Age of Complexity
Redefining Projects For an Age of ComplexityJovan Vidić
 
How To Start Agile Competence Center
How To Start Agile Competence CenterHow To Start Agile Competence Center
How To Start Agile Competence CenterJovan Vidić
 
5 Games for Effective Agile Coaching
5 Games for Effective Agile Coaching5 Games for Effective Agile Coaching
5 Games for Effective Agile CoachingJovan Vidić
 
La Higiene Postural
La Higiene PosturalLa Higiene Postural
La Higiene Posturalguest261b8
 
Higiene postural[1]
Higiene postural[1]Higiene postural[1]
Higiene postural[1]Henry Leiva
 
Enfermedades ocupacionales
Enfermedades ocupacionalesEnfermedades ocupacionales
Enfermedades ocupacionalesaguzmanvel
 
Higiene postural y pausas activas
Higiene postural y pausas activasHigiene postural y pausas activas
Higiene postural y pausas activasoscarruiz254
 
Principales enfermedades causadas por una mala postura corporal
Principales enfermedades causadas por una mala postura corporalPrincipales enfermedades causadas por una mala postura corporal
Principales enfermedades causadas por una mala postura corporalSuny Sanchez
 
Ergonomía higiene postural
Ergonomía  higiene posturalErgonomía  higiene postural
Ergonomía higiene posturalvicaaron
 
Taller de higiene postural
Taller de higiene posturalTaller de higiene postural
Taller de higiene posturaljuanjoreverte
 

Viewers also liked (14)

Redefining Projects For an Age of Complexity
Redefining Projects For an Age of ComplexityRedefining Projects For an Age of Complexity
Redefining Projects For an Age of Complexity
 
How To Start Agile Competence Center
How To Start Agile Competence CenterHow To Start Agile Competence Center
How To Start Agile Competence Center
 
LA COLUMNA VERTEBRAL
LA COLUMNA VERTEBRALLA COLUMNA VERTEBRAL
LA COLUMNA VERTEBRAL
 
5 Games for Effective Agile Coaching
5 Games for Effective Agile Coaching5 Games for Effective Agile Coaching
5 Games for Effective Agile Coaching
 
La Higiene Postural
La Higiene PosturalLa Higiene Postural
La Higiene Postural
 
Higiene Postural 2º ESO
Higiene Postural 2º ESOHigiene Postural 2º ESO
Higiene Postural 2º ESO
 
Higiene postural[1]
Higiene postural[1]Higiene postural[1]
Higiene postural[1]
 
Capacitacion higiene postural
Capacitacion higiene posturalCapacitacion higiene postural
Capacitacion higiene postural
 
Enfermedades ocupacionales
Enfermedades ocupacionalesEnfermedades ocupacionales
Enfermedades ocupacionales
 
Higiene postural
Higiene posturalHigiene postural
Higiene postural
 
Higiene postural y pausas activas
Higiene postural y pausas activasHigiene postural y pausas activas
Higiene postural y pausas activas
 
Principales enfermedades causadas por una mala postura corporal
Principales enfermedades causadas por una mala postura corporalPrincipales enfermedades causadas por una mala postura corporal
Principales enfermedades causadas por una mala postura corporal
 
Ergonomía higiene postural
Ergonomía  higiene posturalErgonomía  higiene postural
Ergonomía higiene postural
 
Taller de higiene postural
Taller de higiene posturalTaller de higiene postural
Taller de higiene postural
 

Similar to Refactoring JavaScript Applications

WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Ran Mizrahi
 
Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Ran Mizrahi
 
Coffee@DBG - Exploring Angular JS
Coffee@DBG - Exploring Angular JSCoffee@DBG - Exploring Angular JS
Coffee@DBG - Exploring Angular JSDeepu S Nath
 
BPM-4 Migration from jBPM to Activiti
BPM-4 Migration from jBPM to ActivitiBPM-4 Migration from jBPM to Activiti
BPM-4 Migration from jBPM to ActivitiAlfresco Software
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSModular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSGunnar Hillert
 
Developing Java Web Applications
Developing Java Web ApplicationsDeveloping Java Web Applications
Developing Java Web Applicationshchen1
 
How I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScriptHow I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScriptKevin Read
 
Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8Kevin Read
 
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache CordovaHazem Saleh
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundryrajdeep
 
Unlocking the power of the APEX Plugin Architecture
Unlocking the power of the APEX Plugin ArchitectureUnlocking the power of the APEX Plugin Architecture
Unlocking the power of the APEX Plugin ArchitectureMatt Nolan
 
WSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected Business
WSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected BusinessWSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected Business
WSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected BusinessWSO2
 
Developer Productivity with Forge, Java EE 6 and Arquillian
Developer Productivity with Forge, Java EE 6 and ArquillianDeveloper Productivity with Forge, Java EE 6 and Arquillian
Developer Productivity with Forge, Java EE 6 and ArquillianRay Ploski
 
Server Side JavaScript on the Java Platform - David Delabassee
Server Side JavaScript on the Java Platform - David DelabasseeServer Side JavaScript on the Java Platform - David Delabassee
Server Side JavaScript on the Java Platform - David DelabasseeJAXLondon2014
 
In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsIn Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsSpike Brehm
 

Similar to Refactoring JavaScript Applications (20)

WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)
 
Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)
 
Avatar 2.0
Avatar 2.0Avatar 2.0
Avatar 2.0
 
Coffee@DBG - Exploring Angular JS
Coffee@DBG - Exploring Angular JSCoffee@DBG - Exploring Angular JS
Coffee@DBG - Exploring Angular JS
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
 
BPM-4 Migration from jBPM to Activiti
BPM-4 Migration from jBPM to ActivitiBPM-4 Migration from jBPM to Activiti
BPM-4 Migration from jBPM to Activiti
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSModular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJS
 
Jsf2 overview
Jsf2 overviewJsf2 overview
Jsf2 overview
 
Developing Java Web Applications
Developing Java Web ApplicationsDeveloping Java Web Applications
Developing Java Web Applications
 
How I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScriptHow I learned to stop worrying and love embedding JavaScript
How I learned to stop worrying and love embedding JavaScript
 
Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8Embedding V8 in Android apps with Ejecta-V8
Embedding V8 in Android apps with Ejecta-V8
 
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundry
 
Unlocking the power of the APEX Plugin Architecture
Unlocking the power of the APEX Plugin ArchitectureUnlocking the power of the APEX Plugin Architecture
Unlocking the power of the APEX Plugin Architecture
 
WSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected Business
WSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected BusinessWSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected Business
WSO2Con Asia 2014 - WSO2 AppDev Platform for the Connected Business
 
WSO2 AppDev platform
WSO2 AppDev platformWSO2 AppDev platform
WSO2 AppDev platform
 
Developer Productivity with Forge, Java EE 6 and Arquillian
Developer Productivity with Forge, Java EE 6 and ArquillianDeveloper Productivity with Forge, Java EE 6 and Arquillian
Developer Productivity with Forge, Java EE 6 and Arquillian
 
Server Side JavaScript on the Java Platform - David Delabassee
Server Side JavaScript on the Java Platform - David DelabasseeServer Side JavaScript on the Java Platform - David Delabassee
Server Side JavaScript on the Java Platform - David Delabassee
 
In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript AppsIn Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
In Pursuit of the Holy Grail: Building Isomorphic JavaScript Apps
 

Recently uploaded

Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 

Recently uploaded (20)

Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 

Refactoring JavaScript Applications

  • 1. codecentric d.o.o Jovan Vidić, IT Consultant @ codecentric Refactoring Java Script Applications
  • 2. Motivation Should We Refactor JavaScript? Refactoring Sample Application Beyond Refactoring Agenda
  • 3. ~ 6 years of development Java + DWR 732 JavaScript files ~ 20 000 lines of javascript code Motivation - Legacy project
  • 4. What was wrong? - JavaScript in HTML - Global functions - Inline styles - No coding style guidelines - No tests MOTIVATION - Legacy project
  • 5. What was OK? - OOP - Throwing own errors - Wrapping third party libraries - Prototype.js MOTIVATION - Legacy project
  • 6. Should We Refactor JavaScript ?
  • 7. “It is not necessary to change. Survival is not mandatory” W. Edwards Deming W E Deming
  • 9. What is Refactoring? a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior M. Fowler
  • 10. This is not refactoring
  • 11. agile manifesto 8th principle Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.
  • 12. Refactoring Sample Application – v1 – index.html </head>! <body>! <ul class="nav nav-pills">! <li class="active"><a href="../../v1/client/index.html">V1</a></ li>! <li><a href="../../v2/client/index.html">V2</a></li>! <li><a href="../../v3/client/index.html">V3</a></li>! <li><a href="../../v4/client/index.html">V4</a></li>! <li><a href="../../v5/client/index.html">V5</a></li>! </ul>! <div class="page-header">! <h1>Coding Serbia <small> Refactoring JavaScript Applications - V1</small></h1>! </div>! <!-- Button trigger modal -->! <button class="btn btn-primary btn-lg" data-toggle="modal" onclick="createSpeaker()">! Add Speaker! </button>!
  • 13. <script src="js/jquery.min.js"></script>! <script src="js/bootstrap.min.js"></script>! <script src="js/speakers.js"></script>! ! <script type="text/javascript">! load();! </script>! </body>! Refactoring Sample Application – v1 – index.html
  • 14. Refactoring Sample Application – v1 – speakers.js function add() {! var speakerId = $('#speakerId').val();! ! $.ajax({! type: speakerId == '' ? "POST" : "PUT",! url: speakerId == '' ? "http://localhost:4730/speakers" : "http:/! data: JSON.stringify({id: speakerId, firstName: $('#firstName').v! contentType: "application/json; charset=utf-8",! dataType: "json",! success: function(data){ $('#speakerId').val(''); $('#firstName’)! failure: function(errMsg) {alert(errMsg);}! ! function load() {! $.getJSON( "http://localhost:4730/speakers", function( data ) {! var newRows = "";! $.each(data, function(i,item) {! var sessionTime = new Date(Date.parse(item.sessionTime));! ! newRows += "<tr><td>" + sessionTime.toLocaleString() +"</td><! });! $(".table-striped tbody").html("");! $(".table-striped tbody").append(newRows);! });! };!
  • 15. Refactoring Sample Application – v1 It is a complete mess! How should I start?
  • 16. Refactoring Sample Application – v1 – selenium
  • 17. Refactoring Sample Application – v1 What about JSLint/JSHIT?
  • 18. It will scream at you!
  • 19. Refactoring Sample Application – v2 Invert dependencies
  • 20. Refactoring Sample Application – v2 - REQUIREJS requirejs.config({! paths: {! "jquery": "lib/jquery.min",! "bootstrap": "lib/bootstrap.min"! },! shim: {! "bootstrap": {! deps: ["jquery"]! }! }! });! ! require(["app/speakers","bootstrap"], function (speakers) {! ! $("#btnSaveSpeaker").click(function() {! speakers.save();! });! ! speakers.loadAll();! });! <script data-main="scripts/main" src="scripts/lib/require.js"></script>!
  • 21. Refactoring Sample Application – V2 – SPEAKERS.JS & THEME.jS define(["jquery","app/theme"], function ($, theme) {! "use strict";! ! var SpeakerControler = {! loadAll : function () {! $.getJSON("http://localhost:4730/speakers", function (data) {! var speakersTable = $("." + theme.SPEAKERS_TABLE +" tbody") define([], function () {! "use strict";! ! return {! DELETE_BUTTON : "btn btn-danger glyphicon glyphicon-remove",! EDIT_BUTTON : "btn btn-default glyphicon glyphicon-pencil",! SPEAKERS_TABLE : "table-striped"! };! });!
  • 22. Refactoring Sample Application – SPEAKERS.JS define(["jquery","app/theme"], function ($, theme) {! "use strict";! ! var SpeakerControler = {! loadAll : function () {! cell.append($("<button class='"+theme.DELETE_BUTTON+"'></button>”)! SpeakerControler.remove(item.id);! })); remove : function(id) {! $.ajax({! type: "DELETE",! url: "http://localhost:4730/speaker/" + id,! success: function() {! SpeakerControler.loadAll();! }! });! }! return SpeakerControler;! });
  • 23. My code is isolated now Can I write unit tests?
  • 24.
  • 25. Refactoring Sample Application – v3 Manage dependencies
  • 26. Refactoring Sample Application – v3 – bower.json {! "name": "javascript-refactoring",! "version": "1.0",! "authors": [! "Jovan Vidic <jovan.vidic@codecentric.de>"! ],! "private": true,! "ignore": [! "node_modules",! "bower_components",! "test",! "tests"! ],! "dependencies": {! "jquery": "1.11.1",! "bootstrap" : "3.2.0",! "requirejs" : "2.1.15"! },! ! "devDependencies": {! ! }! }!
  • 27. Refactoring Sample Application – v4 Improve design Introduce model objects & unit tests
  • 28. Refactoring Sample Application – v4 – MODEL.JS function Speaker(id, firstName, lastName, topic, sessionTime, track) {! this.id = id;! this.firstName = firstName;! this.lastName = lastName;! this.topic = topic;! this.sessionTime = sessionTime;! this.track = track;! ! this.hasId = function () {! return (this.id !== undefined) && (this.id !== null) ! && (this.id !== "");! };! ! this.getFullName = function () {! return this.firstName + " " + this.lastName;! };! }! ! return {! "Agenda" : {! "Speaker" : Speaker! }! };!
  • 29. Refactoring Sample Application – v4 – Speakers.JS define(["jquery", "app/model", "app/theme"], function ($, model, theme) {! "use strict";! var SpeakerControler = {! editSpeaker : function(id) {! $.getJSON( "http://localhost:4730/speaker/" + id, ! function(speakerData) {! if(speakerData) {! var speaker = convertToModel(speakerData);! showEditSpeakerPopup(speaker);! }! });! }! function showEditSpeakerPopup(speaker) {! $('#myModalLabel').html('Edit speaker <strong>' ! + speaker.getFullName() + "</strong>");! }! function convertToModel(speakerData) {! return new model.Agenda.Speaker(speakerData.id, speakerData.firstName, speakerData.lastName, speakerData.topic, speakerData.sessionTime, speakerData.track);! }
  • 30. Refactoring Sample Application – v4 – jasmine describe("Test model objects", function() {! "use strict";! ! var Model;! ! beforeEach(function(done) {! require(["app/model"], function (model) {! Model = model;! done();! });! }); it("should return Jovan Vidic when firstName is Jovan and lastName is Vidic", function() {! ! var speaker = new Model.Agenda.Speaker(1, "Jovan", "Vidic");! ! expect(speaker.getFullName()).toBe("Jovan Vidic");! });!
  • 31. Refactoring Sample Application – v4 That's all cool but my code still stinks?!
  • 32. Trust me I've been there
  • 33. Refactoring Sample Application – v5 Improve design & automate
  • 34. Refactoring Sample Application – v5 – SPEAKERS AJAX CLIENT define(["jquery", "app/model"], function ($, model) {! "use strict";! ! var baseURL = requirejs.s.contexts._.config.cs["api-url"],! speakersURL = baseURL + "speakers/",! speakerURL = baseURL + "speaker/";! ! function convertToModel(speakerData) {! return new model.Agenda.Speaker(speakerData.id, speakerData.firstNa }! return {! loadAllSpeakers : function (callbackHandle) {! $.getJSON(speakersURL, function (speakersData) {! var speakers = [];! $.each(speakersData, function (index, speakerData) {! var speaker = convertToModel(speakerData);! speakers.push(speaker);! });! callbackHandle.success(speakers);! });! },
  • 35. Refactoring Sample Application – v5 – Backend FACADE define(["app/client/speakers_ajax_client"], function (speakersClient) {! "use strict";! ! return {! loadAllSpeakers : function (callbackHandle) {! speakersClient.loadAllSpeakers(callbackHandle);! },! ! saveSpeaker : function (speaker, callbackHandle) {! speakersClient.saveSpeaker(speaker, callbackHandle);! }!
  • 36. Refactoring Sample Application – v5 - TesTS define(["squire"], function (Squire) {! "use strict";! ! var injector = new Squire(),! client = jasmine.createSpyObj("client", ["loadAllSpeakers", "saveSpeaker", "removeSpeaker"]),! callbackHandle = jasmine.createSpy("callback"),! builder = injector.mock("app/client/speakers_ajax_client”, client); ! describe("Test backend facade", function() {! ! var backend;! ! beforeEach(function(done) {! builder.require(["app/backend_facade"], function(backendFacade) backend = backendFacade;! done();! });! });! it("should loadAllSpeakers", function() {! backend.loadAllSpeakers(callbackHandle);! expect(client.loadAllSpeakers)! .toHaveBeenCalledWith(callbackHandle);! });! ! !
  • 37. Refactoring Sample Application – v5 - MVP http://warren.chinalle.com/2010/12/18/model-view-presenter/
  • 38. Refactoring Sample Application – v5 – speakers PRESENTER define(["app/backend_facade", "app/speakers/speakers_view", ! "app/events"], function (backend, SpeakersView, events) {! ! "use strict";! ! var EventManager = events.EventManager,! Actions = events.Actions;! ! function SpeakerPresenter() { ! var view = new SpeakersView(),! self;! ! return {! init : function () {! self = this;! EventManager.register(Actions.LOAD_ALL_SPEAKERS, this.loadAll);! },! loadAll : function () {! backend.loadAllSpeakers({! "success" : function (speakers) {! view.showAll(speakers);! }! });! },!
  • 39. Refactoring Sample Application – v5 – Speakers view define(["app/events", "app/components", "app/speakers/speakers_popup"], ! "use strict”;! var EventManager = events.EventManager;! ! function SpeakersView() {! var speakersTable = new components.SpeakersTable(),! createButton = new components.Button("btnAddSpeaker"),! popup = new SpeakersPopup();! ! function showCreateSpeakerDialog() {! EventManager.fire(events.Actions.SHOW_CREATE_SPEAKER);! }! function init() {! createButton.addClickListener(showCreateSpeakerDialog);! }! init();! return {! showAll : function (speakers) {! var i, len;! speakersTable.clear();! for (i = 0, len = speakers.length; i < len; i += 1) {! speakersTable.addSpeaker(speakers[i]);! }! }!
  • 40. Refactoring Sample Application – v5 – SPEAKERS POPUP define(["app/model", "app/events", "app/components"], function (model, even ! function SpeakersPopup() {! var speaker,! popup = new components.Popup("myModal"),! firstNameInput = new TextField("firstName"),! ! function saveSpeaker() {! speaker.firstName = firstNameInput.val();! speaker.lastName = lastNameInput.val();! speaker.topic = topicInput.val();! ! if (speaker.hasId()) {! EventManager.fire(events.Actions.EDIT_SPEAKER, speaker);! } else {! EventManager.fire(events.Actions.SAVE_SPEAKER, speaker);! }! }! return {! openAndSet : function (speakerToUpdate) {! speaker = speakerToUpdate;! firstNameInput.val(speaker.firstName);! lastNameInput.val(speaker.lastName);! !
  • 41. Refactoring Sample Application – v5 – components http://warren.chinalle.com/2010/12/18/model-view-presenter/ define(["jquery", "app/events", "app/theme"], function ($, events, theme) ! function TextField(id) {! var textField = $("#" + id);! return {! val : function (value) {! if (value !== undefined) {! textField.val(value);! } else {! return textField.val();! }! }! };! }! ! function SimpleButton(id) {! var button = $("#" + id);! return {! addClickListener : function (listener) {! button.click(listener);! }! };! }! !
  • 43. Refactoring Sample Application – v5 - GRUNT grunt.initConfig({! ! jslint: {! src: [! "scripts/**/*.js"! ],! ! },! ! karma: {! unit: {! configFile: "karma.conf.js"! }! },! ! copy: {! main: {! files: [! {expand: true, src: ["lib/bootstrap/dist/css/**"], dest: "dist/"},! {expand: true, src: ["lib/bootstrap/dist/fonts/**"], dest: "dist/"} {expand: true, src: ["lib/requirejs/require.js"], dest: "dist/"}! ]! }! }!
  • 44. Refactoring Sample Application – v5 - GRUNT requirejs: {! compile: {! options: {! baseUrl: "scripts/",! name: "main",! out: "dist/app-built.js”,! paths: {! app: "app/",! "jquery": "../lib/jquery/dist/jquery.min",! "bootstrap": "../lib/bootstrap/dist/js/bootstrap"! }! }! }! },! processhtml: {! options: {! data: { ! }! },! dist: {! files: {! "dist/index.html": ["index.html"]! }! }!
  • 46. Coffeescript define [], () ->! ! class Speaker! constructor: (@id, @firstName, @lastName, @topic, @sessionTime, @track) ->! ! hasId: ->! @id?.length != 0! ! fullName: ->! @firstName + " " + @lastName! ! return {"Agenda": {"Speaker" : Speaker}} !
  • 48.