flux - rethink in design pattern

37
Flux – Rethink In Design Pattern JULY, 2015

Upload: oleg-gomozov

Post on 28-Jan-2018

522 views

Category:

Engineering


1 download

TRANSCRIPT

Page 1: Flux - rethink in design pattern

Flux – Rethink In Design Pattern

JULY, 2015

Page 2: Flux - rethink in design pattern

‹#›CONFIDENTIAL

AGENDA

•What is wrong with MVC?

•Flux in a nutshell

•React as a part of Flux

•What is wrong with Flux?

•Flux frameworks overview

Page 3: Flux - rethink in design pattern

‹#›CONFIDENTIAL

WHAT IS WRONG WITH MVC?

Page 4: Flux - rethink in design pattern

‹#›CONFIDENTIAL

COMMON MVC DIAGRAM

Page 5: Flux - rethink in design pattern

‹#›CONFIDENTIAL

IDEAL MVC APPLICATION

Page 6: Flux - rethink in design pattern

‹#›CONFIDENTIAL

REAL MVC APPLICATION

Page 7: Flux - rethink in design pattern

‹#›CONFIDENTIAL

Models can send events to many views as well as

views too

1

Common two-way binding pattern leads to cascade

changes, which hard to debug

2

No single entry point for actions, so any function can

be publisher or subscriber of event

3

Single responsibility principle is usually become

broken

4

MAIN ISSUES

Page 8: Flux - rethink in design pattern

‹#›CONFIDENTIAL

FLUX IN A NUTSHELL

Page 9: Flux - rethink in design pattern

‹#›CONFIDENTIAL

FLUX COMMON DIAGRAM

(c) http://facebook.github.io/flux/docs/overview.html

Page 10: Flux - rethink in design pattern

‹#›CONFIDENTIAL

DISPATHER

class Dispatcher {

register(callback) {}

unregister(id) {}

waitFor(ids) {}

dispatch(payload) {

for (var id in this._callbacks) {

this._invokeCallback(id);

}

}

_invokeCallback(id) {}

}

Page 11: Flux - rethink in design pattern

‹#›CONFIDENTIAL

STORE

class Store = {

emitChange: function(CHANGE_EVENT) {},

addChangeListener: function(CHANGE_EVENT , callback) {},

removeChangeListener: function(CHANGE_EVENT , callback) {}

};

Dispatcher.register(function(action) {

switch(action.actionType) {

case ACTIONS.ACTION1:

// do something

Store.emitChange(CHANGE_EVENT1);

case ACTIONS.ACTION2:

// do something

Store.emitChange(CHANGE_EVENT2);

}

});

Page 12: Flux - rethink in design pattern

‹#›CONFIDENTIAL

ACTIONS

class Actions = {

action1Function: function(params) {

Dispatcher.dispatch({

actionType: ACTION1,

params: params

});

},

action2Function: function(params) {

Dispatcher.dispatch({

actionType: ACTION2,

params: params

});

}

};

Page 13: Flux - rethink in design pattern

‹#›CONFIDENTIAL

VIEW

class View = {

onEvent1: function() {

Actions.action1Function(params);

},

onEvent2: function() {

Actions.action2Function(params);

}

};

Page 14: Flux - rethink in design pattern

‹#›CONFIDENTIAL

REACT AS A PART OF FLUX

Page 15: Flux - rethink in design pattern

‹#›CONFIDENTIAL

FLUX + REACT WEB DIAGRAM

(c) https://github.com/facebook/flux

Page 16: Flux - rethink in design pattern

‹#›CONFIDENTIAL

Decoupling with component model 1

Virtual DOM, synthetic events and fast render 2

No templates, code and markup in one place3

Uni-directional flow4

Page 17: Flux - rethink in design pattern

‹#›CONFIDENTIAL

REACT BACKBONE

Page 18: Flux - rethink in design pattern

‹#›CONFIDENTIAL

VIRTUAL DOM VS REAL DOM

Page 19: Flux - rethink in design pattern

‹#›CONFIDENTIAL

React View Life Cycle

Page 20: Flux - rethink in design pattern

‹#›CONFIDENTIAL

WHAT IS WRONG WITH FLUX?

Page 21: Flux - rethink in design pattern

‹#›CONFIDENTIAL

ACTIONS list and file grows with complexity of

application

1

class Actions = {

action1Function: function(params) {………………………},

action2Function: function(params) {………………………},

action3Function: function(params) {………………………},

action4Function: function(params) {………………………},

action5Function: function(params) {………………………},

action6Function: function(params) {………………………},

action7Function: function(params) {………………………},

};

Page 22: Flux - rethink in design pattern

‹#›CONFIDENTIAL

When to create new STORE, what are criteria of

STORE as definite entity?

2

Facebook: “Stores are not models, not single records, not collections. Stores manage the application state for a particular domain wi

Page 23: Flux - rethink in design pattern

