Zombie Code

A presentation at Front-Trends 2015 in May 2015 in Warsaw, Poland by Marco Cedaro

Slide 1

Slide 1

TA L K

Slide 2

Slide 2

Zombie Code

Slide 3

Slide 3

Zombie Code how to survive a Javascript Zombiecodeapocalypse

Slide 4

Slide 4

First things first my name is @cedmax

Slide 5

Slide 5

cedmax @ Shazam

Slide 6

Slide 6

cedmax @ Shazam Flav Umar Luca Beer ced

Slide 7

Slide 7

Basically Zombies?

Slide 8

Slide 8

Basically Zombies?

Slide 9

Slide 9

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

Slide 10

Slide 10

ZOMBIE CODE?

Slide 11

Slide 11

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

Slide 12

Slide 12

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

Slide 13

Slide 13

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

Slide 14

Slide 14

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

Slide 15

Slide 15

during estimation

Slide 16

Slide 16

during debugging

Slide 17

Slide 17

during development

Slide 18

Slide 18

It is dumb code  that makes you dumb as well

Slide 19

Slide 19

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

Slide 20

Slide 20

How to identify  Zombie CODE ?

Slide 21

Slide 21

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

Slide 22

Slide 22

3 tips

Slide 23

Slide 23

TIp #1  Code should be appealing

Slide 24

Slide 24

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 25

Slide 25

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

Slide 26

Slide 26

                    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 27

Slide 27

HOW LONG IS THAT?

Slide 28

Slide 28

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 29

Slide 29

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

Slide 30

Slide 30

14 (FOURTEEN!) ifs

Slide 31

Slide 31

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 32

Slide 32

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

Slide 33

Slide 33

are comments a bad thing?

Slide 34

Slide 34

TIp #2  Code should talk to you

Slide 35

Slide 35

_ $

= ( function (_) {

return {

pub : function (a, b, c, d) {

for (d =- 1 , c

[].concat(_[a]); c[ ++ d];) cd },

sub : function (a, b) { ([a] || ([a]

[])).push(b) } } })({})

Slide 36

Slide 36

_ $

= ( function (_) {

return {

pub : function (a, b, c, d) {

for (d =- 1 , c

[].concat(_[a]); c[ ++ d];) cd },

sub : function (a, b) { ([a] || ([a]

[])).push(b) } } })({}) #140bytes

Slide 37

Slide 37

_ $

