Slide 1

Slide 1 text

TALK

Slide 2

Slide 2 text

Zombie Code

Slide 3

Slide 3 text

Zombie Code how to survive a Javascript Zombiecodeapocalypse

Slide 4

Slide 4 text

First things first my name is @cedmax I work for Shazam I organize conferences with From The Front

Slide 5

Slide 5 text

DISCLAIMER

Slide 6

Slide 6 text

DISCLAIMER I’m strongly opinionated

Slide 7

Slide 7 text

DISCLAIMER I’m strongly opinionated it’s a gift and a curse

Slide 8

Slide 8 text

Basically Zombies?

Slide 9

Slide 9 text

Basically Zombies?

Slide 10

Slide 10 text

Zombies! “Brains, BRAINS, BRains, brains, BRAINS. BRaiNS, brains, Brains, BRAINS, BRains, brains, BRAINS. BRAINS, BRains, brains, BRAINS, brains.” Ryan Mecum

Slide 11

Slide 11 text

ZOMBIE CODE?

Slide 12

Slide 12 text

it’s not dead code http://alfasin.com/i-see-dead-code-homage-for-intellij-idea/

Slide 13

Slide 13 text

How to identify Zombie CODE?

Slide 14

Slide 14 text

What I can tell is..

Slide 15

Slide 15 text

It may seems harmless http://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/

Slide 16

Slide 16 text

http://couchpotatofiles.wordpress.com/2012/03/20/the-walking-dead-ups-the-death-count-and-the-ratings/ but it’s NOT

Slide 17

Slide 17 text

and it will, eventually http://imgur.com/r/SRDBroke/JimqK CODE

Slide 18

Slide 18 text

during estimation

Slide 19

Slide 19 text

during debugging

Slide 20

Slide 20 text

during development

Slide 21

Slide 21 text

It is dumb code that makes you dumb as well

Slide 22

Slide 22 text

Hopefully it’s not too late http://tacticaltshirts.com/shop/shirt-zombies-eat-brains/

Slide 23

Slide 23 text

What's that smell? Zombies smell worse than anything you can imagine Lilith Saintcrow, Strange Angels

Slide 24

Slide 24 text

TIp #1 Code should be appealing

Slide 25

Slide 25 text

