it’s not dead code
http://alfasin.com/i-see-dead-code-homage-for-intellij-idea/
Slide 13
Slide 13 text
How to identify
Zombie CODE?
Slide 14
Slide 14 text
What I can tell is..
Slide 15
Slide 15 text
It may seems harmless
http://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/
Slide 16
Slide 16 text
http://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/
but it’s NOT
Slide 17
Slide 17 text
and it will, eventually
http://imgur.com/r/SRDBroke/JimqK
CODE
Slide 18
Slide 18 text
during estimation
Slide 19
Slide 19 text
during debugging
Slide 20
Slide 20 text
during development
Slide 21
Slide 21 text
It is dumb code
that makes you dumb as well
Slide 22
Slide 22 text
Hopefully it’s not too late
http://tacticaltshirts.com/shop/shirt-zombies-eat-brains/
Slide 23
Slide 23 text
What's that smell?
Zombies smell worse than
anything you can imagine
Lilith Saintcrow, Strange Angels
Slide 24
Slide 24 text
TIp #1
Code should be appealing
Slide 25
Slide 25 text
function validate( options ) {
// if nothing is selected, return nothing; can't chain anyway
if ( !this.length ) {
if ( options && options.debug && window.console ) {
console.warn( "Nothing selected, can't validate, returning nothing." );
}
return;
}
// check if a validator for this form was already created
var validator = $.data( this[0], "validator" );
if ( validator ) {
return validator;
}
// Add novalidate tag if HTML5.
this.attr( "novalidate", "novalidate" );
validator = new $.validator( options, this[0] );
$.data( this[0], "validator", validator );
if ( validator.settings.onsubmit ) {
this.validateDelegate( ":submit", "click", function( event ) {
if ( validator.settings.submitHandler ) {
validator.submitButton = event.target;
}
Slide 26
Slide 26 text
// allow suppressing validation by adding a cancel class to the
submit button
if ( $(event.target).hasClass("cancel") ) {
validator.cancelSubmit = true;
}
// allow suppressing validation by adding the html5 formnovalidate
attribute to the submit button
if ( $(event.target).attr("formnovalidate") !== undefined ) {
validator.cancelSubmit = true;
}
});
// validate the form on submit
this.submit( function( event ) {
if ( validator.settings.debug ) {
// prevent form submit to be able to see console output
event.preventDefault();
}
function handle() {
var hidden;
if ( validator.settings.submitHandler ) {
if ( validator.submitButton ) {
// insert a hidden input as a replacement for the missing
submit button
hidden = $("").attr("name",
validator.submitButton.name).val( $
(validator.submitButton).val() ).appendTo(validator.currentForm);
}
Slide 27
Slide 27 text
validator.settings.submitHandler.call( validator,
validator.currentForm, event );
if ( validator.submitButton ) {
// and clean up afterwards; thanks to no-block-scope, hidden
can be referenced
hidden.remove();
}
return false;
}
return true;
}
// prevent submit for invalid forms or custom submit handlers
if ( validator.cancelSubmit ) {
validator.cancelSubmit = false;
return handle();
}
if ( validator.form() ) {
if ( validator.pendingRequest ) {
validator.formSubmitted = true;
return false;
}
return handle();
} else {
validator.focusInvalid();
return false;
}
});
}
return validator;
}
Slide 28
Slide 28 text
HOW LONG IS THAT?
Slide 29
Slide 29 text
function validate( options ) {
// if nothing is selected, return nothing; can't chain anyway
if ( !this.length ) {
if ( options && options.debug && window.console ) {
console.warn( "Nothing selected, can't validate, returning nothing." );
}
return;
}
// check if a validator for this form was already created
var validator = $.data( this[0], "validator" );
if ( validator ) {
return validator;
}
// Add novalidate tag if HTML5.
this.attr( "novalidate", "novalidate" );
validator = new $.validator( options, this[0] );
$.data( this[0], "validator", validator );
if ( validator.settings.onsubmit ) {
this.validateDelegate( ":submit", "click", function( event ) {
if ( validator.settings.submitHandler ) {
validator.submitButton = event.target;
}
// allow suppressing validation by adding a cancel class to the submit button
if ( $(event.target).hasClass("cancel") ) {
validator.cancelSubmit = true;
}
// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $(event.target).attr("formnovalidate") !== undefined ) {
validator.cancelSubmit = true;
}
});
Slide 30
Slide 30 text
// validate the form on submit
this.submit( function( event ) {
if ( validator.settings.debug ) {
// prevent form submit to be able to see console output
event.preventDefault();
}
function handle() {
var hidden;
if ( validator.settings.submitHandler ) {
if ( validator.submitButton ) {
// insert a hidden input as a replacement for the missing submit button
hidden = $("").attr("name", validator.submitButton.name).val( $
(validator.submitButton).val() ).appendTo(validator.currentForm);
}
validator.settings.submitHandler.call( validator, validator.currentForm, event );
if ( validator.submitButton ) {
// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
hidden.remove();
}
return false;
}
return true;
}
// prevent submit for invalid forms or custom submit handlers
if ( validator.cancelSubmit ) {
validator.cancelSubmit = false;
return handle();
}
if ( validator.form() ) {
if ( validator.pendingRequest ) {
validator.formSubmitted = true;
return false;
}
return handle();
} else {
validator.focusInvalid();
return false;
}
});
}
return validator;
}
Slide 31
Slide 31 text
14 (FOURTEEN!) ifs
Slide 32
Slide 32 text
function validate( options ) {
// if nothing is selected, return nothing; can't chain anyway
if ( !this.length ) {
if ( options && options.debug && window.console ) {
console.warn( "Nothing selected, can't validate, returning nothing." );
}
return;
}
// check if a validator for this form was already created
var validator = $.data( this[0], "validator" );
if ( validator ) {
return validator;
}
// Add novalidate tag if HTML5.
this.attr( "novalidate", "novalidate" );
validator = new $.validator( options, this[0] );
$.data( this[0], "validator", validator );
if ( validator.settings.onsubmit ) {
this.validateDelegate( ":submit", "click", function( event ) {
if ( validator.settings.submitHandler ) {
validator.submitButton = event.target;
}
// allow suppressing validation by adding a cancel class to the submit button
if ( $(event.target).hasClass("cancel") ) {
validator.cancelSubmit = true;
}
// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $(event.target).attr("formnovalidate") !== undefined ) {
validator.cancelSubmit = true;
}
});
Slide 33
Slide 33 text
// validate the form on submit
this.submit( function( event ) {
if ( validator.settings.debug ) {
// prevent form submit to be able to see console output
event.preventDefault();
}
function handle() {
var hidden;
if ( validator.settings.submitHandler ) {
if ( validator.submitButton ) {
// insert a hidden input as a replacement for the missing submit button
hidden = $("").attr("name", validator.submitButton.name).val( $
(validator.submitButton).val() ).appendTo(validator.currentForm);
}
validator.settings.submitHandler.call( validator, validator.currentForm, event );
if ( validator.submitButton ) {
// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
hidden.remove();
}
return false;
}
return true;
}
// prevent submit for invalid forms or custom submit handlers
if ( validator.cancelSubmit ) {
validator.cancelSubmit = false;
return handle();
}
if ( validator.form() ) {
if ( validator.pendingRequest ) {
validator.formSubmitted = true;
return false;
}
return handle();
} else {
validator.focusInvalid();
return false;
}
});
}
return validator;
}
//used translate3d to trigger hardware acceleration in webViews
//http://www.youtube.com/watch?v=IKl78ZgJzm4
.animated {
translate: translate3d(0,0,0)
}
/**
* Returns a unique ID for use in HTML id attribute.
* @param {String/Number} nr A name or number of the ID.
* @param {String} [prefix="id-"] The prefix for the ID.
* @return {String} the new ID
*/
function createId(nr, prefix){
//TODO implementation
}
Slide 41
Slide 41 text
//used translate3d to trigger hardware acceleration in webViews
//http://www.youtube.com/watch?v=IKl78ZgJzm4
.animated {
translate: translate3d(0,0,0)
}
/**
* Returns a unique ID for use in HTML id attribute.
* @param {String/Number} nr A name or number of the ID.
* @param {String} [prefix="id-"] The prefix for the ID.
* @return {String} the new ID
*/
function createId(nr, prefix){
//TODO implementation
}
un-avoidable
hacks explanation
Slide 42
Slide 42 text
//used translate3d to trigger hardware acceleration in webViews
//http://www.youtube.com/watch?v=IKl78ZgJzm4
.animated {
translate: translate3d(0,0,0)
}
/**
* Returns a unique ID for use in HTML id attribute.
* @param {String/Number} nr A name or number of the ID.
* @param {String} [prefix="id-"] The prefix for the ID.
* @return {String} the new ID
*/
function createId(nr, prefix){
//TODO implementation
}
un-avoidable
hacks explanation
AUTOMATED DOC
GENERATION
Slide 43
Slide 43 text
//used translate3d to trigger hardware acceleration in webViews
//http://www.youtube.com/watch?v=IKl78ZgJzm4
.animated {
translate: translate3d(0,0,0)
}
/**
* Returns a unique ID for use in HTML id attribute.
* @param {String/Number} nr A name or number of the ID.
* @param {String} [prefix="id-"] The prefix for the ID.
* @return {String} the new ID
*/
function createId(nr, prefix){
//TODO implementation
}
un-avoidable
hacks explanation
AUTOMATED DOC
GENERATION
TODOs
Slide 44
Slide 44 text
TIp #3
Code should have boundaries
Slide 45
Slide 45 text
Single
responsibility
principle
your best tool
against Zombie Code
since1902
(guaranteed 20 years)
Slide 46
Slide 46 text
No global
pollution
http://leosabanganii.blogspot.co.uk/2012/10/zombie-dressed-activists-protest.html
Slide 47
Slide 47 text
No coupling
http://leosabanganii.blogspot.co.uk/2012/10/zombie-dressed-activists-protest.html
http://ajandcharli.blogspot.co.uk/2011/05/we-dont-do-dead-people.html
Slide 48
Slide 48 text
worst case smell
Slide 49
Slide 49 text
worst case smell
Long methods
Slide 50
Slide 50 text
worst case smell
Long methods
Deep Level of Indentation
Slide 51
Slide 51 text
worst case smell
Long methods
Deep Level of Indentation
Hard to tell what it does
Slide 52
Slide 52 text
worst case smell
Long methods
Deep Level of Indentation
Hard to tell what it does
Lack of portability
Slide 53
Slide 53 text
worst case smell
Long methods
Deep Level of Indentation
Hard to tell what it does
Lack of portability
Hardcoded style/templating
Slide 54
Slide 54 text
worst case smell
Long methods
Deep Level of Indentation
Hard to tell what it does
Lack of portability
Hardcoded style/templating
Logic block duplication
Slide 55
Slide 55 text
worst case smell
Long methods
Deep Level of Indentation
Hard to tell what it does
Lack of portability
Hardcoded style/templating
Logic block duplication
Callback hell
Slide 56
Slide 56 text
And now what?
Slide 57
Slide 57 text
Play cool!
Slide 58
Slide 58 text
Basically
Quarantine
Slide 59
Slide 59 text
Basically
Quarantine
Slide 60
Slide 60 text
QUARANTINE
Most teams are trying to stop further
spread only through quarantines. It's a good
short-term solution, but it won't prevent
long-term population loss.
http://cdmx.it/quarantinequote
Slide 61
Slide 61 text
The broken window
Slide 62
Slide 62 text
“Don't leave "broken windows" (bad
designs, wrong decisions, or poor code)
unrepaired. Fix each one as soon as it is
discovered.”
Programming is insanely detail oriented, and perhaps this is why:
if you're not on top of the details, the perception is that things
are out of control, and it's only a matter of time before your
project spins out of control. Maybe we should be sweating the
small stuff.
Jeff Atwood
http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html
The broken window
Slide 63
Slide 63 text
Maybe we should be sweating
the small stuff.
Jeff Atwood
http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html
The broken window
Slide 64
Slide 64 text
Isolate the Zombies
Slide 65
Slide 65 text
define style guidelines
Slide 66
Slide 66 text
function Zombie(personName)
{
function do_something() {
console.log(personName + " just ate a brain!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
Slide 67
Slide 67 text
function Zombie(personName)
{
function do_something() {
console.log(personName + " just ate a brain!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
Slide 68
Slide 68 text
function Zombie(personName)
{
function do_something() {
console.log(personName + " just ate a brain!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
Slide 69
Slide 69 text
function Zombie(personName)
{
function do_something() {
console.log(personName + " just ate a brain!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
Slide 70
Slide 70 text
define style guidelines
Slide 71
Slide 71 text
start linting your code
Slide 72
Slide 72 text
Inversion of control freakness
AM I A CONTROL FREAK?
Slide 73
Slide 73 text
start testing your code
Slide 74
Slide 74 text
Unit or Functional?
Slide 75
Slide 75 text
Do both
Slide 76
Slide 76 text
What to test
Unit testing is
supposed to test a
single atomic “unit” of
functionality without
dependencies on
anything else
Slide 77
Slide 77 text
What to test
Unit testing is
supposed to test a
single atomic “unit” of
functionality without
dependencies on
anything else
This is where you start
to run into serious
dependency problems
due to the interrelation
HTML and CSS
Slide 78
Slide 78 text
What to test
Unit testing is
supposed to test a
single atomic “unit” of
functionality without
dependencies on
anything else
This is where you start
to run into serious
dependency problems
due to the interrelation
HTML and CSS
What do you test?
Usually how the user
interface responds to
user input.
Actually, the realm of
functional testing
Slide 79
Slide 79 text
No matter which toolset
Grunt
PhantomJS
JsTestDriver
Buster.js
Karma
Chutzpah
Testem
Qunit
Mocha
Jasmine
Slide 80
Slide 80 text
No matter which toolset
Grunt
PhantomJS
JsTestDriver
Buster.js
Karma
Chutzpah
Testem
Qunit
Mocha
Jasmine
Slide 81
Slide 81 text
As long as it can be automated
share
identify
build
make it
continuous
Slide 82
Slide 82 text
Make it part of the process
Make it part of the process
Slide 83
Slide 83 text
Make it part of the process
http://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/
Estimate testing
http://malyn.edublogs.org/2011/10/16/process-tools-people/
Slide 84
Slide 84 text
Make it part of the process
Do code review
http://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/
http://malyn.edublogs.org/2011/10/16/process-tools-people/
Slide 85
Slide 85 text
Make it part of the process
http://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/
Involve people
http://malyn.edublogs.org/2011/10/16/process-tools-people/
Slide 86
Slide 86 text
Fear the living? DON’T
Slide 87
Slide 87 text
The team
Slide 88
Slide 88 text
DEVOPS PRODUCT OWNER
qa
Slide 89
Slide 89 text
QA
Slide 90
Slide 90 text
QA
Crucial role in the
process
Slide 91
Slide 91 text
QA
Crucial role in the
process
Quality should be your
goal too
Slide 92
Slide 92 text
QA
Crucial role in the
process
Quality should be your
goal too
Get help for functional
test coverage not to
screw up refactoring
Slide 93
Slide 93 text
Devops
Slide 94
Slide 94 text
Devops
The tough guy
Slide 95
Slide 95 text
Devops
The tough guy
It could be hard to deal
with
Slide 96
Slide 96 text
Devops
The tough guy
It could be hard to deal
with
Get help setting up the
automated process
Slide 97
Slide 97 text
Product owner
Slide 98
Slide 98 text
Product owner
The less interested in
code itself
Slide 99
Slide 99 text
Product owner
The less interested in
code itself
Bring numbers, not
theories
Slide 100
Slide 100 text
Product owner
The less interested in
code itself
Bring numbers, not
theories
Get help not wasting
time, staying focused on
functionalities
Slide 101
Slide 101 text
Others in the team
Slide 102
Slide 102 text
juniors
external
lobbyist
Slide 103
Slide 103 text
Juniors
Slide 104
Slide 104 text
Juniors
Pair with them, code
review their (and your)
code
Slide 105
Slide 105 text
Juniors
Pair with them, code
review their (and your)
code
Involve them during the
whole process definition
Slide 106
Slide 106 text
Juniors
Pair with them, code
review their (and your)
code
Involve them during the
whole process definition
Get help keeping things
easy and accessible
Slide 107
Slide 107 text
Lobbyists
Slide 108
Slide 108 text
Lobbyists
They will slow you
down, your brain will be
more prone to be eaten
Slide 109
Slide 109 text
Lobbyists
They will slow you
down, your brain will be
more prone to be eaten
Redirect them to the
product owner
Slide 110
Slide 110 text
Basically
KILL ‘EM ALL (AGAIN?)
Slide 111
Slide 111 text
Basically
KILL ‘EM ALL (AGAIN?)
Slide 112
Slide 112 text
KILL ‘EM ALL (AGAIN?)
“Nothing is impossible to kill.”
Mira Grant, Feed
Slide 113
Slide 113 text
but
Slide 114
Slide 114 text
“Without requirements or design,
programming is the art of adding bugs
to an empty text file”
Louis Srygley
Design for your goal
Slide 115
Slide 115 text
Design for your goal
Slide 116
Slide 116 text
Modular Architecture
Slide 117
Slide 117 text
No content
Slide 118
Slide 118 text
Scalable JavaScript
Application
Architecture
by Nicholas Zakas
“The key is to acknowledge from the
start that you have no idea how this will
grow. When you accept that you don’t
know everything, you begin to design
the system defensively.”
Nicholas Zakas
Overengineering?
Slide 155
Slide 155 text
AMD
Slide 156
Slide 156 text
icon by http://www.deleket.com/
jQuery
Mustache
Libraries Plugins Your scripts
Slide 157
Slide 157 text
icon by http://www.deleket.com/
jQuery
Mustache
Libraries Plugins Your scripts
//API: define(id?, dependencies?, factory);
define("My-Module", ["Another-Module"], function(AnotherModule){
// Do Something
});
one define to rule them all
Slide 161
Slide 161 text
//API: define(id?, dependencies?, factory);
define("My-Module", ["Another-Module"], function(AnotherModule){
// Do Something
});
one define to rule them all