= ( 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 38

Slide 38

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

Slide 39

Slide 39

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 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 40

Slide 40

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 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 41

Slide 41

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 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 42

Slide 42

//used translate3d to trigger hardware acceleration in webViews //http://www.youtube.com/watch?v=IKl78ZgJzm4 .animated { translate: translate 3 d( 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 43

Slide 43

TIp #3  Code should have 
 personal boundaries

Slide 44

Slide 44

Define 
 boundaries

Slide 45

Slide 45

Single responsibility principle your best tool against Zombie Code

Slide 46

Slide 46

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

Slide 47

Slide 47

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

code-sense is the key Writing clean code requires the disciplined use of a myriad little techniques applied through a painstakingly acquired sense of "cleanliness". Robert C. Martin

Slide 49

Slide 49

worst case smell

Slide 50

Slide 50

worst case smell Long methods

Slide 51

Slide 51

worst case smell Long methods Deep Level of Indentation

Slide 52

Slide 52

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

Slide 53

Slide 53

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

Slide 54

Slide 54

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

Slide 55

Slide 55

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 56

Slide 56

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 57

Slide 57

And now what?

Slide 58

Slide 58

Play cool!

Slide 59

Slide 59

Basically Quarantine

Slide 60

Slide 60

Basically Quarantine

Slide 61

Slide 61

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 62

Slide 62

The broken window

Slide 63

Slide 63

“Don't leave "broken windows" (bad designs, wrong decisions, or poor code) unrepaired. Fix each one as soon as it is discovered.” Jeff Atwood 
 http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html The broken window

Slide 64

Slide 64

“Programming is insanely detail oriented, and perhaps this is why: if you're not on top of the details, the perception is that things are out of control, and it's only a matter of time before your project spins out of control.” Jeff Atwood 
 http://www.codinghorror.com/blog/2005/06/the-broken-window-theory.html The broken window

Slide 65

Slide 65

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 66

Slide 66

Isolate the

Zombies

Slide 67

Slide 67

define style guidelines

Slide 68

Slide 68

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

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

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 71

Slide 71

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 72

Slide 72

start linting your code

Slide 73

Slide 73

Inversion of control freakness AM I A CONTROL FREAK?

Slide 74

Slide 74

start testing your code

Slide 75

Slide 75

Unit or Functional?

Slide 76

Slide 76

Do both

Slide 77

Slide 77

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

continuous

Slide 78

Slide 78

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

Slide 79

Slide 79

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 80

Slide 80

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 81

Slide 81

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 82

Slide 82

Fear the living? DON’T

Slide 83

Slide 83

The team

Slide 84

Slide 84

DEVOPS PRODUCT OWNER qa

Slide 85

Slide 85

QA

Slide 86

Slide 86

QA Crucial role in the process

Slide 87

Slide 87

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

Slide 88

Slide 88

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

Slide 89

Slide 89

Devops

Slide 90

Slide 90

Devops The tough guy

Slide 91

Slide 91

Devops The tough guy It could be hard to deal with

Slide 92

Slide 92

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

Slide 93

Slide 93

Product owner

Slide 94

Slide 94

Product owner The less interested in code itself

Slide 95

Slide 95

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

Slide 96

Slide 96

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

Slide 97

Slide 97

Others in the company

Slide 98

Slide 98

juniors external lobbyist

Slide 99

Slide 99

Juniors

Slide 100

Slide 100

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

Slide 101

Slide 101

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

Slide 102

Slide 102

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 103

Slide 103

Learn to say NO!

Slide 104

Slide 104

Learn to say NO! Lobbyists will slow you down, your brain will be more prone to be eaten

Slide 105

Slide 105

Learn to say NO! Lobbyists will slow you down, your brain will be more prone to be eaten Redirect them to the product owner

Slide 106

Slide 106

Basically KILL ‘EM ALL (AGAIN?)

Slide 107

Slide 107

Basically KILL ‘EM ALL (AGAIN?)

Slide 108

Slide 108

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

Mira Grant, Feed

Slide 109

Slide 109

but

Slide 110

Slide 110

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

Slide 111

Slide 111

Design for your goal

Slide 112

Slide 112

ā k āś e

 sanskrit for "in the sky"/"to the sky"  https://github.com/cedmax/akase

Slide 113

Slide 113

Modular Architecture

Slide 114

Slide 114

Slide 115

Slide 115

Scalable JavaScript Application  Architecture by Nicholas Zakas

Slide 116

Slide 116

Slide 117

Slide 117

Slide 118

Slide 118

core.register( "module-name" , function (sandbox){

return {

init : function (){

    },
    

destroy : function (){

    }
};

});

Slide 119

Slide 119

core.register( "module-name" , function (sandbox){

return {

init : function (){

    },
    

destroy : function (){

    }
};

});

Slide 120

Slide 120

core.register( "module-name" , function (sandbox){

return {

init : function (){

    },
    

destroy : function (){

    }
};

});

Slide 121

Slide 121

Slide 122

Slide 122

Slide 123

Slide 123

core.register( "module-name" , function (sandbox){

return {

init : function (){

var user

sandbox.getUser(); },

destroy : function (){

    }
};

});

Slide 124

Slide 124

core.register( "module-name" , function (sandbox){

return {

init : function (){

var user

sandbox.getUser(); },

destroy : function (){

    }
};

});

Slide 125

Slide 125

Slide 126

Slide 126

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 127

Slide 127

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 128

Slide 128

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 129

Slide 129

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

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

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

Slide 133

Slide 133

Slide 134

Slide 134

Event Driven Pattern

Slide 135

Slide 135

core.register( "module-name" , function (sandbox){

return {

init : function (){ sandbox.layer( "an error occured" ); } }; });

Slide 136

Slide 136

core.register( "module-name" , function (sandbox){

return {

init : function (){ sandbox.layer( "an error occured" ); } }; });

Slide 137

Slide 137

sandbox.layer( "an error occured" );

Slide 138

Slide 138

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

Slide 139

Slide 139

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 140

Slide 140

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 141

Slide 141

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 142

Slide 142

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

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

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

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

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

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

Slide 148

Slide 148

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

Slide 149

Slide 149

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

Slide 150

Slide 150

Advantages DECOUPLING

Slide 151

Slide 151

“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 152

Slide 152

AMD

Slide 153

Slide 153

//API: define(id?, dependencies?, factory) ; define( "My-Module" , [ "Another-Module" ], function (AnotherModule){

// Do Something }); one define to rule them all

Slide 154

Slide 154

//API: define(id?, dependencies?, factory) ; define( "My-Module" , [ "Another-Module" ], function (AnotherModule){

// Do Something }); one define to rule them all

Slide 155

Slide 155

//app/config.js define([], function () {

return { url: "http://whatever.it/is/" , debug: true }; });

