SlideShare a Scribd company logo
1 of 208
Download to read offline
TALK
Zombie Code
Zombie Code
how to survive a Javascript
Zombiecodeapocalypse
First things first
my name is
@cedmax
I work for Shazam
I organize
conferences with
From The Front
DISCLAIMER
DISCLAIMER
I’m strongly opinionated
DISCLAIMER
I’m strongly opinionated
it’s a gift and a curse
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/
How to identify
Zombie CODE?
What I can tell is..
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/
What's that smell?
Zombies smell worse than
anything you can imagine
Lilith Saintcrow, Strange Angels
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;
}
// 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;
}
});
// 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 = $("<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
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;
}
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;
}
// 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;
}
});
// 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 = $("<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
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;
}
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;
}
// 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;
}
});
// 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 = $("<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
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;
}
are comments a bad thing?
TIp #2
Code should talk to you
_$ = (function(_) {
return {
pub: function(a, b, c, d) {
for (d=-1, c=[].concat(_[a]); c[++d];) c[d](b)
},
sub: function(a, b) {
(_[a] || (_[a] = [])).push(b)
}
}
})({})
_$ = (function(_) {
return {
pub: function(a, b, c, d) {
for (d=-1, c=[].concat(_[a]); c[++d];) c[d](b)
},
sub: function(a, b) {
(_[a] || (_[a] = [])).push(b)
}
}
})({})
#140bytes
_$ = (function() {
var registered = {};
return {
pub: function(event, memo) {
if (registered[event] instanceof Array){
var handlers = [].concat(registered[event]);
for (var i=0, handler; (handler = handlers[i]); i++){
handler.call(this, memo);
}
}
},
sub: function(event, handler) {
if (typeof registered[event] === "undefined"){
registered[event] = [];
}
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: 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
}
//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
//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 explanationAUTOMATED DOC
GENERATION
//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 explanationAUTOMATED DOC
GENERATION
TODOs
TIp #3
Code should have boundaries
Single
responsibility
principle
your best tool
against Zombie Code
since1902
(guaranteed 20 years)
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
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.”
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
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!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
function Zombie(personName)
{
function do_something() {
console.log(personName + " just ate a brain!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
function Zombie(personName)
{
function do_something() {
console.log(personName + " just ate a brain!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
function Zombie(personName)
{
function do_something() {
console.log(personName + " just ate a brain!");
}
return {
doSomethingZombiesDo: do_something
};
}
var adam = new Zombie("Adam");
adam.doSomethingZombiesDo();
define style guidelines
start linting your code
Inversion of control freakness
AM I A CONTROL FREAK?
start testing your code
Unit or Functional?
Do both
What to test
Unit testing is
supposed to test a
single atomic “unit” of
functionality without
dependencies on
anything else
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 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
No matter which toolset
Grunt
PhantomJS
JsTestDriver
Buster.js
Karma
Chutzpah
Testem
Qunit
Mocha
Jasmine
No matter which toolset
Grunt
PhantomJS
JsTestDriver
Buster.js
Karma
Chutzpah
Testem
Qunit
Mocha
Jasmine
As long as it can be automated
share
identify
build
make it
continuous
Make it part of the processMake 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 team
juniors
externallobbyist
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
Lobbyists
Lobbyists
They will slow you
down, your brain will be
more prone to be eaten
Lobbyists
They 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
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(){
var user = sandbox.getUser();
},
destroy:function(){
}
};
});
core.register("module-name", function(sandbox){
return {
init:function(){
var user = 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
icon by http://www.deleket.com/
jQuery
Mustache
Libraries Plugins Your scripts
icon by http://www.deleket.com/
jQuery
Mustache
Libraries Plugins Your scripts
<script src="jquery.min.js"></script>
<script src="mustache.js"></script>
<?php if ($env == "prod") : ?>
<script src="my-code-bundle.js"></script>
<?php else: ?>
<script src="jquery.plugin_1.js"></script>
<script src="jquery.plugin_2.js"></script>
<script src="my-code_1.js"></script>
<script src="my-code_2.js"></script>
<script src="my-code_3.js"></script>
<script src="my-code_4.js"></script>
<script src="my-code_5.js"></script>
<?php endif; ?>
var MyNamespace = {};
MyNamespace.MyAwesomeLibrary = function() {
//implementation
};
MyNamespace.AnotherCoolOne = function() {
//implementation
};
MyNamespace.SlightlyCrappyLibrary = function() {
//implementation
};
MyNamespace.BestLibEver = function() {
//implementation
};
//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({
url: "http://whatever.it/is/",
debug: true
});
//app/config.js
define([], function() {
return {
url: "http://whatever.it/is/",
debug: true
};
});
//app/config.js
define({
url: "http://whatever.it/is/",
debug: true
});
//app/config.js
define([], function() {
return {
url: "http://whatever.it/is/",
debug: true
};
});
//app/config.js
define({
url: "http://whatever.it/is/",
debug: true
});
//app/myProduct.js
define(["app/config"], function(config) {
return function(id){
return {
getProductUrl: function(){
var prodPath = 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(){
var prodPath = 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(){
var prodPath = 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(){
var prodPath = 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(){
var prodPath = 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(){
var prodPath = 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(){
var prodPath = 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(){
var prodPath = 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(){
var prodPath = config.url + "product/" + id;
if (config.debug){
console.log(prodPath)
}
return prodPath;
}
};
};
});
<script data-main="app/main" src="require.js"></script>
<script data-main="app/main" src="require.js"></script>
//app/main.js
require(["jQuery", "app/myProduct"], function($, Product) {
$(".product").on("click", function(){
var prodID = $(this).data("id");
var prod = new Product(prodID);
document.location.href = prod.getProductUrl();
})
});
<script data-main="app/main" src="require.js"></script>
//app/main.js
require(["jQuery", "app/myProduct"], function($, Product) {
$(".product").on("click", function(){
var prodID = $(this).data("id");
var prod = new Product(prodID);
document.location.href = prod.getProductUrl();
})
});
<script data-main="app/main" src="require.js"></script>
//app/main.js
require(["jQuery", "app/myProduct"], function($, Product) {
$(".product").on("click", function(){
var prodID = $(this).data("id");
var prod = new Product(prodID);
document.location.href = prod.getProductUrl();
})
});
<script data-main="app/main" src="require.js"></script>
//app/main.js
require(["jQuery", "app/myProduct"], function($, Product) {
$(".product").on("click", function(){
var prodID = $(this).data("id");
var prod = new Product(prodID);
document.location.href = prod.getProductUrl();
})
});
<script data-main="app/main" src="require.js"></script>
//app/main.js
require(["jQuery", "app/myProduct"], function($, Product) {
$(".product").on("click", function(){
var prodID = $(this).data("id");
var prod = new Product(prodID);
document.location.href = 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
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.”
OrsonWells
Happy ending
You can run, you can hide
You are going to
SHITTY code
anyway
write
face
You are going to
SHITTY code
anyway
face
You are going to
Zombie code
anyway
Embrace it!
http://drezner.foreignpolicy.com/posts/2009/08/18/theory_of_international_politics_and_zombies
Don’t improvise
Learn to know 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?

More Related Content

Recently uploaded

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 

Recently uploaded (20)

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Zombie Code