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