Slide 156

Slide 156

//app/config.js define([], function () {

return { url: "http://whatever.it/is/" , debug: true }; });

Slide 157

Slide 157

//app/config.js define([], function () {

return { url: "http://whatever.it/is/" , debug: true }; });

Slide 158

Slide 158

//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 159

Slide 159

//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 160

Slide 160

//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 161

Slide 161

//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 162

Slide 162

//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 163

Slide 163

//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 164

Slide 164

//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 165

Slide 165

//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 166

Slide 166

//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

<script data-main= "app/main" src= "require.js" ></script>

Slide 168

Slide 168

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

Slide 169

Slide 169

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

Slide 170

Slide 170

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

Slide 171

Slide 171

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

Slide 172

Slide 172

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

Slide 173

Slide 173

Pulling all together

Slide 174

Slide 174

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 175

Slide 175

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 176

Slide 176

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 177

Slide 177

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 178

Slide 178

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 179

Slide 179

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

Slide 180

Slide 180

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

Slide 181

Slide 181

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

Slide 182

Slide 182

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

Slide 183

Slide 183

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

Slide 184

Slide 184

ā k āś e

 sanskrit for "in the sky"/"to the sky"  https://github.com/cedmax/akase

Slide 185

Slide 185

2 years later…

Slide 186

Slide 186

require = { baseUrl: '/assets/js/module' , shim: { 'magnificpopup' : { deps: [ 'jquery' ] }, 'timezone' : { exports: 'jstz' }, 'facebook' : { exports: 'FB' } }, paths: { 'templates' : '../../templates' , 'widget' : '../widget' , 'core' : '../core' , 'packages' : '../packages' , 'jquery' : 'js/vendor/jquery-2.0.0.min.js' , 'magnificpopup' : 'js/vendor/mpopup-0.9.2.min.js' , 'modernizr' : 'js/vendor/modernizr.min.js' , 'fastclick' : 'js/vendor/fastclick-1.0.2.min.js' , 'timezone' : 'js/vendor/timezone-1.0.4.min.js' , 'typeahead' : 'js/vendor/typeahead-0.9.3.min.js' }, waitSeconds:30 };

Slide 187

Slide 187

var $ = require( "jquery" ); // Do Something var myscript = require( "myscript" ); var anotherDep = require( "anotherDep" ); // Do Something else COMMON JS require([ "jquery" , "myscript" , "anotherDep" , ], function ($, myscript, anotherDep ){

// Do Something }); REQUIRE JS

Slide 188

Slide 188

import $ from

'jquery' ; import myscript from

'myscript' ; import anotherDep from

'anotherDep' ; // Do Something ES6

Slide 189

Slide 189

No such thing!

Slide 190

Slide 190

Basically Happy Endings?

Slide 191

Slide 191

Basically Happy Endings?

Slide 192

Slide 192

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

Slide 193

Slide 193

You can run, you can hide

Slide 194

Slide 194

You are going to 

SHITTY code  anyway write

Slide 195

Slide 195

You are going to  write Zombie code  anyway

Slide 196

Slide 196

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

Slide 197

Slide 197

Don’t improvise

Slide 198

Slide 198

Learn how to deal with it

Slide 199

Slide 199

Until you master it

Slide 200

Slide 200

in any case just  remember to

Slide 201

Slide 201

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

Slide 202

Slide 202

Slide 203

Slide 203

marco@fromthefront.it http://cedmax.com @cedmax any question?