Zum Inhalt springen
_CORE
KI & Agentensysteme Unternehmensinformationssysteme Cloud & Platform Engineering Datenplattform & Integration Sicherheit & Compliance QA, Testing & Observability IoT, Automatisierung & Robotik Mobile & Digitale Produkte Banken & Finanzen Versicherungen Öffentliche Verwaltung Verteidigung & Sicherheit Gesundheitswesen Energie & Versorgung Telko & Medien Industrie & Fertigung Logistik & E-Commerce Retail & Treueprogramme
Referenzen Technologien Blog Know-how Tools
Über uns Zusammenarbeit Karriere
CS EN DE
Lassen Sie uns sprechen

Backbone.js — endlich strukturiertes JavaScript

08. 11. 2011 5 Min. Lesezeit CORE SYSTEMSdevelopment
Backbone.js — endlich strukturiertes JavaScript

Unsere JavaScript-Dateien wachsen stetig. Was als ein paar Zeilen jQuery für Formularvalidierung und AJAX-Aufrufe begann, hat sich in Tausende Zeilen unübersichtlichen Code verwandelt. jQuery ist hervorragend für DOM-Manipulation, bietet aber keinerlei Struktur für die Organisation von Anwendungslogik. Backbone.js von Jeremy Ashkenas löst genau dieses Problem — es bringt Models, Collections, Views und einen Router in die Frontend-Entwicklung.

Warum wir Struktur im Frontend brauchen

Vor drei Jahren war ein typisches Web-Frontend einfach — der Server renderte HTML, jQuery fügte ein paar interaktive Effekte hinzu. Doch mit steigenden Nutzererwartungen wurde das Frontend immer komplexer. Gmail, Google Maps, Facebook — diese Anwendungen laufen überwiegend im Browser, und der Server dient hauptsächlich als API. Wenn man Tausende Zeilen JavaScript ohne klare Struktur hat, wird jede Änderung zum Risiko.

Das Problem ist nicht jQuery — jQuery tut genau das, wofür es konzipiert wurde. Das Problem ist das Fehlen architektonischer Muster im Frontend. Auf dem Server haben wir MVC (Spring MVC, Rails, Django), Dependency Injection, einen Service Layer. Im Frontend hatten wir eine Datei voller $()-Selektoren und anonymer Funktionen. Backbone.js ist der erste weit verbreitete Versuch, diesen Zustand zu ändern.

Models

Ein Backbone Model repräsentiert eine Datenentität — einen Benutzer, ein Produkt, eine Bestellung. Ein Model enthält Attribute (Daten), Validierungslogik und Methoden zur Kommunikation mit dem Server (save, fetch, destroy). Die Schlüsseleigenschaft ist, dass ein Model Events auslöst, wenn sich Attribute ändern — wenn sich der Name eines Benutzers ändert, aktualisieren sich alle Views, die diesen Namen anzeigen, automatisch.

Dies ist das grundlegende Prinzip des Data Binding — das Model ist die einzige Quelle der Wahrheit und Views reagieren darauf. In der jQuery-Welt haben wir Daten typischerweise im DOM gespeichert (in Attributen, in Elementtexten) und JavaScript las von dort und schrieb dorthin. Mit Backbone sind Models von der Darstellung getrennt. Den Namen eines Benutzers ändern? Ändern Sie das Model-Attribut und alle Views aktualisieren sich selbst.

Models abstrahieren auch die Kommunikation mit dem Server. Backbone setzt ein RESTful JSON API voraus. Der Aufruf von model.save() sendet einen POST- oder PUT-Request an den Server, model.fetch() lädt Daten per GET, model.destroy() sendet DELETE. Die URL wird automatisch aus der Root-URL der Collection und der Model-ID abgeleitet. Dieser Convention-over-Configuration-Ansatz reduziert Boilerplate-Code erheblich.

Collections

Eine Collection ist eine geordnete Menge von Models desselben Typs. Eine Collection von Benutzern, eine Collection von Produkten, eine Collection von Bestellungen. Collections bieten Methoden zum Hinzufügen, Entfernen, Filtern und Sortieren von Models. Dank der Integration mit Underscore.js (Backbones Geschwisterbibliothek) steht ein umfangreicher Satz funktionaler Methoden zur Verfügung — map, filter, reduce, find, sortBy, groupBy.

Genau wie Models lösen Collections Events aus — add, remove, reset, sort. Ein View, der eine Produktliste anzeigt, kann auf diese Events lauschen und sich automatisch neu rendern, wenn sich Daten ändern. Ein neues Produkt hinzufügen? Die Collection löst ein add-Event aus, der View fügt eine neue Zeile zur Liste hinzu. Ein Produkt löschen? Das remove-Event, der View entfernt die Zeile. Keine manuelle DOM-Manipulation.

Views

Ein Backbone View ist für das Rendern von HTML und die Verarbeitung von Benutzerinteraktionen verantwortlich. Jeder View ist mit einem DOM-Element verknüpft und kann auf DOM-Events (click, submit, keyup) innerhalb seines Elements lauschen. Ein View lauscht typischerweise auf Model-Änderungen und rendert sich bei Änderungen neu.

Backbone schreibt kein Template-System vor — man kann alles verwenden, von einfachen String-Templates über Underscore-Templates bis hin zu Handlebars oder Mustache. Wir verwenden Handlebars, weil es Logik-Helper und Partials bietet, ohne komplexe Logik in Templates zuzulassen (Separation of Concerns). Der View bereitet Daten aus dem Model vor, übergibt sie an das Template und fügt das resultierende HTML in das DOM ein.

