Hinter den Kulissen – abiapp.net Blog https://blog.abiapp.net Abizeitung stressfrei organisieren Sat, 25 Feb 2017 16:28:06 +0000 de-DE hourly 1 https://wordpress.org/?v=5.2.13 Achtung Technik: Unsere Methode für Live-Updates https://blog.abiapp.net/js-models/ Thu, 20 Nov 2014 14:47:38 +0000 https://blog.abiapp.net/?p=116 Achtung, dies ist ein sehr technischer Beitrag, der nicht darauf ausgerichtet ist, für Laien verständlich zu sein. Wenn du dich nicht auskennst, kannst Du ihn natürlich trotzdem lesen – wir übernehmen aber keine Verantwortung :-) Bei technischen Fragen kannst du uns natürlich gern unter hallo@abiapp.net kontaktieren.

Kürzlich im abiapp.net-Changelog:

  • Fundamentale Überarbeitungen an unserer Technik, die dafür sorgen, dass noch mehr Dinge auf abiapp.net sich jetzt live ändern, ohne dass ihr die Seite neu laden müsst

Dahinter versteckt sich nicht weniger als die komplette Umstrukturierung und Neuimplementierung des beinahe kompletten JavaScript-Quelltextes von abiapp.net – ein Vorgang, der sich über einige Monate gestreckt hat. In diesem Beitrag wollen wir etwas mehr dazu erzählen und auch für die Technikinteressierten unter euch zeigen, wie man mit den neuen Techniken herumspielen kann. :)

Neben einigen typischen abiapp.net-UI-Werkzeugen wie den „fliegenden Namen“ im Adminbereich, editierbaren Feldern (die gelb hinterlegten) und dem automatischen Umleiten von Formularsendungen als AJAX-Request besteht der JavaScript-Code von abiapp.net hauptsächlich aus Zeilen, die unser Haupt-UI-Feature verantworten: Die Live-Änderungen. Jede veränderte Eigenschaft, jeder neue Kommentar, fast alles was bei abiapp.net passieren kann wird live bei allen Usern die online sind, angezeigt, ohne dass die Seite neu geladen werden muss.

Aktuell läuft diese Technik über sekündliche AJAX-Requests (auf mobilen Clients seltener; in Zukunft ist eine Implementierung per Websockets geplant). Bisher war das so implementiert, dass es für jede Seite, auf der sich etwas ändern konnte, eigenen Code gab. Die AJAX-Requests enthielten eine Beschreibung der Seite und der Server antwortete mit Änderungen, die seit der letzten Anfrage geschehen sind. Was zunächst am einfachsten war, entwickelte sich schnell zu einer gigantischen Menge an Fallunterscheidungen. Schnell war klar, dass dieses System eines der ersten war, dass einer gründlichen Überarbeitung unterzogen werden sollte. „js-models“ hieß unser git-Branch – und der Name ist Programm: Auf Serverseite setzen wir Django ein, das wie die meisten Datenbankabstraktionen mit sogenannten Models (abstrakten Beschreibungen der Datenstrukturen) gearbeitet wird – so gibt es bei uns beispielsweise Models für Personen, Kommentare, Umfragen, Umfrageoptionen und vieles mehr. Äquivalente zu diesen Models sind nun auch JavaScript-seitig im Einsatz.

Was heißt das? Der Einfachste Weg für dich, hier unter die Haube zu gucken, ist, in der Javascript-Konsole einfach mal objects einzugeben. Schon siehst du alle Objekte, die aktuell auf dieser Seite existieren – geordnet nach Model. Clientseitig sind hier alle bekannten Eigenschaften über auf der Seite vorhandene Objekte gespeichert. Diese Daten werden automatisch aus dem DOM der Seite beim Seitenaufbau generiert. Alle Objekte enthalten in einem data-object-HTML-Attribut ihr Model und in einem data-id-Attribut ihre ID. Die Javascript-Models sind in der Lage, aus den gerenderten Objekten ihre Eigenschaften aufzulesen und zu speichern. Das tolle: Das geht auch umgekehrt – jede Änderung an einer Eigenschaft wird sofort überall im DOM ebenfalls geändert. Mehr dazu gleich.

