wiki:UniPhi/MVC-Framework

MVC-Framework für UniPhi

Auf dieser Seite werden die einzusetzenden Libraries für UniPhi diskutiert. Diese Wiki-Seite ist am 31. Mai 2014 als "Zusammenschrieb" meiner Browserhistory nach einem 48-Stündigen Entwicklungsmarathon (eher einem Surf-Marathon) von Sven entstanden. Um die Diskussion hier voranzutreiben, soll sie aber von jedem erweitert werden.

Existierende Software

Grundsätzlich gab es natürlich die Möglichkeit, auf existierende Software aufzubauen. Gut hätte sich die Reddit-Betreibersoftware angeboten. Wir haben uns zumindest stark von den Seiten, mit denen UniPhi Features teilt, inspirieren lassen.

Zu Reddit hab ich, recht informativ, gelesen:Blog: Reddits database has two tables (reddit, ycombinator)

Thomas hat Reddit auf POKAL2 irgendwo installiert (vtl. #797, #796). Insgesamt hab ich Reddit bislang quasi nicht gekannt, aber die letzten Tage sehr viel Zeit auf http://reddit.com verbracht ;-)

Client-Framework und Templating: Erster Überblick

UniPhi sollte sich als moderne Webbrowser-Anwendung möglichst flüssig anfühlen, daher wollten wir uns für ein client-seitiges Model-View-Controller-Framework entscheiden (siehe http://todomvc.com/ für eine gute Übersicht). Ich diskutier hier die verbreitesten mit Vorweggriff auf Begriffe, die erst in den nächsten Abschnitten erläutert werden. Es gibt im Internet sehr viele Vergleiche zwischen diesen Frameworks (am besten The Top 10 JS MVC-Frameworks reviewed, aber auch etwa dieser Blogeintrag). Die interessantesten Frameworks sind sortiert nach ihrem Umfang (subjektiv):

  • Backbone.js:
    • Sehr klein (stets mit underscore.js), aber auch nur geringer Funktionsumfang (Event-Binding). Ein Router ist aber drin. Läuft mit Rendr sehr einfach auf Server.
    • Hübsche Models und einfaches Syncing
    • Problem: kein Data-Binding!
  • Knockout.js:
    • Scheint die dünnste Library mit Double-Bind zu sein
    • hübsche Templates mit unobstructive data-bind-Attributen.
    • Läuft problemlos auf Server.
    • Knockback: Backbone.js+Knockout.js erlaubt hübsches Backbone-ORM zusammen mit Data-Binding.
  • React (Facebook): Virtual DOM (HTML und JS direkt verzahnt, Preprocessing nötig), Server Rendering. Sehr hässlich.
  • Ember.js: Hat die einladenste Website
  • AngularJS: Monster-Framework, sehr groß
    • Templates sind nicht unobstructive.
    • Kann auf gar keinen Fall Templates auf Server rendern.
    • Sehr hohe Lernkurve (ziemlich umfangreich), aber auch sehr mächtig (deklaratives Programmieren). Wird auch oft als Langsam bezeichnet (lange Ladezeit - tatsächlich ist Ember wohl sogar größer)

Wichtige Stichpunkte bei den Fähigkeiten von Client-Frameworks sind:

  • 2-Way-Data-Binding (auch: Double-Bind/Reverse-Bind): Alle Frameworks können Daten zu HTML machen (Templating). Ist das Binden von Daten an den DOM aber auch möglich (Rückwärts-Bind)? Das erspart enorm das Event-Handling (Erklärung bei AngularJS).
  • Client-Side Modell-Verifikation: Macht den Umgang mit Usereingaben wesentlich einfacher (ersetzt aber nicht Server-Side-Verifikation)

Es gibt verschiedene verbreitete Template-Lösungen (ich liste nur welche mit echter Trennung von HTML-Template und Code auf, keine String-Ersetzungen):

Zusammenfassung Client-MVC: Die Entscheidung kann nur in Hinblick auf einen reibungslosen Ablauf mit der Serverkomponente gefällt werden. Siehe daher weiter unten.

Datenbank

Wir wollen uns für eine NoSQL-Datenbank entscheiden, um die Anwendung flexibel weiterentwickeln zu können. In der Diskussion standen Neo4j (Graphbasiert, JSON), MongoDB (Dokumentenorientiert, JSON), Redis (Key-Value), aber auch (ITP-Hosting) PostgreSQL (hat mittlerweile JSON-Speicher), ElasticSearch (lesenswert: Elasticsearch vs. Mongodb - für Mongo). Für eine sehr allgemeine Übersicht siehe http://nosql-database.org/.

Argumente gegen Neo4j (ich war bislang eigentlich am ehesten für Neo4j!):

  • Die Pflege des Suchindexes ist sehr aufwändig und nach bestehenden Daten fast nicht mehr möglich. Volltext-Suche gibt es nur mit der alten API.
  • Die Administration finde ich sehr umständlich (man findet bei großen Datenbanken kaum mehr seine Knoten wieder)
  • Die Community/Doku lässt sehr zu wünschen übrig (hab bislang Neo4py verwendet und auch da ist die Doku schlecht)

Ich persönlich finde MongoDB mittlerweile am überzeugensten. Argumente:

  • Javascript-Schnittstelle passt hervorragend zum JS-Charakter des Gesamtprojektes.
  • Der/die DB-Index/Suche wirkt der Doku nach sehr ausgereift. Man kann einfach und schnell neue Indizes anlegen.
  • When to Redis, When to Mongodb?: Klar für MongoDB ist Querying (und damit Suche!) und mehr Struktur.
  • Man kommt von SQL leicht zu MongoDB.
  • Das GridFS ist für Uploads interessant (falls wir Files hosten). Mit nginx-gridfs gibt es auch Plugins für Webserver zum schnellen Ausliefern (geht aber nicht reibungslos)
  • Die Community ist sehr verbreitet. MongoDB ist sehr verbreitet als Backend zu NodeJS-Anwendungen. Es gibt viele Tutorials, die meisten Client-MVCs und NodeJS-Frameworks sind dafür ausgelegt.

Ich hab in dem Zusammenhang Ende Mai auch nochmal nach RDF-Storages und Object Graph Mappers für MongoDB Ausschau gehalten. Es gibt etwa tripod-node oder Slideshare: Mongodb as high performance graph database.

MongoDB-Bindings zu Node.JS (Docs: nodejs Drivers):

Demos/Tutorials um mit Mongoose anzufangen:

Wichtig bei Bridges von MongoDB direkt zum Client ist, welche Access Policies sie ermöglichen: Kann man z.B. willkürlichen Zugriff auf User-Objekte unterbinden? Auf welchem Level lassen sich Anfragen unterbinden? Fast kein Framework scheint sich damit zu beschäftigen, dass man überhaupt nur bestimmt aussehende Anfragen durchlassen kann! Sonst öffnet man komplexen DDOS-artigen Anfragen Tür und Tor.

Bridges von MongoDB zu Toolkits:

  • backbone-orm: Polystore-ORM für Backbone.JS (hässliche Modells, Relationale Features). Sehr gut: Server-Client sind gleich behandelbar! Löst die Client/Server-Schranke.
  • angular-bridge: Hässliche Models auf dem Server, aber erlaubt direkte Anfragen vom Client.

Zusammenfassung Datenbanken: Ich bin für MongoDB mit moongoose. Das würd ich am liebsten mit Backbone verheiraten, auch wenn es dafür keine Library gibt (braucht es vermutlich auch nicht, da die Unterschiede marginal sind).

Server-Framework

Serverseitig stand zur Wahl ziemlich schnell Node.js, um keine Sprachbarriere zu haben. In der einfachstmöglichen Variante ist die Serverkomponente nur ein minimaler Wrapper der Datenbank (die meisten NoSQL-DBs haben REST-Interfaces, von denen man große Teile hätte an den Client durchreichen können). Tatsächlich wird man nicht herumkommen, auf der Serverseite Modelle zu definieren (Objekt-Dokument-Mapper, ODM). Um keine doppelte Modellbildung (Redundanz!) auf Server- und Clientseite zu haben, sollten das MVC-Frameworks serverseitig wiederverwendbar sein. Siehe http://nodeframework.com/ für eine Übersicht an Web-Frameworks.

Siehe auch weiter unten zum Node-Ökosystem und Hilfs-Libraries, die man kennen sollte. Ansonsten zum Einstieg in Node:

Bei Frameworks interessieren mich derzeit nicht nur REST-Router. Die gibt es wie Sand am Meer, lösen aber nicht das Problem, dass auf Client und Server redundant Modelle definiert werden müssen (Redundanzproblem). Außerdem ignorieren die meisten Frameworks auch das Problem, dass der Server keine statischen Seiten generieren kann (SEO/Zugänglichkeit). Es gibt Frameworks, die das mit einem simulierten Browser auf dem Server angehen, die sind aber (u.a. aus Performancegründen) nicht ernst zu nehmen. Auch sollte eine Framework das URL-Routing auf Client und Server gleichermaßen behandeln.

Diese Frameworks sind eher Middleware und kamen am ehesten in Frage:

  • Rendr: Vielversprechend!
    • Erlaubt die hübschen BackboneJS-Modelle auf dem Server zu nutzen.
    • Ermöglicht statische Seiten. Routing?

Dann gibt es noch Full-Stack-Frameworks, die Client+Serverside-Frameworks sind. Die beiden folgenden Vertreter haben gemeinsam, dass sie Echtzeit-Synchronisation von Anfang an drin haben, was das Gegenteil eines abgetrennten REST-Interfaces ist:

  • derbyjs: Sehr vielversprechend, hat viele Dinge drin die ich sehr gut finde:
    • Generiert statische Seiten. Gleiche Templates und Modells auf Client/Server
    • Double View-Bindings frei Haus. Vor allem aber: Echtzeitkollaboration frei Haus
    • Kehrseite: Dafür sehr viel Zusatzcode und braucht eine Redis-Datenbank (!!). Sehr umfangreicher Code.
    • Verwendet u.a. ShareJS, Racer, Googles BrowserChannel (statt Websockets wegen Transactional Operations), Stylus, Redis, MongoDB. Will ORM.
    • Problem: Ökosystem (User-Auth, etc.) ist bereits für Version 0.6 ausgelegt, die sehr bald entwickelt wird.
  • MeteorJS: Viel verbreiteter als DerbyJS
    • Verwendet eigene NodeJS-Kopie (ähnlich PhantomJS) und eigenes Ökosystem
    • Interessant: Hot Code Pushes
    • Templating: Spacebars (Forkt Handlebars), kann 2-Wege-Datenbinding (sehr subtil im Code) und hat dafür Syntaxeinschränkungen (HTML first)
    • Kehrseite: Verwendet Fiber und hat ein eigenes Ökosystem nicht auf NPM-Basis (meteor wie make, Ökosystem heißt Atmosphere und ist noch nicht fertig). Geht nicht den NodeJS-Weg und ist ggf. schlechter mit anderen Packeten vereinbar
    • Best Practices Code-Struktur
    • Wird wesentlich mehr weiterentwickelt als Derby, größere Community
    • Es scheint eine Rechteverwaltung zu geben, ein Client kann also nicht einfach z.B. eine Userdb verändern. Aber es gibt keine Modell-Klassen und weder auf Client noch Server eine fertige Modellverifikation.
    • Routing ist nicht zentral drin, aber iron-router ist der Defaktostandard. Ironischerweise findet das Routing quasi nur auf dem Client statt.
    • Problem: Kann Templates nicht serverseitig rendern! Oft wird meteor-handlebars-server als Lösung genannt, das ist aber falsch, denn damit kann man nur HTML-Mails formatieren und so. fast-render wird als Alternative gelobt (ist aber keine - da werden nur JSON-Daten beim laden der Seite gepusht). Es ist auch nicht absehbar, dass das Feature bald kommt und die ausgeführte Codebase scheint so abstrakt zu sein, dass ich glaube dass man das im Moment nicht leicht reinkriegt.
    • Sehr alternatives Code-Strukturierungs-Konzept - sehr viel Abstraktion vom Dateisystem weg, dafür auch sehr bequem. Es ist beabsichtigt, dass Client und Server Code teilen
    • Die Installation ist sehr umfangreich, da NodeJS und ein eingebettetes MongoDB mitgeliefert werden: meteor gönnt sich 127MB Installationsverzeichnis. Projektverzeichnisse sind ohne Mist 500MB groß, davon gehen 99% auf absurd große MongoDB-Caches. Da dauert es auch mal ein paar Sekunden, bis der Entwicklungsserver (mit eingebettetem MongoDB-Server) gestartet ist.
    • Es gibt Beispielprojekte, die man sehr bequem installieren kann und die ziemlich hilfreich sind

DerbyJs und MeteorJS sind noch nicht sehr ausgereift bzw. unterliegen starken API-Änderungen. MeteorJS ist aber deutlich brauchbarer als DerbyJS.

Diese Frameworks hab ich mir angeschaut und haben mich nicht überzeugt:

  • TotalJS
    • Verspricht AngularJS und MongoDB zu verheiraten, löst aber nicht das Redundanzproblem und kann keine statischen Seiten.
    • Models sind wahrscheinlich hässlich
  • RhapsodyJS, TowerJS hat mich nicht überzeugt (da scheint wohl jeder Hinz und Kunz sein Framework zu schreiben)
  • http://www.senchalabs.org/connect/: Connect, hat mich zunächst nicht überzeugt, ist aber von Sencha, die glaub ich auch Backbone/Underscore gemacht haben.
  • Backnode: Backbone und Connect, als Experiment gekennzeichnet. Nicht näher angeschaut
  • http://mean.io/: Vielversprechend: AngularJS zusammen mit MongoDB und Express/Node. Bloß weder Server-side Rendering noch irgendwas anderes wichtiges. Und eine schlechte Doku. Bloß das Logo ist hübsch.
  • http://deployd.com/: Extrem krasses Video - scheint ein tolles Framework zu sein. Bloß war gestern die Docs-Seite offline. Heute ist sie wieder online. Noch mal Anschauen!
  • Hoodie geht in die gleiche Richtung wie Deployd. Als Offline first und noBackend ist das aber nicht unser Ding.

Zusammenfassung Server: Ich würde am liebsten etwas leichtgewichtiges bevorzugen, oder einer von DerbyJS/MeteorJS, wobei DerbyJS ausgeschieden ist.

Node-Ökosystem

Ich hab bislang nicht mit Nodejs gearbeitet, daher kenne ich das Ökosystem an Libraries dort kaum. Hier soll es daher etwas dokumentiert werden, um die Übersicht leichter zu halten:

Sonstige Libraries, die mir über den Weg gelaufen sind und hilfreich sind:

  • hashids: Short hashes from numbers (like Youtube and Bitly) vllt. für URLs nutzen

Zu Metasprachen/zu kompilierenden Sprachen:

  • Coffeescript: Will ich eigentlich weder Client- noch Serverseitig nutzen
  • LESS: Gerne (find ich hilfreich)

Zusammenfassung Ökosystem: Hier gibt es nicht viel zu sagen. Die meisten Libraries gehen von einer strengen Client/Server-Trennung aus, was ich gerne anders machen möchte.

Last modified 3 years ago Last modified on Jun 1, 2014 7:23:46 AM