function validate( options ) { // if nothing is selected, return nothing; can't chain anyway if ( !this.length ) { if ( options && options.debug && window.console ) { console.warn( "Nothing selected, can't validate, returning nothing." ); } return; } // check if a validator for this form was already created var validator = $.data( this[0], "validator" ); if ( validator ) { return validator; } // Add novalidate tag if HTML5. this.attr( "novalidate", "novalidate" ); validator = new $.validator( options, this[0] ); $.data( this[0], "validator", validator ); if ( validator.settings.onsubmit ) { this.validateDelegate( ":submit", "click", function( event ) { if ( validator.settings.submitHandler ) { validator.submitButton = event.target; }

Slide 26

Slide 26 text

// allow suppressing validation by adding a cancel class to the submit button if ( $(event.target).hasClass("cancel") ) { validator.cancelSubmit = true; } // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button if ( $(event.target).attr("formnovalidate") !== undefined ) { validator.cancelSubmit = true; } }); // validate the form on submit this.submit( function( event ) { if ( validator.settings.debug ) { // prevent form submit to be able to see console output event.preventDefault(); } function handle() { var hidden; if ( validator.settings.submitHandler ) { if ( validator.submitButton ) { // insert a hidden input as a replacement for the missing submit button hidden = $("").attr("name", validator.submitButton.name).val( $ (validator.submitButton).val() ).appendTo(validator.currentForm); }

Slide 27

Slide 27 text

validator.settings.submitHandler.call( validator, validator.currentForm, event ); if ( validator.submitButton ) { // and clean up afterwards; thanks to no-block-scope, hidden can be referenced hidden.remove(); } return false; } return true; } // prevent submit for invalid forms or custom submit handlers if ( validator.cancelSubmit ) { validator.cancelSubmit = false; return handle(); } if ( validator.form() ) { if ( validator.pendingRequest ) { validator.formSubmitted = true; return false; } return handle(); } else { validator.focusInvalid(); return false; } }); } return validator; }

Slide 28

Slide 28 text

HOW LONG IS THAT?

Slide 29

Slide 29 text

function validate( options ) { // if nothing is selected, return nothing; can't chain anyway if ( !this.length ) { if ( options && options.debug && window.console ) { console.warn( "Nothing selected, can't validate, returning nothing." ); } return; } // check if a validator for this form was already created var validator = $.data( this[0], "validator" ); if ( validator ) { return validator; } // Add novalidate tag if HTML5. this.attr( "novalidate", "novalidate" ); validator = new $.validator( options, this[0] ); $.data( this[0], "validator", validator ); if ( validator.settings.onsubmit ) { this.validateDelegate( ":submit", "click", function( event ) { if ( validator.settings.submitHandler ) { validator.submitButton = event.target; } // allow suppressing validation by adding a cancel class to the submit button if ( $(event.target).hasClass("cancel") ) { validator.cancelSubmit = true; } // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button if ( $(event.target).attr("formnovalidate") !== undefined ) { validator.cancelSubmit = true; } });

Slide 30

Slide 30 text

// validate the form on submit this.submit( function( event ) { if ( validator.settings.debug ) { // prevent form submit to be able to see console output event.preventDefault(); } function handle() { var hidden; if ( validator.settings.submitHandler ) { if ( validator.submitButton ) { // insert a hidden input as a replacement for the missing submit button hidden = $("").attr("name", validator.submitButton.name).val( $ (validator.submitButton).val() ).appendTo(validator.currentForm); } validator.settings.submitHandler.call( validator, validator.currentForm, event ); if ( validator.submitButton ) { // and clean up afterwards; thanks to no-block-scope, hidden can be referenced hidden.remove(); } return false; } return true; } // prevent submit for invalid forms or custom submit handlers if ( validator.cancelSubmit ) { validator.cancelSubmit = false; return handle(); } if ( validator.form() ) { if ( validator.pendingRequest ) { validator.formSubmitted = true; return false; } return handle(); } else { validator.focusInvalid(); return false; } }); } return validator; }

Slide 31

Slide 31 text

14 (FOURTEEN!) ifs

Slide 32

Slide 32 text

function validate( options ) { // if nothing is selected, return nothing; can't chain anyway if ( !this.length ) { if ( options && options.debug && window.console ) { console.warn( "Nothing selected, can't validate, returning nothing." ); } return; } // check if a validator for this form was already created var validator = $.data( this[0], "validator" ); if ( validator ) { return validator; } // Add novalidate tag if HTML5. this.attr( "novalidate", "novalidate" ); validator = new $.validator( options, this[0] ); $.data( this[0], "validator", validator ); if ( validator.settings.onsubmit ) { this.validateDelegate( ":submit", "click", function( event ) { if ( validator.settings.submitHandler ) { validator.submitButton = event.target; } // allow suppressing validation by adding a cancel class to the submit button if ( $(event.target).hasClass("cancel") ) { validator.cancelSubmit = true; } // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button if ( $(event.target).attr("formnovalidate") !== undefined ) { validator.cancelSubmit = true; } });

Slide 33

Slide 33 text

// validate the form on submit this.submit( function( event ) { if ( validator.settings.debug ) { // prevent form submit to be able to see console output event.preventDefault(); } function handle() { var hidden; if ( validator.settings.submitHandler ) { if ( validator.submitButton ) { // insert a hidden input as a replacement for the missing submit button hidden = $("").attr("name", validator.submitButton.name).val( $ (validator.submitButton).val() ).appendTo(validator.currentForm); } validator.settings.submitHandler.call( validator, validator.currentForm, event ); if ( validator.submitButton ) { // and clean up afterwards; thanks to no-block-scope, hidden can be referenced hidden.remove(); } return false; } return true; } // prevent submit for invalid forms or custom submit handlers if ( validator.cancelSubmit ) { validator.cancelSubmit = false; return handle(); } if ( validator.form() ) { if ( validator.pendingRequest ) { validator.formSubmitted = true; return false; } return handle(); } else { validator.focusInvalid(); return false; } }); } return validator; }

Slide 34

Slide 34 text

are comments a bad thing?

Slide 35

Slide 35 text

TIp #2 Code should talk to you

Slide 36

Slide 36 text

_$ = (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) } } })({})

Slide 37

Slide 37 text

_$ = (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

Slide 38

Slide 38 text

_$ = (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); } }; })();

Slide 39

Slide 39 text

don’t use comments as an excuse to write bad code

Slide 40

