SlideShare une entreprise Scribd logo
1  sur  208
Télécharger pour lire hors ligne
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?

Contenu connexe

Dernier

DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
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
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
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
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 

Dernier (20)

DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
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
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 

En vedette

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
 

En vedette (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