A presentation at Front-Trends 2015 in in Warsaw, Poland by Marco Cedaro
TA L K
Zombie Code
Zombie Code how to survive a Javascript Zombiecodeapocalypse
First things first my name is @cedmax
cedmax @ Shazam
cedmax @ Shazam Flav Umar Luca Beer ced
Basically Zombies?
Basically Zombies?
Zombies! “Brains, BRAINS, BRains, brains, BRAINS. BRaiNS, brains, Brains, BRAINS, BRains, brains, BRAINS. BRAINS, BRains, brains, BRAINS, brains.” Ryan Mecum
ZOMBIE CODE?
it’s not dead code http://alfasin.com/i-see-dead-code-homage-for-intellij-idea/
It may seems harmless http://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/
http://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/ but it’s NOT
and it will, eventually http://imgur.com/r/SRDBroke/JimqK CODE
during estimation
during debugging
during development
It is dumb code that makes you dumb as well
Hopefully it’s not too late http://tacticaltshirts.com/shop/shirt-zombies-eat-brains/
How to identify Zombie CODE ?
What's that smell? Zombies smell worse than anything you can imagine Lilith Saintcrow, Strange Angels
3 tips
TIp #1 Code should be appealing
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 ; }
$ . data ( this [ 0 ], "validator" );
if ( validator ) {
return validator; }
// Add novalidate tag if HTML5.
new
$ .validator( options, this [ 0 ] );
$ . data ( this [ 0 ], "validator" , validator );
if ( validator.settings.onsubmit ) {
this .validateDelegate( ":submit" , "click" , function( event ) {
event . target ; }
// allow suppressing validation by adding a cancel class to the submit button
true ; }
// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $ ( event . target ).attr( "formnovalidate" ) !==
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 ) {
$ ( "<input type='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
false ;
return handle(); }
if ( validator. form () ) {
true ;
return
false ; }
return handle(); } else { validator.focusInvalid();
return
false ; } }); }
return validator; }
HOW LONG IS THAT?
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 ; }
$ . data ( this [ 0 ], "validator" );
if ( validator ) {
return validator; }
// Add novalidate tag if HTML5.
new
$ .validator( options, this [ 0 ] );
$ . data ( this [ 0 ], "validator" , validator );
if ( validator.settings.onsubmit ) {
this .validateDelegate( ":submit" , "click" , function( event ) {
event . target ; }
// allow suppressing validation by adding a cancel class to the submit button
true ; }
// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $ ( event . target ).attr( "formnovalidate" ) !==
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 ) {
$ ( "<input type='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
false ;
return handle(); }
if ( validator. form () ) {
true ;
return
false ; }
return handle(); } else { validator.focusInvalid();
return
false ; } }); }
return validator; }
14 (FOURTEEN!) ifs
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 ; }
$ . data ( this [ 0 ], "validator" );
if ( validator ) {
return validator; }
// Add novalidate tag if HTML5.
new
$ .validator( options, this [ 0 ] );
$ . data ( this [ 0 ], "validator" , validator );
if ( validator.settings.onsubmit ) {
this .validateDelegate( ":submit" , "click" , function( event ) {
event . target ; }
// allow suppressing validation by adding a cancel class to the submit button
true ; }
// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
if ( $ ( event . target ).attr( "formnovalidate" ) !==
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 ) {
$ ( "<input type='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
false ;
return handle(); }
if ( validator. form () ) {
true ;
return
false ; }
return handle(); } else { validator.focusInvalid();
return
false ; } }); }
return validator; }
are comments a bad thing?
TIp #2 Code should talk to you
_ $
= ( function (_) {
return {
pub : function (a, b, c, d) {
[].concat(_[a]); c[ ++ d];) cd },
[])).push(b) } } })({})
_ $
= ( function (_) {
return {
pub : function (a, b, c, d) {
[].concat(_[a]); c[ ++ d];) cd },
[])).push(b) } } })({}) #140bytes
_ $
= ( function () {
{};
return {
pub : function (event, memo) {
if (registered[event] instanceof Array){
[].concat(registered[event]);
handlers[i]); i ++ ){ handler.call(this, memo); } } },
sub : function (event, handler) {
[]; } registered[event].push(handler); } }; })();
don’t use comments as an excuse to write bad code
//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 0 , 0 , 0 ) } /**
createId (nr, prefix){
//TODO implementation }
//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 0 , 0 , 0 ) } /**
createId (nr, prefix){
//TODO implementation } un-avoidable hacks explanation
//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 0 , 0 , 0 ) } /**
createId (nr, prefix){
//TODO implementation } un-avoidable hacks explanation AUTOMATED DOC GENERATION
//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 0 , 0 , 0 ) } /**
createId (nr, prefix){
//TODO implementation } un-avoidable hacks explanation AUTOMATED DOC GENERATION TODOs
TIp #3 Code should have personal boundaries
Define boundaries
Single responsibility principle your best tool against Zombie Code
No global pollution http://leosabanganii.blogspot.co.uk/2012/10/zombie-dressed-activists-protest.html
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
code-sense is the key Writing clean code requires the disciplined use of a myriad little techniques applied through a painstakingly acquired sense of "cleanliness". Robert C. Martin
worst case smell
worst case smell Long methods
worst case smell Long methods Deep Level of Indentation
worst case smell Long methods Deep Level of Indentation Hard to tell what it does
worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability
worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability Hardcoded style/templating
worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability Hardcoded style/templating Logic block duplication
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
And now what?
Play cool!
Basically Quarantine
Basically Quarantine
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
The broken window
“Don't leave "broken windows" (bad designs, wrong decisions, or poor code) unrepaired. Fix each one as soon as it is discovered.” Jeff Atwood http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html The broken window
“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.” Jeff Atwood http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html The broken window
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
Isolate the
Zombies
define style guidelines
function
Zombie (personName) {
function
do_something () { console.log(personName +
" just ate a brain!" ); }
new Zombie( "Adam" ); adam.doSomethingZombiesDo();
function
Zombie (personName) {
function
do_something () { console.log(personName +
" just ate a brain!" ); }
new Zombie( "Adam" ); adam.doSomethingZombiesDo();
function
Zombie (personName) {
function
do_something () { console.log(personName +
" just ate a brain!" ); }
new Zombie( "Adam" ); adam.doSomethingZombiesDo();
function
Zombie (personName) {
function
do_something () { console.log(personName +
" just ate a brain!" ); }
new Zombie( "Adam" ); adam.doSomethingZombiesDo();
start linting your code
Inversion of control freakness AM I A CONTROL FREAK?
start testing your code
Unit or Functional?
Do both
As long as it can be automated share identify build make it
continuous
Make it part of the process Make it part of the process
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/
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/
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/
Fear the living? DON’T
The team
DEVOPS PRODUCT OWNER qa
QA
QA Crucial role in the process
QA Crucial role in the process Quality should be your goal too
QA Crucial role in the process Quality should be your goal too Get help for functional test coverage not to screw up refactoring
Devops
Devops The tough guy
Devops The tough guy It could be hard to deal with
Devops The tough guy It could be hard to deal with Get help setting up the automated process
Product owner
Product owner The less interested in code itself
Product owner The less interested in code itself Bring numbers, not theories
Product owner The less interested in code itself Bring numbers, not theories Get help not wasting time, staying focused on functionalities
Others in the company
juniors external lobbyist
Juniors
Juniors Pair with them, code review their (and your) code
Juniors Pair with them, code review their (and your) code Involve them during the whole process definition
Juniors Pair with them, code review their (and your) code Involve them during the whole process definition Get help keeping things easy and accessible
Learn to say NO!
Learn to say NO! Lobbyists will slow you down, your brain will be more prone to be eaten
Learn to say NO! Lobbyists will slow you down, your brain will be more prone to be eaten Redirect them to the product owner
Basically KILL ‘EM ALL (AGAIN?)
Basically KILL ‘EM ALL (AGAIN?)
KILL ‘EM ALL (AGAIN?) “Nothing is impossible to kill.”
Mira Grant, Feed
but
“Without requirements or design, programming is the art of adding bugs to an empty text file” Louis Srygley Design for your goal
Design for your goal
ā k āś e
sanskrit for "in the sky"/"to the sky" https://github.com/cedmax/akase
Modular Architecture
Scalable JavaScript Application Architecture by Nicholas Zakas
core.register( "module-name" , function (sandbox){
return {
init : function (){
},
destroy : function (){
}
};
});
core.register( "module-name" , function (sandbox){
return {
init : function (){
},
destroy : function (){
}
};
});
core.register( "module-name" , function (sandbox){
return {
init : function (){
},
destroy : function (){
}
};
});
core.register( "module-name" , function (sandbox){
return {
init : function (){
sandbox.getUser(); },
destroy : function (){
}
};
});
core.register( "module-name" , function (sandbox){
return {
init : function (){
sandbox.getUser(); },
destroy : function (){
}
};
});
core.register( 'module-name' , function (sandbox){
return {
init : function (config){ console.log(config.id); } }; }); core.configure( 'module-name' , { id: 'container' , }); core.start( 'module-name' ); core.stop( 'module-name' );
core.register( 'module-name' , function (sandbox){
return {
init : function (config){ console.log(config.id); } }; }); core.configure( 'module-name' , { id: 'container' , }); core.start( 'module-name' ); core.stop( 'module-name' );
core.register( 'module-name' , function (sandbox){
return {
init : function (config){ console.log(config.id); } }; }); core.configure( 'module-name' , { id: 'container' , }); core.start( 'module-name' ); core.stop( 'module-name' );
core.register( 'module-name' , function (sandbox){
return {
init : function (config){ console.log(config.id); } }; }); core.configure( 'module-name' , { id: 'container' , }); core.start( 'module-name' ); core.stop( 'module-name' );
core.register( 'module-name' , function (sandbox){
return {
init : function (config){ console.log(config.id); } }; }); core.configure( 'module-name' , { id: 'container' , }); core.start( 'module-name' ); core.stop( 'module-name' );
core.register( 'module-name' , function (sandbox){
return {
init : function (config){ console.log(config.id); } }; }); core.configure( 'module-name' , { id: 'container' , }); core.start( 'module-name' ); core.stop( 'module-name' );
Event Driven Pattern
core.register( "module-name" , function (sandbox){
return {
init : function (){ sandbox.layer( "an error occured" ); } }; });
core.register( "module-name" , function (sandbox){
return {
init : function (){ sandbox.layer( "an error occured" ); } }; });
sandbox.layer( "an error occured" );
sandbox.publish( "error" , { msg: "an error occured" });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.publish( "error" , { msg: "an error occured" }); core.register( "errManager" , function(sandbox){
return {
init : function(){ sandbox.subscribe( "error" , function(err) {
console .log (err.msg) }); } }; });
sandbox.subscribe( "error" , function (payload){ console.log(payload.msg); }); Advantages
sandbox.subscribe( "error" , function (payload){ console.log(payload.msg); }); Advantages SEMANTIC
sandbox.subscribe( "error" , function (payload){ console.log(payload.msg); }); Advantages SEMANTIC flexibility
Advantages DECOUPLING
“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?
AMD
//API: define(id?, dependencies?, factory) ; define( "My-Module" , [ "Another-Module" ], function (AnotherModule){
// Do Something }); one define to rule them all
//API: define(id?, dependencies?, factory) ; define( "My-Module" , [ "Another-Module" ], function (AnotherModule){
// Do Something }); one define to rule them all
//app/config.js define([], function () {
return { url: "http://whatever.it/is/" , debug: true }; });
//app/config.js define([], function () {
return { url: "http://whatever.it/is/" , debug: true }; });
//app/config.js define([], function () {
return { url: "http://whatever.it/is/" , debug: true }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/myProduct.js define([ "app/config" ], function (config) {
return
function (id){
return {
getProductUrl : function (){
config.url +
"product/"
id;
if (config.debug){ console.log(prodPath) }
return prodPath; } }; }; });
//app/main.js require([ "jQuery" , "app/myProduct" ], function ( $ , Product) {
$ ( ".product" ).on( "click" , function (){
$ (this).data( "id" );
prod.getProductUrl(); }) });
//app/main.js require([ "jQuery" , "app/myProduct" ], function ( $ , Product) {
$ ( ".product" ).on( "click" , function (){
$ (this).data( "id" );
prod.getProductUrl(); }) });
//app/main.js require([ "jQuery" , "app/myProduct" ], function ( $ , Product) {
$ ( ".product" ).on( "click" , function (){
$ (this).data( "id" );
prod.getProductUrl(); }) });
//app/main.js require([ "jQuery" , "app/myProduct" ], function ( $ , Product) {
$ ( ".product" ).on( "click" , function (){
$ (this).data( "id" );
prod.getProductUrl(); }) });
//app/main.js require([ "jQuery" , "app/myProduct" ], function ( $ , Product) {
$ ( ".product" ).on( "click" , function (){
$ (this).data( "id" );
prod.getProductUrl(); }) });
Pulling all together
define( function (){
'use strict' ;
return
function (sandbox){
//the logic of the module
function
doSomething (){
//do something }
return {
init : function (config){
//the initialization code sandbox.subscribe( 'myEventName' , doSomething) },
destroy : function (){
//optional destroy method } }; }; });
define( function (){
'use strict' ;
return
function (sandbox){
//the logic of the module
function
doSomething (){
//do something }
return {
init : function (config){
//the initialization code sandbox.subscribe( 'myEventName' , doSomething) },
destroy : function (){
//optional destroy method } }; }; });
define( function (){
'use strict' ;
return
function (sandbox){
//the logic of the module
function
doSomething (){
//do something }
return {
init : function (config){
//the initialization code sandbox.subscribe( 'myEventName' , doSomething) },
destroy : function (){
//optional destroy method } }; }; });
define( function (){
'use strict' ;
return
function (sandbox){
//the logic of the module
function
doSomething (){
//do something }
return {
init : function (config){
//the initialization code sandbox.subscribe( 'myEventName' , doSomething) },
destroy : function (){
//optional destroy method } }; }; });
define( function (){
'use strict' ;
return
function (sandbox){
//the logic of the module
function
doSomething (){
//do something }
return {
init : function (config){
//the initialization code sandbox.subscribe( 'myEventName' , doSomething) },
destroy : function (){
//optional destroy method } }; }; });
require([ "akase" ], function (core) { core.start( "module1" ); core.start( "module2" , { config: { debug: true } }); core.start( "module3" , { event: "audio:stop" }); });
require([ "akase" ], function (core) { core.start( "module1" ); core.start( "module2" , { config: { debug: true } }); core.start( "module3" , { event: "audio:stop" }); });
require([ "akase" ], function (core) { core.start( "module1" ); core.start( "module2" , { config: { debug: true } }); core.start( "module3" , { event: "audio:stop" }); });
require([ "akase" ], function (core) { core.start( "module1" ); core.start( "module2" , { config: { debug: true } }); core.start( "module3" , { event: "audio:stop" }); });
require([ "akase" ], function (core) { core.start( "module1" ); core.start( "module2" , { config: { debug: true } }); core.start( "module3" , { event: "audio:stop" }); });
ā k āś e
sanskrit for "in the sky"/"to the sky" https://github.com/cedmax/akase
2 years later…
require = { baseUrl: '/assets/js/module' , shim: { 'magnificpopup' : { deps: [ 'jquery' ] }, 'timezone' : { exports: 'jstz' }, 'facebook' : { exports: 'FB' } }, paths: { 'templates' : '../../templates' , 'widget' : '../widget' , 'core' : '../core' , 'packages' : '../packages' , 'jquery' : 'js/vendor/jquery-2.0.0.min.js' , 'magnificpopup' : 'js/vendor/mpopup-0.9.2.min.js' , 'modernizr' : 'js/vendor/modernizr.min.js' , 'fastclick' : 'js/vendor/fastclick-1.0.2.min.js' , 'timezone' : 'js/vendor/timezone-1.0.4.min.js' , 'typeahead' : 'js/vendor/typeahead-0.9.3.min.js' }, waitSeconds:30 };
var $ = require( "jquery" ); // Do Something var myscript = require( "myscript" ); var anotherDep = require( "anotherDep" ); // Do Something else COMMON JS require([ "jquery" , "myscript" , "anotherDep" , ], function ($, myscript, anotherDep ){
// Do Something }); REQUIRE JS
import $ from
'jquery' ; import myscript from
'myscript' ; import anotherDep from
'anotherDep' ; // Do Something ES6
No such thing!
Basically Happy Endings?
Basically Happy Endings?
“If you want a happy ending, that depends, of course, on where you stop your story.” Orson Wells Happy ending
You can run, you can hide
You are going to
SHITTY code anyway write
You are going to write Zombie code anyway
Embrace it! http://drezner.foreignpolicy.com/posts/2009/08/18/theory_of_international_politics_and_zombies
Don’t improvise
Learn how to deal with it
Until you master it
in any case just remember to
Aim for the head http://halloween.squidoo.com/get-spooked/aim-for-the-head
marco@fromthefront.it http://cedmax.com @cedmax any question?
Have you ever had the need to figure out how to survive a Javascript Zombiecodepocalipse? Have you ever dreamt about loads of living legacy code and the urge to run away from it? Hundreds of lines of code tightly coupled and hardly understandable there were trying to catch you?
I’ve been there and I’m a survivor because I learned the art of refactoring. This talk is about how to deal with features request, deadlines and still increase the maintainability of your code.
Here’s what was said about this presentation on social media.
Wisdom on how to get rid of zombie code on stage by @cedmax #FrontTrends pic.twitter.com/giZgi8AP1o
— Bastian Albers (@bastianalbers) May 7, 2015
I will not look at the code in the same way... I fear the zombies! @cedmax #fronttrends
— Giacomo Zinetti 👾 (@gcmznt) May 7, 2015
without requirements and design, programming is an art of adding bugs into the empty text file. #fronttrends @cedmax
— Piotr Nalepa (@sunpietro) May 7, 2015