09 · Engineering
Wie eine Änderung in die Produktion gelangt.
Die Arbeit wird in nummerierten Runden geliefert, 454 davon in der aktuellen Serie. Jede wird spezifiziert, vereinbart, vollständig gebaut, nachgewiesen und dokumentiert.
Plattformbeschreibung
Die Entwicklungsumgebung
Die Entwicklung läuft auf zwei Maschinen, die absichtlich ungleich gehalten werden: einer vollständigen Umgebung auf der Entwicklungs-Workstation, auf der die Datenbank liegt, und einem verwerfbaren Cloud-Container, in dem der Code ganz ohne Datenbank geschrieben und getestet wird.
Die Workstation, phoenix-dev26.
- Die Solution wird in Visual Studio aus dem Projektstamm geöffnet und unter Kestrel über das Startprofil des Projekts unter https://localhost:51880 ausgeführt, mit einem zusätzlichen einfachen HTTP-Port, in der Development-Umgebung.
- Die Anwendung greift direkt auf SQL Server zu. Nach Festlegung des Projektinhabers greift sie auf die Produktivkataloge zu statt auf eine wiederhergestellte Entwicklungskopie, über eine Verbindungszeichenfolge, die in einer Systemumgebungsvariablen gehalten wird.
- Eine User-Secrets-Kennung ist in der Projektdatei vorhanden, wird in der Praxis aber nicht verwendet; die Konfiguration stammt aus der Umgebung.
- Eine bekannte Falle: Razor-Views werden in dieselbe Assembly kompiliert wie die Page-Models. Wenn also eine Änderung in einer .cs-Datei sichtbar wird und eine Änderung in einer .cshtml-Datei nicht, verwendet der inkrementelle Build eine veraltete View wieder. Die Abhilfe besteht darin, die Ordner obj und bin zu löschen und neu zu bauen.
- Schemaskripte werden vom Projektinhaber von Hand pro Katalog aus seinem eigenen SQL-Client ausgeführt.
- Ein einziger Befehl, verify.cmd, baut die Solution, führt vier Probes aus, startet eine isolierte Instanz auf einem eigenen Port, meldet sich an, öffnet alle sechzehn Berichtsseiten und lädt jede als PDF herunter. Sein Beispielmodus führt denselben Lauf gegen Fixtures ganz ohne Datenbank aus.
Der Cloud-Container hat ein .NET 8 SDK, einen Build-Baum und überhaupt keine Datenbank.
- Das Fehlen einer Verbindungszeichenfolge wählt den Beispielmodus, in dem Fixture-Implementierungen der Finanz-, Berichts-, Kalender-, Umsatzsteuer- und Belegspeicher jede Abfrage beantworten; das Startprogramm verweigert den Start, wenn eine Verbindungszeichenfolge vorhanden ist.
- Die Fixtures werden aus den eigenen Belegen und Zahlen des Unternehmens erstellt, sodass ein Test gegen Zahlen prüfen kann, die bereits auf Papier vorliegen.
- Ein Headless-Browser steuert die laufende Anwendung für Probes, Screenshots und PDF-Rendering.
- Ein lokaler Platzhalter antwortet anstelle des KI-Endpunkts sowie der Markt- und Wechselkurs-Feeds mit exakt vorgegebenen Antworten, sodass Arithmetik ohne Modell im Kreislauf nachgewiesen werden kann.
Gates. Siebenunddreißig Gate-Skripte und vier Quellcode-Sweeps werden gegen jede Runde ausgeführt.
- Einige sind statische Scans, die eine Eigenschaft des Quellcodes zusichern, etwa das Fehlen einer unbenannten Projektion innerhalb einer CTE oder eines langen hexadezimalen Literals in einer Konfigurationsdatei.
- Die wertvolleren steuern die laufende Anwendung. Die teuerste Lehre dieses Projekts ist, dass ein Test, der nie ausführt, was der Benutzer ausführt, einen Laufzeitfehler nicht sehen kann.
- Gates sichern die Regel zu, die eine Runde festgelegt hat, nicht den Ausdruck, der ausgeliefert wurde, und sie entfernen Kommentare vor der Prüfung; diese Korrektur musste viermal gesondert vorgenommen werden.
Übergang zwischen den Maschinen. Dateien gelangen nach einem festen Verfahren über die Desktop-Dateibrücke:
- vor der ersten Bearbeitung einer Runde wird jede Datei, die die Runde berühren könnte, auf der Festplatte der Workstation gehasht;
- vor dem Commit werden dieselben Dateien erneut bereitgestellt und inhaltlich verglichen;
- nach dem Commit werden beide Seiten erneut gehasht und der kombinierte Digest verglichen.
"Ausgeliefert" ist eine Aussage über die Festplatte der Workstation, niemals über den Build-Container.
Das Deployment kopiert genau vier Dinge auf die Live-Site: den gesamten statischen Web-Ordner, die Anwendungs-Assembly, ihre Symbole und ihre ausführbare Datei. Konfigurationsdateien werden nicht kopiert, sodass Live-Einstellungen und Geheimnisse ein Release überstehen. Der Anwendungspool wird nach dem Kopieren neu gestartet, und die Checkliste vor der Veröffentlichung entfernt das Health-Token und bestätigt, dass die Diagnoseklasse entfernt ist.
Wie Arbeit spezifiziert, gebaut und nachgewiesen wird
Die Arbeit wird in nummerierten Runden geliefert. Der aktuelle Build ist v31.454, was zeigt, wie das Projekt geführt wurde: viele kleine, vollständige, verifizierte Lieferungen statt langer Branches. Eine Runde beginnt mit der Anfrage des Projektinhabers, wird in eine Matrix von Festlegungen überführt, die der Projektinhaber annimmt oder ändert, und wird dann vollständig ausgeliefert. Eine Runde wird nur für Arbeit aufgeteilt, die noch nicht erledigt werden kann, etwa eine unbeantwortete Diagnose oder eine Entscheidung, die nur der Projektinhaber treffen kann.
Jede Runde hinterlässt eine schriftliche Aufzeichnung.
- Eine Rundennotiz in der Projektdokumentation hält fest, was sich geändert hat und warum.
- Ein Annahmenregister erfasst jede Einschätzung, die falsch sein könnte: nummeriert, im Code neben der Zeile markiert, die sie betrifft, nach Risiko bewertet und mit dem SQL versehen, das sie klären würde.
- Wo eine Entscheidung eine frühere umkehrt, wird die frühere Festlegung durchgestrichen und kommentiert statt gelöscht, sodass die Geschichte einer Entscheidung lesbar bleibt.
Vier ständige Regeln bestimmen, was ohne Rückfrage getan werden darf:
- Geheimnisse liegen ausschließlich in Systemumgebungsvariablen, niemals in einer Datei, die der Webserver ausliefern kann, und werden niemals in eine Unterhaltung eingefügt.
- Dem Projekt darf kein neues Paket hinzugefügt werden, weshalb die Web Push-Implementierung, der PDF-Writer und der Parser für Kalendereinladungen allesamt handgeschrieben sind.
- Keine Schemaänderung, auch kein neuer Index, wird ohne Zustimmung des Projektinhabers vorgenommen, und jedes Skript wird abgesichert und wiederholt ausführbar geschrieben und vom Projektinhaber pro Katalog ausgeführt.
- Gebuchte Buchhaltungsdaten werden niemals verändert, um ein Darstellungsproblem auszugleichen, und historische Datensätze werden niemals als Nebeneffekt einer Fehlerbehebung massenhaft korrigiert.
Der Nachweis ist geschichtet.
- Der Build muss fehlerfrei sein.
- Die Sweeps prüfen den Quellcode auf die bekannten Fehlerklassen.
- Die Gates sichern die Regeln zu.
- Probes steuern die laufende Anwendung.
- Die abschließende Prüfung ist immer ein Hash-Vergleich mit der Festplatte der Workstation.
Wo die Sandbox etwas nicht sehen kann, sagt der Bericht das. Das deutlichste Beispiel ist SQL: Im Build-Container wird keine Abfrage ausgeführt, daher wird eine Abfrageänderung statisch und durch Inspektion nachgewiesen, bis sie auf den Produktivkatalogen läuft, und der Rundenbericht hält das fest.