One-Way-Data-Binding, Two-Way-Data-Binding und Virtual DOM Diff

model-view

Diesen Begriffen begegnet man immer wieder und den meisten dürfte bekannt sein, dass es dabei um Datenverarbeitung in Client-Applikationen geht. Genau genommen um die Verbindung zwischen Daten und dem UI. Aber worum handelt es sich bei diesen Begriffen genau? Stehen sie in Zusammenhang und kann man sie vergleichen? Gibt es eine „beste“ Methodik? Wenn ja, welche? Wann sollte man was verwenden?

Um diese Fragen beantworten zu können, möchte ich einen Überblick über die Begriffe verschaffen.

One-Way-Binding

Bei diesem bisher weit verbreiteten Vorgehen werden Daten unidirektional weitergegeben. Änderungen dieser Daten werden demzufolge nur manuell über Events und Methoden an andere Komponenten weitergegeben oder im Model geändert. Eine Änderung im Model hat nicht automatisch eine Anpassung der View zur Folge. Andersrum müssen Änderungen der Daten in der View auch dem Model mitgeteilt werden. Dies wird unter anderem auch „Data-down-Actions-up“ genannt.

One-Way-Binding

 

Two-Way-Binding

Die Daten in einem Model und ihre Ausgabe im UI sind bidirektional verknüpft. Technisch gesehen werden Daten quasi als Referenz auf das Model an Komponenten einer View weitergegeben. Demzufolge passt sich das UI an, wenn sich diese Daten ändern. Andersrum werden die Daten eines Models aktualisiert, wenn das UI vom Nutzer z.B. durch Eingabe in ein Input-Feld verändert wird.

Änderungen der Daten treten also überall in Kraft, wo das Model verwendet wird. Das Ergebnis einer Änderung ist sofort und ohne manuelles Eingreifen applikationsweit sichtbar. Da die Daten direkt im Model geändert werden, bleiben sie immer konsistent. Entsprechende Event-Listener können auf die Änderung reagieren und Operationen ausführen, wie z.B.: Sortierung, Filter oder die De- / Aktivierung von Features.

Two-Way-Binding

 

Um das Prinzip zu verstehen, hier eine gute Demo-Seite, die Two-Way-Binding anhand einiger Frameworks und sogar nativem JS deutlich macht.

Große Frameworks wie Angular.js und Ember.js bringen eine eigene Implementierung dieses Konzepts bereits mit und nehmen einem somit viel Arbeit ab. Des Weiteren habe ich weiter unten ein paar Tools / Libraries aufgeführt.

Virtual DOM Diff

Gleich vorweg: das wohl bisher beste Beispiel für die Umsetzung eines V-DOM bietet React.

Der virtuelle DOM ist ein leichtgewichtige abstrakte Kopie des echten DOM. Ein Teil der Baumstruktur wird nachgebildet und kann beliebig verändert werden ohne Einfluss auf den echten DOM zu nehmen. Nachdem Änderungen vorgenommen worden sind, können diese einfach mit Hilfe eines Updates auf den richtigen DOM übertragen werden. Dieser Vorgang wird Patch genannt. Dabei werden Abweichungen durch einen Vergleich gefunden und die entsprechenden Stellen ersetzt und neu gerendert, wodurch sich das UI anpasst.

Die Manipulation des DOM via V-DOM ist deutlich schneller im Vergleich zu herkömmlicher DOM-Manipulation, da nur am abstrakten Abbild gearbeitet wird bis es ein Update des DOM gibt.

Damit das überhaupt passieren kann braucht es den sogenannten Virtual DOM Diff, den Vergleich vom DOM mit dem virtuellen DOM. Der Virtual DOM wird direkt im Client oder auf einem Server aufgebaut und bei einem Update mit dem DOM über einen Algorithmus verglichen. Anschließend wird ein Neu-Rendern des DOM angestoßen. Wenige, gezielte Updates beschleunigen den Vorgang zusätzlich.

Virtual-DOM

 

Es gibt zwei gängige Methoden, um Änderungen festzustellen:

