79
Flux Application Architecture Facebooks' Architekturansatz Sven Kölpin open knowledge GmbH

Die Flux Application Architecture - Facebooks Ansatz für Client-side Web Applications

Embed Size (px)

Citation preview

Flux Application ArchitectureFacebooks' Architekturansatz

Sven Kölpinopen knowledge GmbH

Herbstcampus 2015 – Flux Application Architecture 2

Model View Controller im Web

ControllerModel View

ClientServer

Herbstcampus 2015 – Flux Application Architecture 3

Model View Controller im Web

ControllerModel View

ClientServer

DB ROUTER HTML

HTML

Herbstcampus 2015 – Flux Application Architecture 4

Model View Controller im Web

ControllerModel View

ClientServer

DB ROUTER HTML

HTML

Business

Logik

Herbstcampus 2015 – Flux Application Architecture 5

Model View Controller im Web

• Applikationsstatus: Entitäten der DB

• Statusänderung: • Per URL

• Per Form-Submit

• Kein Status im Browser• View ist „dumm“

• HTML = Server-Status

Herbstcampus 2015 – Flux Application Architecture 6

Model View Controller im Web

http://davidatlanta.com/

Herbstcampus 2015 – Flux Application Architecture 7

Model View Controller im Web

ControllerModel View

ClientServer

DBRESTful-

Service

HTML

JavaScript

HTML

JSON

Business

Logik

Herbstcampus 2015 – Flux Application Architecture 8

Model View Controller im Web

ControllerModel View

ClientServer

DBRESTful-

Service

HTML

JavaScript

HTML

JSON

ControllerModel View

Business

Logik

Herbstcampus 2015 – Flux Application Architecture 9

Model View Controller im Web

• JavaScript-MVC – Frameworks FTW

• Back to traditional MVC

Herbstcampus 2015 – Flux Application Architecture 10

Model View Controller

Controller Model Viewupdates

queries

notifies

user actions

Herbstcampus 2015 – Flux Application Architecture 11

Model View Controller

• Model:• Verhalten und Status einer Anwendung

• View:• Visuelle Repräsentation des Models

• Controller:• Interaktionen, Manipulation des Modells

Controller Model Viewupdates

queries

notifies

user actions

Herbstcampus 2015 – Flux Application Architecture 12

MVC in JavaScript

Herbstcampus 2015 – Flux Application Architecture 13

MVC in JavaScript

• MV* oder MVW• MVC, MVP, MVVM..

• BackboneJS: kein Controller

• AngularJS: MVVM

• ReactJS: nur View

Herbstcampus 2015 – Flux Application Architecture 14

MVC in JavaScript

• MV* oder MVW• MVC, MVP, MVVM..

• BackboneJS: kein Controller

• AngularJS: MVVM

• ReactJS: nur View

Separation of view and logic

Herbstcampus 2015 – Flux Application Architecture 15

MVC in JavaScript

Model View

Controller, Router, ..

observer

Herbstcampus 2015 – Flux Application Architecture 16

MVC in JavaScript

• Und außerdem:

• Entity-State

• Nicht mehr Vordergründig

• View braucht eigenen State

• UI-State

• Server-State

Herbstcampus 2015 – Flux Application Architecture 17

Flux

Herbstcampus 2015 – Flux Application Architecture 18

MVC – Facebooks‘ Probleme

Model View

View

View

View

Model

Model

Model

Controller

Herbstcampus 2015 – Flux Application Architecture 19

MVC – Facebooks‘ Probleme

Model View

View

View

View

Model

Model

Model

Controller Bidirektional!

Herbstcampus 2015 – Flux Application Architecture 20

MVC – Facebooks‘ Probleme

• Beispiel FB-Chat:

• View A: Liste aller Nachrichten,

ungelesene hervorgehoben

• View B: Anzahl ungelesener Nachrichten

Herbstcampus 2015 – Flux Application Architecture 21

MVC – Facebooks‘ Probleme

Model(thread model)

View

View

View

View

Model(unread thread count

model)

Model

Model

Herbstcampus 2015 – Flux Application Architecture 22

MVC – Facebooks‘ Probleme

• Komplexe Interaktionen• Einfaches Model-Update Massenänderungen

• Model triggers View, View triggers Model

• Zirkuläre Abhängigkeiten

• Kein Raum für neue Features

MVC does not scale © facebook

Herbstcampus 2015 – Flux Application Architecture 23

Flux

© fansshare.com

Excited for the

Flux-solution???

Herbstcampus 2015 – Flux Application Architecture 24

Flux ist…

• Architekturvorschlag (micro-architecture)• Fokus: Frontend & Webapps

• Kein Framework

• Ziel: Schwächen von MVC eliminieren• Nachvollziehbare Pfade für Daten