Slide 40 text

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate3d(0,0,0) } /** * Returns a unique ID for use in HTML id attribute. * @param {String/Number} nr A name or number of the ID. * @param {String} [prefix="id-"] The prefix for the ID. * @return {String} the new ID */ function createId(nr, prefix){ //TODO implementation }

Slide 41

Slide 41 text

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate3d(0,0,0) } /** * Returns a unique ID for use in HTML id attribute. * @param {String/Number} nr A name or number of the ID. * @param {String} [prefix="id-"] The prefix for the ID. * @return {String} the new ID */ function createId(nr, prefix){ //TODO implementation } un-avoidable hacks explanation

Slide 42

Slide 42 text

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate3d(0,0,0) } /** * Returns a unique ID for use in HTML id attribute. * @param {String/Number} nr A name or number of the ID. * @param {String} [prefix="id-"] The prefix for the ID. * @return {String} the new ID */ function createId(nr, prefix){ //TODO implementation } un-avoidable hacks explanation AUTOMATED DOC GENERATION

Slide 43

Slide 43 text

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate3d(0,0,0) } /** * Returns a unique ID for use in HTML id attribute. * @param {String/Number} nr A name or number of the ID. * @param {String} [prefix="id-"] The prefix for the ID. * @return {String} the new ID */ function createId(nr, prefix){ //TODO implementation } un-avoidable hacks explanation AUTOMATED DOC GENERATION TODOs

Slide 44

Slide 44 text

TIp #3 Code should have boundaries

Slide 45

Slide 45 text

Single responsibility principle your best tool against Zombie Code since1902 (guaranteed 20 years)

Slide 46

Slide 46 text

No global pollution http://leosabanganii.blogspot.co.uk/2012/10/zombie-dressed-activists-protest.html

Slide 47

Slide 47 text

No coupling http://leosabanganii.blogspot.co.uk/2012/10/zombie-dressed-activists-protest.html http://ajandcharli.blogspot.co.uk/2011/05/we-dont-do-dead-people.html

Slide 48

Slide 48 text

worst case smell

Slide 49

Slide 49 text

worst case smell Long methods

Slide 50

Slide 50 text

worst case smell Long methods Deep Level of Indentation

Slide 51

Slide 51 text

worst case smell Long methods Deep Level of Indentation Hard to tell what it does

Slide 52

Slide 52 text

worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability

Slide 53

Slide 53 text

worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability Hardcoded style/templating

Slide 54

Slide 54 text

worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability Hardcoded style/templating Logic block duplication

Slide 55

Slide 55 text

worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability Hardcoded style/templating Logic block duplication Callback hell

Slide 56

Slide 56 text

And now what?

Slide 57

Slide 57 text

Play cool!

Slide 58

Slide 58 text

Basically Quarantine

Slide 59

Slide 59 text

Basically Quarantine

Slide 60

Slide 60 text

QUARANTINE Most teams are trying to stop further spread only through quarantines. It's a good short-term solution, but it won't prevent long-term population loss. http://cdmx.it/quarantinequote

Slide 61

Slide 61 text

The broken window

Slide 62

Slide 62 text

“Don't leave "broken windows" (bad designs, wrong decisions, or poor code) unrepaired. Fix each one as soon as it is discovered.” Programming is insanely detail oriented, and perhaps this is why: if you're not on top of the details, the perception is that things are out of control, and it's only a matter of time before your project spins out of control. Maybe we should be sweating the small stuff. Jeff Atwood http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html The broken window

Slide 63

Slide 63 text

Maybe we should be sweating the small stuff. Jeff Atwood http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html The broken window

Slide 64

Slide 64 text

Isolate the Zombies

Slide 65

Slide 65 text

define style guidelines

Slide 66

Slide 66 text

function Zombie(personName) { function do_something() { console.log(personName + " just ate a brain!"); } return { doSomethingZombiesDo: do_something }; } var adam = new Zombie("Adam"); adam.doSomethingZombiesDo();

Slide 67

Slide 67 text

function Zombie(personName) { function do_something() { console.log(personName + " just ate a brain!"); } return { doSomethingZombiesDo: do_something }; } var adam = new Zombie("Adam"); adam.doSomethingZombiesDo();

Slide 68

Slide 68 text

function Zombie(personName) { function do_something() { console.log(personName + " just ate a brain!"); } return { doSomethingZombiesDo: do_something }; } var adam = new Zombie("Adam"); adam.doSomethingZombiesDo();

Slide 69

Slide 69 text

function Zombie(personName) { function do_something() { console.log(personName + " just ate a brain!"); } return { doSomethingZombiesDo: do_something }; } var adam = new Zombie("Adam"); adam.doSomethingZombiesDo();

Slide 70

Slide 70 text

define style guidelines

Slide 71

Slide 71 text

start linting your code

Slide 72

Slide 72 text

Inversion of control freakness AM I A CONTROL FREAK?

Slide 73

Slide 73 text

start testing your code

Slide 74

Slide 74 text

Unit or Functional?

Slide 75

Slide 75 text

Do both

Slide 76

Slide 76 text

What to test Unit testing is supposed to test a single atomic “unit” of functionality without dependencies on anything else

Slide 77

Slide 77 text

What to test Unit testing is supposed to test a single atomic “unit” of functionality without dependencies on anything else This is where you start to run into serious dependency problems due to the interrelation HTML and CSS

Slide 78

Slide 78 text

What to test Unit testing is supposed to test a single atomic “unit” of functionality without dependencies on anything else This is where you start to run into serious dependency problems due to the interrelation HTML and CSS What do you test? Usually how the user interface responds to user input. Actually, the realm of functional testing

Slide 79

Slide 79 text

No matter which toolset Grunt PhantomJS JsTestDriver Buster.js Karma Chutzpah Testem Qunit Mocha Jasmine

Slide 80

Slide 80 text

No matter which toolset Grunt PhantomJS JsTestDriver Buster.js Karma Chutzpah Testem Qunit Mocha Jasmine

Slide 81

Slide 81 text

As long as it can be automated share identify build make it continuous

Slide 82

Slide 82 text

Make it part of the process Make it part of the process

Slide 83

Slide 83 text

Make it part of the process http://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/ Estimate testing http://malyn.edublogs.org/2011/10/16/process-tools-people/

Slide 84

Slide 84 text

Make it part of the process Do code review http://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/ http://malyn.edublogs.org/2011/10/16/process-tools-people/

Slide 85

Slide 85 text

Make it part of the process http://rosarioconsulting.net/inspiredtoeducate/?p=706 http://powerbuilder.us/ Involve people http://malyn.edublogs.org/2011/10/16/process-tools-people/

Slide 86

Slide 86 text

Fear the living? DON’T

Slide 87

Slide 87 text

The team

Slide 88

Slide 88 text

DEVOPS PRODUCT OWNER qa

Slide 89

Slide 89 text

QA

Slide 90

Slide 90 text

QA Crucial role in the process

Slide 91

Slide 91 text

QA Crucial role in the process Quality should be your goal too

Slide 92

Slide 92 text

QA Crucial role in the process Quality should be your goal too Get help for functional test coverage not to screw up refactoring

Slide 93

Slide 93 text

Devops

Slide 94

Slide 94 text

Devops The tough guy

Slide 95

Slide 95 text

Devops The tough guy It could be hard to deal with

Slide 96

Slide 96 text

Devops The tough guy It could be hard to deal with Get help setting up the automated process

Slide 97

Slide 97 text

Product owner

Slide 98

Slide 98 text

Product owner The less interested in code itself

Slide 99

Slide 99 text

Product owner The less interested in code itself Bring numbers, not theories

Slide 100

Slide 100 text

Product owner The less interested in code itself Bring numbers, not theories Get help not wasting time, staying focused on functionalities

Slide 101

Slide 101 text

Others in the team

Slide 102

Slide 102 text

juniors external lobbyist

Slide 103

Slide 103 text

Juniors

Slide 104

Slide 104 text

Juniors Pair with them, code review their (and your) code

Slide 105

Slide 105 text

Juniors Pair with them, code review their (and your) code Involve them during the whole process definition

Slide 106

Slide 106 text

Juniors Pair with them, code review their (and your) code Involve them during the whole process definition Get help keeping things easy and accessible

Slide 107

Slide 107 text

Lobbyists

Slide 108

Slide 108 text

Lobbyists They will slow you down, your brain will be more prone to be eaten

Slide 109

Slide 109 text

Lobbyists They will slow you down, your brain will be more prone to be eaten Redirect them to the product owner

Slide 110

Slide 110 text

Basically KILL ‘EM ALL (AGAIN?)

Slide 111

Slide 111 text

Basically KILL ‘EM ALL (AGAIN?)

Slide 112

Slide 112 text

KILL ‘EM ALL (AGAIN?) “Nothing is impossible to kill.” Mira Grant, Feed

Slide 113

Slide 113 text

but

Slide 114

Slide 114 text

“Without requirements or design, programming is the art of adding bugs to an empty text file” Louis Srygley Design for your goal

Slide 115

Slide 115 text

Design for your goal

Slide 116

Slide 116 text

Modular Architecture

Slide 117

Slide 117 text

No content

Slide 118

Slide 118 text

Scalable JavaScript Application Architecture by Nicholas Zakas

Slide 119

Slide 119 text

No content

Slide 120

Slide 120 text

No content

Slide 121

Slide 121 text

core.register("module-name", function(sandbox){ return { init:function(){ }, destroy:function(){ } }; });

Slide 122

Slide 122 text

core.register("module-name", function(sandbox){ return { init:function(){ }, destroy:function(){ } }; });

Slide 123

Slide 123 text

core.register("module-name", function(sandbox){ return { init:function(){ }, destroy:function(){ } }; });

Slide 124

Slide 124 text

No content

Slide 125

Slide 125 text

No content

Slide 126

Slide 126 text

core.register("module-name", function(sandbox){ return { init:function(){ var user = sandbox.getUser(); }, destroy:function(){ } }; });

Slide 127

Slide 127 text

core.register("module-name", function(sandbox){ return { init:function(){ var user = sandbox.getUser(); }, destroy:function(){ } }; });

Slide 128

Slide 128 text

No content

Slide 129

Slide 129 text

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');

Slide 130

Slide 130 text

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');

Slide 131

Slide 131 text

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');

Slide 132

Slide 132 text

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');

Slide 133

Slide 133 text

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');

Slide 134

Slide 134 text

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');

Slide 135

Slide 135 text

No content

Slide 136

Slide 136 text

No content

Slide 137

Slide 137 text

Event Driven Pattern

Slide 138

Slide 138 text

core.register("module-name", function(sandbox){ return { init: function(){ sandbox.layer("an error occured"); } }; });

Slide 139

Slide 139 text

core.register("module-name", function(sandbox){ return { init: function(){ sandbox.layer("an error occured"); } }; });

Slide 140

Slide 140 text

sandbox.layer("an error occured");

Slide 141

Slide 141 text

sandbox.publish("error", { msg: "an error occured" });

Slide 142

Slide 142 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 143

Slide 143 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 144

Slide 144 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 145

Slide 145 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 146

Slide 146 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 147

Slide 147 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 148

Slide 148 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 149

Slide 149 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox){ return { init: function(){ sandbox.subscribe("error", function(err) { console.log(err.msg) }); } }; });