a) Dirty Checking: im Intervall wird rekursiv auf Veränderungen in Werten der Datenstruktur geprüft. Da rekursiv gesucht wird, kann dies bei hoher Komplexität sehr langsam werden.
Der Diff-Algorithmus von React vergleicht beispielsweise Level für Level via Dirty-Checking.

b) Durch Observer: In der Baumstruktur werden Zustandsänderungen überwacht. Nachdem via Diff-Algorithmus geänderte Werte und Stellen ermittelt wurden, wird das DOM-Update gezielt und gebündelt ausgeführt.

Was sind also die wichtigsten Punkte für Effizienz?

  • gute Diff-Algorithmen
  • Schreib- und Lese-Vorgänge auf den DOM zusammenfassen
  • gezielte Updates mit Beschränkung auf Sub-Trees

Welche Vor- und Nachteile sehe ich?

One-Way-Binding

Pro:

  • übersichtliche Datenhaltung, da sie nur in eine Richtung fließen
  • dadurch leichteres Debugging
  • keine unkontrollierte Verkettung von Operationen durch Observer / Event-Listener auf Daten-Objekten

Contra:

  • keine automatische Anpassung von Daten im Model, anderen Komponenten, des UI

Two-Way-Bindung

Pro:

  • direkte Anbindung der Daten an das UI => Datenkonsistenz
  • keine programmatische Änderung von Daten im Model nötig
  • bei gleichen Daten an vielen Stellen der Applikation wird deren Ausgabe / Verarbeitung vereinfacht

Contra:

  • implizite Änderungen des Models / des UI kann zu schwerer Performance-Last und Nebeneffekten führen
  • durch viele Änderungen im DOM können weiter Performance-Probleme entstehen
  • hohe Komplexität durch „durchschleifen“ von Daten über mehrere Applikations-Ebenen

V-DOM

Pro:

  • weniger Interaktion mit echtem DOM
  • kontrollierte Anpassung von Teilbereichen, Updates werden zusammengefasst
  • weniger unkontrollierte Verkettung von Operationen durch Observer / Event-Listener auf DOM-Änderungen
  • je nach Komplexität weniger Verzögerung durch CSS-Renderings

Contra:

  • Diff-Algorithmus nötig => muss performant sein, andernfalls verschwindet Vorteil
  • Dirty Checking kann langsam sein

Fazit

One-Way-Bindings ermöglichen mehr Kontrolle über den Datenfluss, bringen aber zugleich je nach Tool einen höheren Implementierungsaufwand mit sich. Dafür wird man mit einer hohen Performance belohnt.

Im Gegensatz dazu nimmt einem das Two-Way-Binding viel Arbeit und Implementierung ab, verlangt dafür im Gegenzug allerdings eine saubere Daten-Architektur mit einem Setup / einer Implementierung, welche einen strukturierten Datenfluss ohne unerwünschte Nebeneffekte ermöglicht und dabei performant bleibt. Bei zunehmender Applikationsgröße allerdings leidet die Performance und das Debuggen fällt schwer.

Ein Virtual-DOM Diff unterstützt darin die Verknüpfung von Daten und UI für DOM-Anpassungen so effizient wie möglich zu gestalten. Durch einen guten Diff-Algorithmus können die Änderungen im DOM gebündelt und aufs Nötigste reduziert erfolgen. Datenanpassungen können so auch leicht in einer Datenbank persistiert werden.

Letztendlich hängt die Wahl der ein oder anderen Methode unter anderem vom Projekt-Setup, der technischen Umgebung und z.B. der Bewertung von Performance-Faktoren ab.

Ein Ausblick in die Zukunft

One-Way-Binding vs. Two-Way-Binding ist auch in Angular und Ember ein großes Thema. Die neue Tendenz: One-Way-Binding, um Performance-Problemen frühzeitig entgegenzuwirken und Datenänderungen im Model kontrolliert vornehmen zu können.

Empfehlenswerte Tools

Two-Way-Binding
jquerymy.js
agility.js
bind.js

Virtual DOM
mithril.js
virtual-dom

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>