Zusätzlich zu Javascript-Models existieren nun auch Listen. Diese sind via lists (bzw lists_by_type) einsehbar. Auch sie werden anhand von Attributen wie data-list und data-filter beim Seitenaufbau initialisiert. Listen haben die Aufgabe, verschiedene Objekte eines Models aufzulisten. Dabei kann es Kriterien geben, nach denen die Objekte, die in dieser Liste aufgeführt werden, ausgewählt werden (bei Kommentaren auf einer Personenseite sollen zum Beispiel nur Kommentare zu dieser Person geführt werden). Auch die Anzeige der Elemente in einer bestimmten Reihenfolge ist möglich. Listen halten sich automatisch aktuell, neue oder geänderte Objekte, die in die Liste passen, werde der Liste hinzugefügt (wir nutzen dafür EJS als Implementierung für Javascript-Templates – die Javascript-Templates findest Du in <script type="text/template">-Tags im HTML-Quelltext). Gelöschte Objekte oder Objekte, die durch eine Änderung nicht mehr in die Liste gehören, werden aus der Liste entfernt. Auch die Sortierung wird immer aktuell gehalten. Selbstverständlich werden alle diese Änderungen automatisch einheitlich animiert.

Was bringen uns die ganzen Models nun? Zum ersten eine Vereinheitlichung und eine deutliche verbesserte Übersichtlichkeit der Codes. Aber vor allem bedeutet es für uns, dass wir jetzt viel einfacher und an viel mehr stellen simpel Dinge live aktualisieren können. Und das geht nun teilweise bis in die kleinsten Details: Ändert sich der Name einer Person, ändert sich die Beschriftung aller Links auf dieser Person bei allen Benutzern! Zudem ist es jetzt möglich, dem Server sehr einfach mitzuteilen, welche Informationen benötigt werden – auch das Senden von nur einzelnen geänderten Eigenschaften ist möglich und für die Zukunft vorgesehen – so spart man noch mehr Bandbreite.

Aber genug der Theorie – wie kannst Du nun damit herumspielen? Ganz einfach, wir erklären dir wie du lokal mit der Javascript-Konsole Daten verändern kannst. Keine Bange, beim Ausprobieren kannst du nichts kaputt machen – lokale Änderungen werden nicht zum Server gesendet. Zwei Funktionen regeln alles:

update_object(type, id, data, user)
Ändere Daten eines Objekts, das durch sein Model (type, z.B. 'comment') und id definiert wird. Wenn das Objekt aktuell nicht bekannt ist, wird es angelegt. type und id kannst du aus der oben genannten Variable objects herausfinden. data sollte ein Javascript-Objekt mit neuen Werten für Eigenschaften sein, die geändert werden sollen. user kannst du weglassen, du kannst aber auch ein Object im Format {'name':'Frank Nord'} angeben – an allen Stellen auf der Seite, an denen dieses Objekt nun erscheint oder verändert wird oder verschwindet (gefilterte Listen) wird erscheint nun kurz dieser Name.

remove_object(type, id, user)
Entferne ein Objekt komplett. Die Parameter sind die selben wie bei update_object, nur dass hier keine Daten übergeben werden. Das Objekt verschwindet hiermit an allen Stellen der Seite, an denen es Dargestellt wird sowie ebenfalls aus allen Listen.

Beispiele:
Gehe auf eine Personenseite, auf der Kommentare angezeigt werden. Such dir einen Kommentar heraus, sodass du seine id weißt. Jetzt stehen dir folgende Möglichkeiten offen (id jeweils ersetzen):

// Verändert den Text dieses Kommentars
update_object('comment', id, {'text': 'lalala'})

// Erstellt einen neuen Kommentar zu der Person des gewählten
update_object('comment', 42, {'text': 'Neuer Kommentar', 'person': objects.comment[id].person})

// Ändert die Person, auf den sich der Kommentar bezieht (verschwindet aus der Liste)
update_object('comment', id, {'person': {'id':0}})

// Entfernt diesen Kommentar und Zeigt an dass eine Person namens „Ich“ das war.
remove_object('comment', id, {'name': 'Ich'})

Fragen? Immer her damit! Viel Spaß beim Erkunden! :)

]]>
Warum abiapp.net Geld kostet https://blog.abiapp.net/warum-abiapp-net-geld-kostet/ Sun, 18 May 2014 22:09:52 +0000 https://blog.abiapp.net/?p=60 Uns wird des Öfteren die Frage gestellt, warum wir uns entschieden haben, abiapp.net gegen eine Gebühr anzubieten statt einen Weg zu finden, es kostenlos zu betreiben, wo doch Abijahrgänge selten zu viel Geld haben, schon gar nicht am Anfang der Abiplanung. Wir haben uns entschieden, trotz der abschreckenden Wirkung eine niedrige Gebühr zu verlangen, weil wir nicht glauben, dass AbiturientInnen so einfach gestrickt sind. Wir glauben, dass wir in der Lage sind, euch davon zu überzeugen, dass sich die Ausgabe lohnt. Und zwar in dem wir euch erklären, was die Alternativen wären.

