Slide 1

Slide 1 text

TALK

Slide 2

Slide 2 text

Zombie Code London 21st October

Slide 3

Slide 3 text

First things first my name is @cedmax

Slide 4

Slide 4 text

cedmax @ Kahoot!

Slide 5

Slide 5 text

Basically Zombies?

Slide 6

Slide 6 text

Basically Zombies?

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

ZOMBIE CODE?

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

during estimation

Slide 14

Slide 14 text

during debugging

Slide 15

Slide 15 text

during development

Slide 16

Slide 16 text

It is dumb code that makes you dumb as well

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

There isn’t a recipe https://www.etsy.com/listing/224941057/zombie-cure-pill-case-7-sections-pill

Slide 19

Slide 19 text

How to identify Zombie CODE?

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

TIp #1 Code should be appealing

Slide 22

Slide 22 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 23

Slide 23 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 24

Slide 24 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 25

Slide 25 text

- A very long method

Slide 26

Slide 26 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 27

Slide 27 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 28

Slide 28 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 29

Slide 29 text

- 14 (FOURTEEN!) if statements

Slide 30

Slide 30 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 31

Slide 31 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 32

Slide 32 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 33

Slide 33 text

- nested function definitions

Slide 34

Slide 34 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 35

Slide 35 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 36

Slide 36 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 37

Slide 37 text

- deep level of indentation

Slide 38

Slide 38 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 39

Slide 39 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 40

Slide 40 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 41

Slide 41 text

HOLD ON THERE!
 are comments a bad thing?

Slide 42

Slide 42 text

TIp #2 Code should talk to you

Slide 43

Slide 43 text

var PubSub = ((_) => ({ pub:(a, b, c, d) => { for (d=-1, c=[].concat(_[a]); c[++d];) c[d](b) }, sub:(a, b) => { (_[a] || (_[a] = [])).push(b) } }))({})

Slide 44

Slide 44 text

var PubSub = ((_) => ({ pub:(a, b, c, d) => { for (d=-1, c=[].concat(_[a]); c[++d];) c[d](b) }, sub:(a, b) => { (_[a] || (_[a] = [])).push(b) } }))({}) #140bytes

Slide 45

Slide 45 text

var PubSub = (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 46

Slide 46 text

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

Slide 47

Slide 47 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 48

Slide 48 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 49

Slide 49 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 50

Slide 50 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 51

Slide 51 text

TIp #3 Code should have 
 personal boundaries

Slide 52

Slide 52 text

Define 
 boundaries

Slide 53

Slide 53 text

Single responsibility principle your best tool against Zombie Code

Slide 54

Slide 54 text

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 55

Slide 55 text

worst case smell

Slide 56

Slide 56 text

worst case smell Long methods

Slide 57

Slide 57 text

worst case smell Long methods Deep Level of Indentation

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability Copy/paste driven development

Slide 61

Slide 61 text

worst case smell Long methods Deep Level of Indentation Hard to tell what it does Lack of portability Copy/paste driven development Callback hell

Slide 62

Slide 62 text

And now what?

Slide 63

Slide 63 text

Play cool!

Slide 64

Slide 64 text

Basically Quarantine

Slide 65

Slide 65 text

Basically Quarantine

Slide 66

Slide 66 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 67

Slide 67 text

The broken window

Slide 68

Slide 68 text

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

Slide 69 text

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

Slide 70 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 71

Slide 71 text

Isolate the Zombies

Slide 72

Slide 72 text

define a styleguide http://alistapart.com/article/creating-style-guides

Slide 73

Slide 73 text

…and enforce it

Slide 74

Slide 74 text

Inversion of control freakness AM I A CONTROL FREAK?

Slide 75

Slide 75 text

start testing your code

Slide 76

Slide 76 text

Both Unit or Functional

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 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 80

Slide 80 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 81

Slide 81 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 82

Slide 82 text

Fear the living? DON’T

Slide 83

Slide 83 text

The team

Slide 84

Slide 84 text

PRODUCT OWNER DevOPS qa

Slide 85

Slide 85 text

Quality Assurance

Slide 86

Slide 86 text

Quality Assurance Crucial role in the process

Slide 87

Slide 87 text

Quality Assurance Crucial role in the process You share the same goals

Slide 88

Slide 88 text

Quality Assurance Crucial role in the process You share the same goals Get help for functional tests, they are a drain!

Slide 89

Slide 89 text

Devops

Slide 90

Slide 90 text

Devops The tough one

Slide 91

Slide 91 text

Devops The tough one It could be hard to deal with

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

Product owner

Slide 94

Slide 94 text

Product owner The less interested in code itself

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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 text

Others in the company

Slide 98

Slide 98 text

juniors external lobbyist

Slide 99

Slide 99 text

Juniors

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

Learn to say NO!

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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 text

Basically KILL ‘EM ALL (AGAIN?)

Slide 107

Slide 107 text

Basically KILL ‘EM ALL (AGAIN?)

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

but

Slide 110

Slide 110 text

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

Design for your goal

Slide 112

Slide 112 text

Modular Architecture

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

Scalable JavaScript Application Architecture by Nicholas Zakas
 circa 2009

Slide 115

Slide 115 text

No content

Slide 116

Slide 116 text

No content

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

No content

Slide 121

Slide 121 text

No content

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

No content

Slide 125

Slide 125 text

core.register(‘module-name', (sandbox) => { init: function(config) { console.log(config.id); } }); core.configure('module-name', { id: 'container', }); core.start('module-name'); core.stop('module-name');

Slide 126

Slide 126 text

core.register(‘module-name', (sandbox) => { 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 text

core.register(‘module-name', (sandbox) => { 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 text

core.register(‘module-name', (sandbox) => { 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 text

core.register(‘module-name', (sandbox) => { 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', (sandbox) => { 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

No content

Slide 132

Slide 132 text

No content

Slide 133

Slide 133 text

Event Driven Pattern

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

sandbox.layer("an error occured");

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

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

Slide 141

Slide 141 text

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

Slide 142

Slide 142 text

sandbox.publish("error", { msg: "an error occured" }); core.register("errManager", function(sandbox) => { 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) => { 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) => { 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) => { init: function() { sandbox.subscribe("error", function(err) { console.log(err.msg) } }); });

Slide 146

Slide 146 text

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

Slide 147

Slide 147 text

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

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

Advantages DECOUPLING

Slide 150

Slide 150 text

Flux
 circa 2014

Slide 151

Slide 151 text

Flux

Slide 152

Slide 152 text

Flux I can walk you through it

Slide 153

Slide 153 text

Flux A kind of usual feature

Slide 154

Slide 154 text

Flux The user triggers an event…

Slide 155

Slide 155 text

onFollowButtonClick(user) { actionCreators.followButtonClicked({ user }); } …and an event handler kicks in Flux

Slide 156

Slide 156 text

onFollowButtonClick(user) { actionCreators.followButtonClicked({ user }); } …and an event handler kicks in Flux

Slide 157

Slide 157 text

Flux Here comes the action

Slide 158

Slide 158 text

followButtonClicked({ user }) { APIClient.followUser(user.uuid) .then(() => { dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } }); }); } Let’s have a look at the action creator Flux

Slide 159

Slide 159 text

followButtonClicked({ user }) { APIClient.followUser(user.uuid) .then(() => { dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } }); }); } The created action has a type and a data prop Flux

Slide 160

Slide 160 text

followButtonClicked({ user }) { APIClient.followUser(user.uuid) .then(() => { dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } }); }); } Where the type is an identifier Flux