• Änderungen leichter umzusetzen

• Bugs leichter auffindbar

Herbstcampus 2015 – Flux Application Architecture 25

Flux

• Unidirektionaler Datenfluss

Action Dispatcher Store View

Herbstcampus 2015 – Flux Application Architecture 26

Flux

• Unidirektionaler Datenfluss

• View bekommt Daten READONLY

Action Dispatcher Store View

Herbstcampus 2015 – Flux Application Architecture 27

Flux

• Unidirektionaler Datenfluss

• Datenmanipulation synchron durch Actions• Benachrichtigung von Views über Events (synchron)

Action Dispatcher Store View

Herbstcampus 2015 – Flux Application Architecture 28

Flux im Schnelldurchlauf

Herbstcampus 2015 – Flux Application Architecture 29

Flux im Schnelldurchlauf

View

Herbstcampus 2015 – Flux Application Architecture 30

Flux im Schnelldurchlauf

View

Action

Herbstcampus 2015 – Flux Application Architecture 31

Flux im Schnelldurchlauf

View

Action

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Herbstcampus 2015 – Flux Application Architecture 32

Flux im Schnelldurchlauf

View

Action

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Store

Dispatch {PAYLOAD}

Herbstcampus 2015 – Flux Application Architecture 33

Flux im Schnelldurchlauf

View

Action

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Store

Dispatch {PAYLOAD}

Business logic based on action

& payload

emit change event

Update view and

children

Herbstcampus 2015 – Flux Application Architecture 34

Flux im Schnelldurchlauf

View

Action API

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Store

Dispatch {PAYLOAD}

Business logic based on action

& payload

emit change event

Update view and

children

Herbstcampus 2015 – Flux Application Architecture 35

Flux im Detail

Herbstcampus 2015 – Flux Application Architecture 36

Flux im Detail

View

Action API

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Store

Dispatch {PAYLOAD}

Business logic based on action

& payload

emit change event

Update view and

children

Herbstcampus 2015 – Flux Application Architecture 37

Flux - Views

• Ähnlich MVC-View • Rufen Actions auf

• Aktualisieren sich selbst

• Hören auf Stores

• View vs. Controller-View• Controller-View: Kleber zw.

Store und Kind-ViewsState

Store

View View

Controller-View

Herbstcampus 2015 – Flux Application Architecture 38

Flux - Views

var SomeView = React.createClass({

getInitialState() {

return {

loggedUser: SessionStore.getLoggedUser()

}

},

componentDidMount() {

SessionStore.addChangeListener(this.onChange);

},

onChange(){

this.setState({

loggedUser: SessionStore.getLoggedUser()

});

},

render() {

return (

<h1> this.state.loggedUser </h1>

);

}

});

Herbstcampus 2015 – Flux Application Architecture 39

Flux - Views

• Besonderheiten:

• Stores geben gesamten Status an die Views

• Komplexitätsreduzierung

• ReactJS: Virtueller DOM-Tree

• Performante Überprüfung auf Änderungen

• Best-Practice: Ein Controller-View für einen Bereich

Herbstcampus 2015 – Flux Application Architecture 40

Flux im Detail

View

Action API

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Store

Dispatch {PAYLOAD}

Business logic based on action

& payload

emit change event

Update view and

children

Herbstcampus 2015 – Flux Application Architecture 41

Flux - Actions

• Verarbeitung von Interaktionen• Vermittlung zw.View und Store

• Action creator• Sammlung von Funktionen

• Action• POJO

• Action-Type + Payload

var action = {

actionType: TodoConstants.TODO_CREATE,

payload: {

title :"get milk",

details : "must be soja milk"

}

}

Herbstcampus 2015 – Flux Application Architecture 42

Flux - Actions

View

Action

Creator

Action

calls

creates

...

login(){

SessionActions.login();

},

render() {

return (

<button onClick={this.login}/>

);

}

var SessionActions = {

login() {

// ...

var action = {

actionType: SessionStoreConstants.LOGIN,

data: …

};

//...

}

};

Herbstcampus 2015 – Flux Application Architecture 43

Flux - Actions

View

Action

Creator

Action

calls

creates

...

login(){

SessionActions.login();

},

render() {

return (

<button onClick={this.login}/>

);

}

var SessionActions = {

login() {

// ...

var loginOnServ =

$.ajax({url: "login", type: "POST"});

loginOnServ.then((data) => {

var action = {

actionType: SessionStoreConstants.LOGIN,

data: data

}

...

});

}

};

API

Herbstcampus 2015 – Flux Application Architecture 44

Flux - Actions

• Besonderheiten• Actions über Konstanten definiert

• Übergabe von Actions an Dispatcher

• API-Zugriff erfolgt in den Actions