‹#›CONFIDENTIAL

Can STORE produce ACTION? Does it break the flow?3

class Store = {

doSomething: function() {

Actions.action1Function(params);

}

};

Dispatcher.register(function(action) {

switch(action.actionType) {

case ACTIONS.ACTION1:

Store.doSomething();

}

});

Page 24: Flux - rethink in design pattern

‹#›CONFIDENTIAL

Is it eligible to call two ACTIONS in a row? Does it

break the flow?

4

class View = {

onEvent1: function() {

Actions.action1Function(params);

Actions.action2Function(params);

}

};

Page 25: Flux - rethink in design pattern

‹#›CONFIDENTIAL

Is FLUX framework or pattern?5

Facebook: “Flux is the application architecture that Facebook

uses for building client-side web applications. It complements

React's composable view components by utilizing a

unidirectional data flow. It's more of a pattern rather than a

formal framework”

Page 26: Flux - rethink in design pattern

‹#›CONFIDENTIAL

FLUX FRAMEWORKS OVERVIEW

Page 27: Flux - rethink in design pattern

‹#›CONFIDENTIAL

REFLUX JS

Page 28: Flux - rethink in design pattern

‹#›CONFIDENTIAL

REFLUX JS

(c) https://github.com/spoike/refluxjs

The singleton dispatcher is removed in favor for

letting every action act as dispatcher instead

1

Because actions are listenable, the stores may listen

to them. Stores don't need to have big switch

statements that do static type checking with strings

2

Stores may listen to other stores, i.e. it is possible to

create stores that can aggregate data further,

similar to a map/reduce

3

waitFor is replaced in favor to handle serial and

parallel data flows

4

Action creators are not needed because RefluxJS

actions are functions that will pass on the payload

they receive to anyone listening to them

5

Page 29: Flux - rethink in design pattern

‹#›CONFIDENTIAL

var Actions = Reflux.createActions({

"loadData": {children: ["completedData","failedData"]}

});

Actions.loadData.listen( function() {

ajaxAsyncOperation()

.then( this.completedData )

.catch( this.failedData);

});

var Store = Reflux.createStore({

init: function() {

this.listenToMany(Actions);

},

onCompletedData: function(){},

onFailedData: function(){}

});

var Store = Reflux.createStore({

init: function() {

this.joinLeading(actions.action1,

actions.action2, actions.action3);

}

});

Page 30: Flux - rethink in design pattern

‹#›CONFIDENTIAL

DELOREAN JS

Page 31: Flux - rethink in design pattern

‹#›CONFIDENTIAL

DELOREAN JS

Unidirectional data flow1

Automatically listens to data changes and keeps data

updated

2

Makes data more consistent across whole application3

Page 32: Flux - rethink in design pattern

‹#›CONFIDENTIAL

var Store = DeLorean.Flux.createStore({

setData: function (data) {

this.data = data;

this.emit('change');

},

actions: { 'incoming-data': ‘setData' }

});

var Dispatcher = DeLorean.Flux.createDispatcher({

setData: function (data) {

this.dispatch('incoming-data', data);

},

getStores: function () { return {increment: Store}; }

});

var Actions = {

setData: function (data) {

Dispatcher.setData(data);

}

};

Store.onChange(function () {

document.getElementById('result').innerText = store.data;

});

document.getElementById('dataChanger').onclick = function () {

Actions.setData(Math.random());

};

Page 33: Flux - rethink in design pattern

‹#›CONFIDENTIAL

FLUXXOR

Page 34: Flux - rethink in design pattern

‹#›CONFIDENTIAL

FLUXXOR

Easy to bind actions1

Dispatch function is moved to actions layer2

Built-in integration with React components3

Page 35: Flux - rethink in design pattern

‹#›CONFIDENTIAL

var Store = Fluxxor.createStore({

initialize: function() {

this.bindActions(ACTION1, this.onAction1);

},

onAction1: function(payload) {

//do something

this.emit("change");

}

});

var actions = {

action1: function(payload) {

this.dispatch(ACTION1, payload);

}

};

var FluxMixin = Fluxxor.FluxMixin(React), StoreWatchMixin =

Fluxxor.StoreWatchMixin;

var Application = React.createClass({

mixins: [FluxMixin, StoreWatchMixin("Store")],

getStateFromFlux: function() {

return this.getFlux().store("Store").getState();

},

render: function () {}

});

Page 36: Flux - rethink in design pattern

‹#›CONFIDENTIAL

REFERENCE

https://github.com/facebook/flux

http://facebook.github.io/react/blog/2014/05/06/flux.html

https://facebook.github.io/react/docs/component-specs.html

https://github.com/voronianski/flux-comparison

https://www.youtube.com/watch?v=LTj4O7WJJ98

Page 37: Flux - rethink in design pattern

‹#›CONFIDENTIAL

THANKQ

Q&A