Webanwendungsentwicklung
Laravel-Anwendungsentwicklung
Neue Laravel-Anwendungen, gebaut um ihren eigenen Erfolg zu überstehen - ein Schema das vor den Daten entworfen wird, Queues die niemand beobachten muss, und ein zweites Jahr das günstiger ist.
Laravel macht die ersten drei Monate leicht, und genau das ist das Problem. Das Framework lässt Sie bereitwillig eine Anwendung ausliefern, deren Schema eine Migration nach der anderen erfunden wurde, deren Jobs annehmen, sie würden immer nur einmal laufen, und deren langsamste Abfrage schnell ist, weil die Tabelle vierhundert Zeilen hat.
Nichts davon ist beim Start sichtbar. Alles davon ist bei Skalierung sichtbar, und dann sind die Daten in der Produktion und die Korrekturen sind Ausfälle.
Was wir bauen
Anwendungen, bei denen das Verhalten der schwierige Teil ist: mandantenfähige SaaS-Plattformen, Marktplätze mit Geldfluss, interne Systeme, die ein Jahrzehnt Tabellenkalkulation ersetzen, und Backoffices, auf denen ein Unternehmen tatsächlich läuft.
Wo ein Problem eine eigene Form hat, hat es eine eigene Seite – die Datenbank, wenn das Datenmodell die Schwierigkeit ist, Queues, wenn die Arbeit außerhalb der Anfrage passiert, und APIs, wenn jemand anders sie konsumieren muss. Diese Seite ist das, was sie gemeinsam haben.
Das Schema wird vor dem Code entschieden
Die meisten Laravel-Anwendungen bekommen ihre Datenbank aus Versehen. Ein Modell wird angelegt, eine Migration folgt, eine Beziehung kommt hinzu wenn ein Bildschirm sie braucht, und achtzehn Monate später gibt es vier Spalten, die einen Status halten, und keine zwei davon stimmen überein.
Wir entwerfen sie zuerst, auf Papier, und das ist der Teil des Projekts, bei dem wir am meinungsstärksten sind:
- Constraints in der Datenbank, nicht nur in der Anwendung. Ein Fremdschlüssel, den das Schema durchsetzt, ist ein Fehler, der die Produktion nicht erreichen kann. Eine Regel, die nur in einem Form Request lebt, ist eine Regel, die ein Queue-Job, ein Artisan-Befehl oder ein künftiger Entwickler umgeht, ohne zu wissen, dass es sie gab.
- Indizes aus den Abfragen gewählt, nicht geraten. Geschrieben, wenn die Abfrage geschrieben wird, solange der Grund noch in jemandes Kopf ist.
- Migrationen, die auf einer laufenden Tabelle sicher sind. Eine Spalte hinzuzufügen ist umsonst; eine mit Standardwert oder einen Index hinzuzufügen ist eine Sperre, und auf einer Tabelle mit Millionen Zeilen ist eine Sperre ein Ausfall mit einem Deployment daran.
- Geld und Zeit richtig gespeichert. Ganzzahlige kleinste Einheiten, explizite Währung, UTC, und eine einmal aufgeschriebene Entscheidung zur Zeitzonendarstellung statt einer Diskussion pro Bildschirm.
Eloquent, bewusst eingesetzt
Eloquent ist produktiv und es verbirgt die Kosten dessen, was es tut – ein guter Handel bis zu dem Tag, an dem er es nicht mehr ist.
Wir behandeln die Abfragezahl als eine Zahl, für die jemand verantwortlich ist. Relationen werden vorab geladen, weil der Code es sagt, und nicht weil sich eine Seite einmal langsam anfühlte. Lazy Loading ist in Nicht-Produktionsumgebungen komplett abgeschaltet, sodass ein versehentliches N+1 ein fehlschlagender Test ist statt ein Support-Ticket. Aggregate, die ins SQL gehören, bleiben im SQL, statt in den Speicher geholt und in PHP gezählt zu werden.
Nichts davon ist exotisch. Es ist der Unterschied zwischen einer Anwendung, die sich würdevoll verschlechtert, und einer, die an dem Tag umfällt, an dem das Marketing funktioniert hat.
Arbeit, die außerhalb der Anfrage passiert
Alles Langsame, alles von Dritten und alles, was scheitern kann, gehört in einen Job und nicht in einen Controller. Das ist leicht gesagt und hat Folgen, für die man entwerfen sollte, statt sie zu entdecken:
Jobs werden so geschrieben, dass sie zweimal laufen dürfen, denn irgendwann wird jeder von ihnen das tun. Eine Wiederholung ist kein Fehlerfall, sie ist der Normalfall, und ein Job, der eine Karte belastet oder eine E-Mail sendet, muss das wissen. Fehler landen dort, wo ein Mensch sie sieht. Lang laufende Arbeit wird zerteilt, damit ein Deployment sie nicht auf halber Strecke tötet.
Tests, in der Menge die sich rechnet
Feature-Tests über die Routen, die zählen, Unit-Tests wo die Logik wirklich verwickelt ist, und eine Factory für jedes Modell, damit der nächste Test billig zu schreiben ist. Keine hundertprozentige Abdeckung, die das Falsche teuer einkauft.
Der Maßstab, den wir anlegen, ist, ob die Suite die Änderung abfangen würde, die das Geschäft kaputtmacht. Ein Test, der prüft ob ein Controller 200 zurückgibt, fängt fast nichts ab; ein Test, der prüft dass eine Bestellung nicht zweimal bezahlt werden kann, fängt das ab, was Sie eine Rückerstattung und einen Ruf gekostet hätte.
Die Form der Arbeit
Vier Phasen. Jede endet mit etwas, das auf einer URL läuft, statt mit etwas, das in einem Statusbericht beschrieben wird.
- Umfang und Schema. Der Fachbereich ausgeschrieben, die Tabellen und die Constraints, die sie zusammenhalten, jedes System mit dem das hier reden muss, und die Liste der Jobs, die existieren werden. Alles danach wird gegen das kalkuliert, was hier herauskommt – deshalb entsteht ein Dokument und keine Präsentation.
- Das Rückgrat. Migrationen, Modelle, Authentifizierung, Autorisierung, der Queue-Aufbau, die Deployment-Pipeline und eine Testsuite, die ab dem ersten Commit in CI läuft. Nichts sieht fertig aus. Alles darunter ist es.
- Fachbereiche, der wertvollste zuerst. Geschrieben nach den Konventionen, die Phase zwei festgelegt hat, durch Ihren Review-Prozess geschickt falls Sie Entwickler haben, und am Ende jeder Iteration veröffentlicht statt hinter einem Starttermin aufgestaut.
- Härtung und Übergabe. Lasttests wo die Zahlen zählen, ein Handbuch für die Anrufe, die um drei Uhr morgens kommen, das Schema aufgeschrieben, und eine Sitzung je Fachbereich mit den Leuten, die ihn übernehmen werden.
All das passiert dort, wo Ihr Team ohnehin arbeitet – Ihr Repository, Ihr Ticketsystem, Ihre Reviews. Code, der bis zum Starttag in unseren Werkzeugen bleibt, ist Code, den Ihr Team an dem Tag zum ersten Mal sieht, an dem es zu spät ist, mit ihm zu streiten.
Was die Zahl tatsächlich bewegt
Das Framework nicht. Die Dinge, die entscheiden wie lange ein Laravel-Build dauert, sind dieselben, die entscheiden wie lange irgendein Build dauert, und gesagt zu bekommen welche davon auf Sie zutreffen, ist nützlicher als ein Tagessatz:
- Mit wie vielen Systemen es reden muss. Ein Zahlungsdienstleister ist eine Woche. Ein Zahlungsdienstleister, ein ERP, eine Versand-API und ein Bankdateiformat, das in einem PDF von 2011 dokumentiert ist, sind ein anderes Projekt.
- Ob die Regeln irgendwo aufgeschrieben sind. Gegen einen Prozess zu bauen, der nur in einem Kopf existiert, ist der verlässlichste Weg, denselben Bildschirm dreimal zu bauen.
- Ob schon etwas produktiv ist. Daten, die existieren, müssen migriert werden, und Daten zu migrieren, die niemand geprüft hat, ist der Ort an dem Zeitpläne sterben.
- Wie viel davon Reporting ist. Reporting sieht billig aus und ist es nicht: dort sitzen die Abfragearbeit, die Datumsarithmetik und die Gespräche, die mit „aber die Buchhaltung zählt das anders" beginnen.
Wann dies das falsche Projekt ist
Wenn eine Anwendung bereits existiert und das Problem darin besteht, dass sie schwer zu ändern ist oder mehrere Versionen zurückliegt, ist das Upgrades und Rettung, und es beginnt mit Lesen statt Schreiben.
Wenn sie funktioniert, aber unter Last umfällt, ist das Performance und Skalierung.
Und wenn Sie wirklich nicht sagen können, welches der beiden Sie vor sich haben, ist genau dafür das Audit da – zwei Wochen, ein Festpreis, und erheblich billiger als ein Quartal in das falsche zu stecken.
Was Sie bekommen
Die Anwendung und die vier Dokumente, die sie zu etwas machen, das jemand anders betreiben kann: das Schema mit der Begründung zu jeder nicht offensichtlichen Entscheidung, die Queue-Topologie samt dem, was jeder Worker darf, das Deployment-Runbook und die Testsuite mit einer Notiz dazu, was sie bewusst nicht abdeckt.
Pull Requests sind reviewbar und laufen fortlaufend ein, Sie lesen die Arbeit also während sie entsteht statt sie am Ende zu bekommen. Wenn Ihr Team übernehmen soll, sollte es vorher reviewen und nicht danach.