var SessionStoreConstants = {

LOGIN : "LOGIN",

LOGOUT : "LOGOUT“

};

var action = {

actionType: SessionStoreConstants.LOGIN,

data: data

});

AppDispatcher.handleAction(action);

Herbstcampus 2015 – Flux Application Architecture 45

Flux im Detail

View

Action API

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Store

Dispatch {PAYLOAD}

Business logic based on action

& payload

emit change event

Update view and

children

Herbstcampus 2015 – Flux Application Architecture 46

Flux - Dispatcher

• Zentraler HUB der Applikation• Es gibt nur einen Dispatcher!

• Versendet (dispatches) Actions an Stores• Ähnlich zu pub/sub (JS first-class functions)

• != Controller in MVC!• Singleton

• Keinerlei Geschäftslogik, ausschließlich pub/sub

• Domänenunabhängig

Herbstcampus 2015 – Flux Application Architecture 47

Flux - Dispatcher

Payload

Dispatcher

Store Store Store

Herbstcampus 2015 – Flux Application Architecture 48

Flux - Dispatcher

var AppDispatcher = new Dispatcher();

AppDispatcher.handleAction = function(action) {

this.dispatch({

source: 'VIEW_ACTION',

action: action

});

};

var action = {

actionType: SessionStoreConstants.LOGIN,

data: data

});

AppDispatcher.handleAction(action);

Herbstcampus 2015 – Flux Application Architecture 49

Flux - Dispatcher

• Besonderheiten

• Dispatcher arbeitet synchron

• Dispatcher berücksichtigt Abhängigkeiten zw. Stores

• waitFor-Methode

• Erkennt zirkuläre Abhängigkeiten

• Implementierung von FB verfügbar

Herbstcampus 2015 – Flux Application Architecture 50

Flux im Detail

View

Action API

Dispatcher

ACTION_CONSTANT,

{PAYLOAD}

Store

Dispatch {PAYLOAD}

Business logic based on action

& payload

emit change event

Update view and

children

Herbstcampus 2015 – Flux Application Architecture 51

Flux - Store

• Application state• Domain-spezifische Daten

• View state

• Businesslogik

• Registriert sich am Dispatcher

• Benachrichtigt Views (über Events)

Herbstcampus 2015 – Flux Application Architecture 52

Flux - Store

• != Model in MVC• View state

• N Domänenobjekte

• Datenfluss:

Controller-View

Store

emit event request state

Herbstcampus 2015 – Flux Application Architecture 53

Flux - Store

class SessionStore extends EventEmitter {

constructor() {

super();

this.loggedUser = null;

this.loading = false;

}

onLogin(data){

this.loading = false;

this.loggedUser = data.userName;

this.emit("change");

}

onLoad(){

this.loading = true;

this.emit("change");

}

}

Herbstcampus 2015 – Flux Application Architecture 54

Flux - Store

var sessionStore = new SessionStore();

AppDispatcher.register(function (action) {

switch(action.actionType){

case SessionStoreConstants.LOGIN:

sessionStore.onLogin(action.data);

break;

...

}

});

• Store registrieren

Herbstcampus 2015 – Flux Application Architecture 55

Flux - Store

• Besonderheiten

• Stores nur über Actions veränderbar

• Keine setter (konsistenter Status)

• Stores sollen synchron sein

• Keine API-Calls

• Einfacher Datenfluss!

• Umgang mit abgeleiteten Daten (derived data)

• Frage an viele Domänenobjekte (z.B. FB-Chat)

Herbstcampus 2015 – Flux Application Architecture 56

Flux

• Wie skaliert Flux?

ActionStore View

View

View

View

Store

Store

Store

Action

Action

Action

Dispatcher

Herbstcampus 2015 – Flux Application Architecture 57

Flux

• Wie skaliert Flux?

ActionStore View

View

View

View

Store

Store

Store

Action

Action

Action

Dispatcher

Herbstcampus 2015 – Flux Application Architecture 58

Flux ohne ReactJS

Herbstcampus 2015 – Flux Application Architecture 59

Flux ohne ReactJS

• Flux in anderen Technologien / Frameworks• Swift

• AngularJS

• Backbone

• …

• Framework auf Framework…

• Stores sagen nicht, was sich geändert hat• ReactJs-Virtual-DOM-Diff

Universal JavaScript

Herbstcampus 2015 – Flux Application Architecture 60

Lösung für alles?

Herbstcampus 2015 – Flux Application Architecture 61

Lösung für alles? (1/2)

• Fluxs‘ Stärken• Viele Views, kein direkter Domain-Model-Bezug

• N-Models darstellen

• In kleinen CRUD Anwendungen?• Views passen genau auf Models

• Passende View-Technologie