Slide 150

Slide 150 text

sandbox.subscribe("error", function(payload){ console.log(payload.msg); }); Advantages

Slide 151

Slide 151 text

sandbox.subscribe("error", function(payload){ console.log(payload.msg); }); Advantages SEMANTIC

Slide 152

Slide 152 text

sandbox.subscribe("error", function(payload){ console.log(payload.msg); }); Advantages SEMANTIC flexibility

Slide 153

Slide 153 text

Advantages DECOUPLING

Slide 154

Slide 154 text

“The key is to acknowledge from the start that you have no idea how this will grow. When you accept that you don’t know everything, you begin to design the system defensively.” Nicholas Zakas Overengineering?

Slide 155

Slide 155 text

AMD

Slide 156

Slide 156 text

icon by http://www.deleket.com/ jQuery Mustache Libraries Plugins Your scripts

Slide 157

Slide 157 text

icon by http://www.deleket.com/ jQuery Mustache Libraries Plugins Your scripts

Slide 158

Slide 158 text

Slide 159

Slide 159 text

var MyNamespace = {}; MyNamespace.MyAwesomeLibrary = function() { //implementation }; MyNamespace.AnotherCoolOne = function() { //implementation }; MyNamespace.SlightlyCrappyLibrary = function() { //implementation }; MyNamespace.BestLibEver = function() { //implementation };

Slide 160

Slide 160 text

//API: define(id?, dependencies?, factory); define("My-Module", ["Another-Module"], function(AnotherModule){ // Do Something }); one define to rule them all

Slide 161

Slide 161 text

//API: define(id?, dependencies?, factory); define("My-Module", ["Another-Module"], function(AnotherModule){ // Do Something }); one define to rule them all

Slide 162

Slide 162 text

//app/config.js define([], function() { return { url: "http://whatever.it/is/", debug: true }; });

Slide 163

Slide 163 text

//app/config.js define([], function() { return { url: "http://whatever.it/is/", debug: true }; }); //app/config.js define({ url: "http://whatever.it/is/", debug: true });

Slide 164

Slide 164 text

//app/config.js define([], function() { return { url: "http://whatever.it/is/", debug: true }; }); //app/config.js define({ url: "http://whatever.it/is/", debug: true });

Slide 165

Slide 165 text

//app/config.js define([], function() { return { url: "http://whatever.it/is/", debug: true }; }); //app/config.js define({ url: "http://whatever.it/is/", debug: true });

Slide 166

Slide 166 text

//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; } }; }; });

Slide 167

Slide 167 text

//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; } }; }; });

Slide 168

Slide 168 text

//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; } }; }; });

Slide 169

Slide 169 text

//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; } }; }; });

Slide 170

Slide 170 text

//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; } }; }; });

Slide 171

Slide 171 text

//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; } }; }; });

Slide 172

Slide 172 text

//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; } }; }; });

Slide 173

Slide 173 text

//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; } }; }; });

Slide 174

Slide 174 text

//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; } }; }; });

Slide 175

Slide 175 text

Slide 176

Slide 176 text

//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(); }) });

Slide 177

Slide 177 text

//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(); }) });

Slide 178

Slide 178 text

//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(); }) });

Slide 179

Slide 179 text

//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(); }) });

Slide 180

Slide 180 text

//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(); }) });

Slide 181

Slide 181 text

Pulling all together

Slide 182

Slide 182 text

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 } }; }; });