Slide 161

Slide 161 text

followButtonClicked({ user }) { APIClient.followUser(user.uuid) .then(() => { dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } }); }); } The action could depend on a network call Flux

Slide 162

Slide 162 text

followButtonClicked({ user }) { APIClient.followUser(user.uuid) .then(() => { dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } }); }); } It gets sent to the dispatcher Flux

Slide 163

Slide 163 text

Flux The dispatcher is where the magic happens

Slide 164

Slide 164 text

Let’s dumb it down Flux followButtonClicked({ user }) { APIClient.followUser(user.uuid) .then(() => { dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } }); }); }

Slide 165

Slide 165 text

Let’s dumb it down Flux followButtonClicked({ user }) { APIClient.followUser(user.uuid) .then(() => { dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } }); }); }

Slide 166

Slide 166 text

Doesn’t it look like… Flux dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } });

Slide 167

Slide 167 text

a pub sub! Flux dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } });
 
 pubSub.publish( actionTypes.userFollowed, { user } );

Slide 168

Slide 168 text

Flux dispatcher.handleAction({ type: actionTypes.userFollowed, data: { user } });
 
 pubSub.publish( actionTypes.userFollowed, { user } ); As a matter of fact it is

Slide 169

Slide 169 text

Flux And the store is subscribed to it

Slide 170

Slide 170 text

Flux The store is where your business logic lives

Slide 171

Slide 171 text

export default { [actionTypes.userFollowed]: function({ data }) {
 //MAGIC to define the new followers list
 this.updateState({ user: { followers } });
 this.emitChange(); } } Please test your magic Flux

Slide 172

Slide 172 text

export default { [actionTypes.userFollowed]: function({ data }) {
 //MAGIC to define the new followers list
 this.updateState({ user: { followers } });
 this.emitChange(); } } The store updates the model… Flux

Slide 173

Slide 173 text

export default { [actionTypes.userFollowed]: function({ data }) {
 //MAGIC to define the new followers list
 this.updateState({ user: { followers } });
 this.emitChange(); } } …and it emits the change Flux

Slide 174

Slide 174 text

Which would trigger the view to update Flux

Slide 175

Slide 175 text

Want to unfollow? Flux

Slide 176

Slide 176 text

Here we go again Flux

Slide 177

Slide 177 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 178

Slide 178 text

No such thing!

Slide 179

Slide 179 text

Basically Happy Endings?

Slide 180

Slide 180 text

Basically Happy Endings?

Slide 181

Slide 181 text

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

Slide 182

Slide 182 text

You can run, you can hide

Slide 183

Slide 183 text

You are going to SHITTY code anyway write

Slide 184

Slide 184 text

You are going to write Zombie code anyway

Slide 185

Slide 185 text

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

Slide 186

Slide 186 text

Don’t improvise

Slide 187

Slide 187 text

Learn how to deal with it

Slide 188

Slide 188 text

Until you master it

Slide 189

Slide 189 text

Just remember to

Slide 190

Slide 190 text

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

Slide 191

Slide 191 text

No content

Slide 192

Slide 192 text

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