Fakt ist, dass einige Kosten entstehen. Selbst wenn man von den unzähligen Stunden, die wir in dieses Projekt stecken, absieht, zahlen wir für den reibungslosen Betrieb jeden Monat Servermiete und weil wir uns wünschen, dass das Projekt ein Erfolg wird, geben wir eine für uns Studenten recht große Menge Geld für Werbung aus, denn von ganz allein wird man dann doch nicht bekannt. Wir mussten also irgendeinen Weg finden, zumindest die laufenden Kosten zu decken. Wir glauben aus folgenden Gründen, dass eine kleine Gebühr nicht nur für uns, sondern auch für euch die beste Lösung ist.

Natürlich hätten wir die laufenden Kosten aus unserer eigenen Tasche bezahlen und abiapp.net völlig frei anbieten können. Dann müssten wir auf Werbung verzichten, aber könnten das Projekt auf Sparflamme durchaus betreiben. Das Problem ist nur: Auch wir müssen unsere Miete bezahlen und ein Projekt, das Geld kostet statt einzubringen, läuft in die Gefahr, langfristig vernachlässigt und nicht weiter gepflegt zu werden. Anderen Projekten ist das passiert. Das Internet ist voll von nett gemeinten Projekten, die irgendwann der Stillstand befallen hat. Das wollen wir nicht, dafür ist uns abiapp.net zu schade. Wir wollen euch auch in Jahren noch nicht nur eine moderne, erstklassige Plattform bieten, sondern vor allem auch einen Support, der euch auf alle eure E-Mails freundlich und kompetent antwortet, Fehler schnell behebt und stetig neue Funktionen hinzufügt.

Die offensichtliche Möglichkeit, mit einer Internetseite Geld zu verdienen, ist natürlich Werbung. Wir hätten abiapp.net mit Werbung versehen können. Oben eine Linkzeile, unten ein blinkendes Banner, rechts eine bunte Anzeige und bei jedem zehnten Seitenaufruf ein Fenster, das sich quer über den Inhalt schiebt. Im Ernst, das will niemand. Wir glauben nicht, dass ihr die Seite gerne benutzen wollen würdet, wenn sie mit Werbung vollgestopft wäre. Und wir wünschen uns, dass ihr sie gerne benutzt. Jeden Tag, ein ganzes Jahr lang. Das macht keinen Spaß mit Werbung.

Wer das ernsthaft benutzen wollte, würde einen AdBlocker verwenden und das Projekt würde wieder nichts abwerfen. Außerdem sind wir zu klein, um ein eigenes Werbenetzwerk aufzubauen und hätten Werbung über ein Netzwerk wie Google einbinden müssen, dabei halten wir es für ethisch verwerflich, die Daten unserer Nutzer einem anderen Anbieter auf dem Silbertablett zu präsentieren. Fazit: Wir wären unglücklich, ihr wärt unglücklich.

Die andere Möglichkeit wäre ein Sponsor gewesen, zum Beispiel eine große Abizeitungs-Druckerei, die uns finanziert und an die wir uns anhängen. Das wäre für euch auf den ersten Blick bequem, es gäbe nur ein wenig erträgliche Werbung und die Benutzung würde euch nichts kosten. Auch für uns wäre es bequem, wir hätten ein sichereres Einkommen mit dem Projekt und müssten weniger stark dafür kämpfen, mehr Schulen von uns zu überzeugen. Wir sind Sponsoring nach wie vor nicht vollständig abgeneigt, aber es gibt auf den zweiten Blick einen ganz gewichtigen Grund, warum wir uns nicht komplett über Sponsoring finanzieren wollen. Der Grund klingt erst einmal sehr offensichtlich, hat aber große Auswirkungen: Ihr wärt nicht unsere Kunden. Unser Kunde wäre der Sponsor, ihr wärt eher Ware, die wir dem Sponsor anbieten.

Bekanntlich ist der Kunde König, und das bedeutet, dass wir in allen unseren Entscheidungen über beispielsweise die Entwicklung von neuen Funktionen nicht darüber nachdenken müssten, was euch am besten gefällt, sondern was unserem Sponsor am besten gefällt oder am meisten nützt. Uns ist es deutlich lieber wenn ihr unsere Kunden seid und wir damit euren Interessen verpflichtet, und euch wahrscheinlich auch.

All diese Gründe legen nahe, statt uns abhängig zu machen oder euch mit Werbung zukleistern, klar und ehrlich eine einmalige Zahlung von euch zu verlangen – ohne versteckte Kosten, ohne Datenverkauf, ohne fremde Interessen. Damit lösen sich all die oben genannten Interessenkonflikte in Luft auf. Und wir glauben wirklich, dass wir einen Preis festgelegt haben, den jede Stufe zahlen kann. Der Druck von Raphaels Abizeitung (es war eine kleinere Schule) hat etwa 1.300 € gekostet – unsere Gebühr von 60 € bzw. 35 € ist dagegen wirklich verschwindend. Und wir geben uns alle Mühe, dass wir das Geld wert sind.

]]>