Herbstcampus 2015 – Flux Application Architecture 62

Lösung für alles? (2/2)

• Flux ist gut wenn…

• Daten sich häufig ändern

• Nachvollziehbarer Datenfluss

• Views komplex sind

• Vers. Datenquellen

• Logische Abhängigkeiten

• Views stark voneinander abhängen

• Wenn a, dann auch b und c

Herbstcampus 2015 – Flux Application Architecture 63

Kritik an Flux

• FB hat MVC falsch verstanden• Facebooks‘ MVC-Grafik zu komplex

• 1 Controller?

• View generiert Datenfluss?

• Zu viele Models?

• Flux ist nicht einfacher als MVC!• Boilerplate

• Aber: erzwingt vorhersehbaren Datenfluss

Herbstcampus 2015 – Flux Application Architecture 64

Kritik an Flux

• Flux ist CQRS • Datenisolation in Layer (Stores)

• Abfrage und

Manipulation

getrennt

Herbstcampus 2015 – Flux Application Architecture 65

Give Flux a try!

Vielen Dank!

Sven Kölpinopen knowledge GmbH

Herbstcampus 2015 – Flux Application Architecture 67

Flux Implementierungen

http://www.redspy.co.uk/

Herbstcampus 2015 – Flux Application Architecture 68

Flux Implementierungen

• Facebooks‘ Implementierung: Boilerplate!

• Vielzahl an Flux-Implementierungen

• Boilerplate minimieren

• Architektur erweitern & vereinfachen

• Isomorphic

• Serverside rendering

• Für andere Technologien als JS

Herbstcampus 2015 – Flux Application Architecture 69

Flux Implementierungen

• Reflux• Flux-Architektur verändern

• Fluxxor• Flux-Architektur beibehalten

Herbstcampus 2015 – Flux Application Architecture 70

Reflux

Herbstcampus 2015 – Flux Application Architecture 71

Reflux

• Ziele:• Architektur vereinfachen

• Flux funktionaler & dynamischer machen

• Gemeinsamkeiten mit Flux• Views

• Actions

• Stores

• Unidirektionaler Datenfluss

• Unterschiede• Kein Dispatcher

• Keine action creators

Herbstcampus 2015 – Flux Application Architecture 72

Reflux

• Kein Dispatcher

• Action = function

• Action = listenable

• Action = Dispatcher

• Stores subscribe actions

Action(listenable)

Store(listens)

View

Herbstcampus 2015 – Flux Application Architecture 73

Reflux

• Kein Dispatcher

• Action = function

• Action = listenable

• Action = Dispatcher

• Stores subscribe actions

Action(listenable)

Store(listens)

View

Keine Action-Konstanten

Keine switch-statements

Funktionale

Programmierung

Stores can listen to Stores

Herbstcampus 2015 – Flux Application Architecture 74

Fluxxor

Herbstcampus 2015 – Flux Application Architecture 75

Fluxxor

• Folgt exaktem Flux-Architekturvorschlag

• Mindert Boilerplate-Code

Herbstcampus 2015 – Flux Application Architecture 76

Fluxxor

Action Dispatcher Store View

Herbstcampus 2015 – Flux Application Architecture 77

Fluxxor

Action Dispatcher Store View

var SessionStore = Fluxxor.createStore({

initialize() {

this.loggedUser = null;

this.bindActions(

"LOGIN", this.onLogin

);

},

onLogin(userName){

this.loggedUser = userName;

this.emit("change");

}

});

Herbstcampus 2015 – Flux Application Architecture 78

Fluxxor

var SessionActions = {

login(userName) {

//...

this

.dispatch("LOGIN",userName);

}

};

Action Dispatcher Store View

var SessionStore = Fluxxor.createStore({

initialize() {

this.loggedUser = null;

this.bindActions(

"LOGIN", this.onLogin

);

},

onLogin(userName){

this.loggedUser = userName;

this.emit("change");

}

});

Herbstcampus 2015 – Flux Application Architecture 79

Fluxxor

var SessionActions = {

login(userName) {

//...

this

.dispatch("LOGIN",userName);

}

};

Action Disp. Store View

var SessionStore = Fluxxor.createStore({

initialize() {

this.loggedUser = null;

this.bindActions(

"LOGIN", this.onLogin

);

},

onLogin(userName){

this.loggedUser = userName;

this.emit("change");

}

});

var LoginView = React.createClass({

mixins: [Fluxxor.StoreWatchMixin("SessionStore")],

getStateFromFlux() {

var store = this.getFlux().store("SessionStore");

return {

loginState: store.loggedUser

};

},

onLogin() {

this.getFlux().actions.SessionActions.login();

},

render() {

return (

<button onClick={this.onLogin}/>

);

}

});