Slide 183

Slide 183 text

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 } }; }; });

Slide 184

Slide 184 text

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 } }; }; });

Slide 185

Slide 185 text

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 } }; }; });

Slide 186

Slide 186 text

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 } }; }; });

Slide 187

Slide 187 text

require(["akase"], function(core) { core.start("module1"); core.start("module2", { config: { debug: true } }); core.start("module3", { event: "audio:stop" }); });

Slide 188

Slide 188 text

require(["akase"], function(core) { core.start("module1"); core.start("module2", { config: { debug: true } }); core.start("module3", { event: "audio:stop" }); });

Slide 189

Slide 189 text

require(["akase"], function(core) { core.start("module1"); core.start("module2", { config: { debug: true } }); core.start("module3", { event: "audio:stop" }); });

Slide 190

Slide 190 text

require(["akase"], function(core) { core.start("module1"); core.start("module2", { config: { debug: true } }); core.start("module3", { event: "audio:stop" }); });

Slide 191

Slide 191 text

require(["akase"], function(core) { core.start("module1"); core.start("module2", { config: { debug: true } }); core.start("module3", { event: "audio:stop" }); });

Slide 192

Slide 192 text

ākāśe sanskrit for "in the sky"/"to the sky" https://github.com/cedmax/akase

Slide 193

Slide 193 text

No such thing!

Slide 194

Slide 194 text

Basically Happy Endings?

Slide 195

Slide 195 text

Basically Happy Endings?

Slide 196

Slide 196 text

“If you want a happy ending, that depends, of course, on where you stop your story.” Orson Wells Happy ending

Slide 197

Slide 197 text

You can run, you can hide

Slide 198

Slide 198 text

You are going to SHITTY code anyway write

Slide 199

Slide 199 text

face You are going to SHITTY code anyway

Slide 200

Slide 200 text

face You are going to Zombie code anyway

Slide 201

Slide 201 text

Embrace it! http://drezner.foreignpolicy.com/posts/2009/08/18/theory_of_international_politics_and_zombies

Slide 202

Slide 202 text

Don’t improvise

Slide 203

Slide 203 text

Learn to know how to deal with it

Slide 204

Slide 204 text

Until you master it

Slide 205

Slide 205 text

in any case just remember to

Slide 206

Slide 206 text

Aim for the head http://halloween.squidoo.com/get-spooked/aim-for-the-head

Slide 207

Slide 207 text

No content

Slide 208

Slide 208 text

[email protected] http://cedmax.com @cedmax any question?