Ein wichtiges Detail — Backbone Views stellen kein automatisch effizientes Re-Rendering sicher. Wenn man render() aufruft, wird der gesamte View-Inhalt durch neues HTML ersetzt. Für einfache Views ist das kein Problem, aber für komplexe Listen mit Dutzenden von Elementen kann es langsam sein. Optimierung erfordert granularere Updates — anstatt die gesamte Liste neu zu rendern, nur die geänderte Zeile aktualisieren. Dies ist ein Bereich, in dem Backbone die Entscheidung dem Entwickler überlässt.

Router

Der Backbone Router bildet URL-Hash-Fragmente auf Funktionen ab. Wenn ein Benutzer zu #users/123 navigiert, ruft der Router eine Funktion auf, die den Benutzer mit der ID 123 lädt und den entsprechenden View anzeigt. Dies ermöglicht die Erstellung einer Single-Page-Anwendung mit voller Unterstützung für Browserverlauf und Lesezeichen. Der Benutzer kann Vor- und Zurück-Tasten verwenden, URLs teilen und die Seite aktualisieren, ohne den Zustand zu verlieren.

Der Router ist einfacher als Router in serverseitigen Frameworks — keine Middleware, keine benannten Routen, kein Nesting. Für komplexere Anwendungen kann das eine Einschränkung sein, und wir sehen oft Entwickler, die ihre eigene Abstraktion über dem Backbone Router erstellen. Aber für den grundlegenden Anwendungsfall ist der eingebaute Router ausreichend.

Unsere Backbone-Architektur

Nach mehreren Projekten haben wir eine Standardarchitektur für Backbone-Anwendungen entwickelt. An der Spitze steht ein Application-Objekt, das den Router und gemeinsame Services initialisiert. Der Router delegiert an Controller-Objekte (Backbone hat diese nicht nativ — wir haben sie hinzugefügt), die das Laden von Daten und die Erstellung von Views koordinieren. Views sind hierarchisch — der Haupt-Layout-View enthält Regionen und jede Region beherbergt einen spezifischen Unter-View.

Für die Kommunikation zwischen unabhängigen Views verwenden wir einen Event Aggregator — einen globalen Event-Bus, auf dem Views Events auslösen und darauf lauschen können. Dies verhindert direkte Abhängigkeiten zwischen Views und macht den Code flexibler. Beispielsweise ruft der Warenkorb-View nicht direkt den Produktkatalog-View auf — stattdessen löst er ein product:add-to-cart-Event aus und der Warenkorb lauscht darauf.

Diese Architektur ist inspiriert vom Marionette.js-Framework von Derrick Bailey, das Konzepte wie Regions, Layouts und Composite Views zu Backbone hinzufügt. Wir erwägen seine vollständige Übernahme für unser nächstes Projekt.

Testing

Backbone-Code ist gut testbar, da Models und Collections nicht vom DOM abhängen. Man kann Model-Validierung, berechnete Attribute und API-Interaktion mit Unit-Tests ohne Browser testen. Zum Testen verwenden wir Jasmine — ein BDD-Framework für JavaScript mit klarer Syntax (describe, it, expect). Für Views testen wir, ob sie HTML korrekt rendern und auf Events reagieren.

API-Aufrufe mocken wir mit Sinon.js FakeServer, der AJAX-Requests abfängt und vorbereitete Antworten zurückgibt. Dies ermöglicht das Testen des gesamten Flows — vom Laden der Daten über das Model bis zur Anzeige im View — ohne echten Server.

Grenzen von Backbone

Backbone ist bewusst minimalistisch. Jeremy Ashkenas hat es als „minimalen Werkzeugsatz zur Strukturierung von JavaScript” konzipiert, nicht als vollständiges Framework. Das bedeutet, dass man viele Dinge selbst lösen muss — Memory Management (Abmelden von Event-Listenern beim Zerstören von Views), effizientes Listen-Rendering, Kommunikation zwischen Views, Lazy Loading von Modulen. Für jedes dieser Probleme gibt es Community-Lösungen, aber sie sind nicht Teil des Core-Frameworks.

Es ist auch wichtig zu beachten, dass Backbone nicht die einzige Option ist. Knockout.js bietet deklaratives Data Binding. Ember.js ist ein vollständigeres Framework mit Konventionen. Und am Horizont zeichnet sich AngularJS von Google ab, das einen radikal anderen Ansatz verspricht. Aber heute, im Herbst 2011, ist Backbone die ausgereifteste und am weitesten verbreitete Wahl für die Strukturierung von Frontend-JavaScript.

Fazit

Backbone.js bringt dringend benötigte Struktur in die Frontend-Entwicklung. Models, Collections, Views und Router sind die grundlegenden Bausteine, die es ermöglichen, eine wachsende JavaScript-Codebasis zu organisieren. Es ist keine Wunderwaffe — es erfordert Disziplin und ergänzende Bibliotheken — aber es ist ein enormer Schritt vorwärts gegenüber jQuery-Spaghetti. Wir empfehlen es jedem Team, das eine nicht-triviale Webanwendung entwickelt.

backbone.jsjavascriptmvc
Teilen:

CORE SYSTEMS

Wir bauen Kernsysteme und KI-Agenten, die den Betrieb am Laufen halten. 15 Jahre Erfahrung mit Enterprise-IT.

Brauchen Sie Hilfe bei der Implementierung?

Unsere Experten helfen Ihnen bei Design, Implementierung und Betrieb. Von der Architektur bis zur Produktion.

Kontaktieren Sie uns