chapters: Fliesstext auf 57 reine Textseiten kuerzen

Zwei Kompressionsdurchgaenge ueber Kapitel 2-7. Entfernt wurden
Redundanzen, Meta-Kommentare, Ueberklaerungen und Fuellsaetze;
Fakten, Namen, Daten, Entscheidungen samt Begruendung sowie alle
Abbildungen und Tabellen bleiben unveraendert.

Reine Textseiten: 78 -> 57 (Woerter 19613 -> 12451).
Gesamt-PDF: 138 -> 116 Seiten.
This commit is contained in:
2026-08-25 23:02:17 +02:00
parent 1a3d0820da
commit ce0875f29b
38 changed files with 351 additions and 445 deletions
+11 -13
View File
@@ -3,7 +3,7 @@
\subsection{Schichtung}
Das Dokumentenmodul folgt der in Houston bereits etablierten Schichtung und führt keine neuen Strukturmuster ein. Abbildung~\ref{fig:module-components} zeigt die Komponenten und ihre Beziehungen.
Das Dokumentenmodul folgt der in Houston etablierten Schichtung. Abbildung~\ref{fig:module-components} zeigt die Komponenten.
\begin{figure}[H]
\centering
@@ -12,30 +12,28 @@ Das Dokumentenmodul folgt der in Houston bereits etablierten Schichtung und füh
\label{fig:module-components}
\end{figure}
Die oberste Schicht bilden drei Razor Pages. \texttt{Documents} stellt die eigentliche Liste samt Suche, Filtern und Blätterelementen dar. \texttt{Document/Download} nimmt Downloadanforderungen entgegen, sowohl für einzelne Dokumente als auch für ZIP-Archive. \texttt{Document/Share} liefert die Vorschauseite für Freigabelinks. Die Aufteilung auf getrennte Seiten statt auf mehrere Handler einer einzigen Seite folgt daraus, dass Download und Freigabe eigene Routen mit eigenen Antwortformaten benötigen.
Die oberste Schicht bilden drei Razor Pages: \texttt{Documents} für Liste, Suche, Filter und Blätterelemente, \texttt{Document/Download} für Downloadanforderungen (einzeln und als ZIP) und \texttt{Document/Share} für Freigabelinks. Die Aufteilung folgt daraus, dass Download und Freigabe eigene Routen mit eigenen Antwortformaten benötigen.
Darunter liegt der \texttt{DocumentsService} als fachliche Schicht. Er kennt die Regeln des Ablagekonzepts: wie ein Kundenordner aufgelöst wird, welche Objekte als Dokumente gelten, wie der Typ aus dem Pfad abgeleitet wird und welche Einträge auszublenden sind. Der \texttt{S3DocumentsClient} kapselt darunter den technischen Zugriff auf den Speicher und ist die einzige Stelle, an der \texttt{IAmazonS3} unmittelbar verwendet wird.
Darunter liegt der \texttt{DocumentsService} als fachliche Schicht mit den Regeln des Ablagekonzepts: Auflösung des Kundenordners, Typableitung aus dem Pfad, Ausblendung technischer Einträge. Der \texttt{S3DocumentsClient} kapselt den technischen Speicherzugriff und ist die einzige Stelle, an der \texttt{IAmazonS3} unmittelbar verwendet wird.
\subsection{Eigene Typen statt Zeichenketten}
Eine Entwurfsentscheidung, die sich erst im Verlauf der Umsetzung herausbildete, betrifft den Umgang mit Pfaden. In der ersten Fassung wurden Dokumentschlüssel als gewöhnliche Zeichenketten durch die Schichten gereicht. Im Review des Downloads führte das zu wiederholten Rückfragen zur Pfadvalidierung — und zwar deshalb, weil einer Zeichenkette nicht anzusehen ist, ob sie bereits geprüft wurde.
Eine Entwurfsentscheidung, die sich im Verlauf herausbildete, betrifft den Umgang mit Pfaden. Anfangs wurden Dokumentschlüssel als Zeichenketten durch die Schichten gereicht. Im Review des Downloads führte das zu wiederholten Rückfragen zur Pfadvalidierung, weil einer Zeichenkette nicht anzusehen ist, ob sie bereits geprüft wurde.
Daraufhin wurden eigene Typen eingeführt, die diese Unterscheidung im Typsystem sichtbar machen. Ein \emph{Schlüssel} bezeichnet den vollständigen, bereits gegen das Kundenpräfix validierten Pfad im Speicher; ein \emph{relativer Pfad} bezeichnet den Anteil unterhalb des Kundenordners, wie er in Freigabelinks und in der ZIP-Struktur auftritt. Beide Typen können nur über Konstruktionswege entstehen, die die jeweilige Prüfung durchführen.
Daraufhin wurden eigene Typen eingeführt: Ein \emph{Schlüssel} bezeichnet den vollständigen, validierten Pfad; ein \emph{relativer Pfad} den Anteil unterhalb des Kundenordners. Beide können nur über Konstruktionswege entstehen, die die jeweilige Prüfung durchführen. Eine vergessene Prüfung führt zu einem Übersetzungsfehler statt zu einer Sicherheitslücke.
Der Nutzen liegt darin, dass eine vergessene Prüfung nicht mehr zu einer Sicherheitslücke, sondern zu einem Übersetzungsfehler führt. Der zugehörige Pull Request durchlief 23 Iterationen und bestand zu einem erheblichen Teil aus genau diesem Refactoring — ein Aufwand, der sich in den folgenden Anforderungen mehrfach auszahlte, weil ZIP-Download, PDF-Vorschau und Freigabelinks dieselben Typen wiederverwenden konnten.
Nach demselben Muster entstanden \texttt{DocumentType} für die Typisierung, \texttt{DocumentName} für die Behandlung von Anzeigenamen und Dateiendungen sowie \texttt{OrgSlug} für die Normalisierung des Firmennamens.
Der zugehörige Pull Request durchlief 23 Iterationen und bestand zu einem erheblichen Teil aus diesem Refactoring — ein Aufwand, der sich auszahlte, weil ZIP-Download, PDF-Vorschau und Freigabelinks dieselben Typen wiederverwenden konnten. Nach demselben Muster entstanden \texttt{DocumentType}, \texttt{DocumentName} und \texttt{OrgSlug}.
\subsection{Zentrale Autorisierung}
Die erste Fassung des Document Explorers prüfte die Berechtigung im PageModel selbst. Im Review wies \emph{Hanna Ebner} darauf hin, dass die Autorisierung in Houston zentral in der Anwendungskonfiguration eingerichtet wird und eine zusätzliche Prüfung an der Seite deshalb überflüssig ist.
Die erste Fassung des Document Explorers prüfte die Berechtigung im PageModel. Im Review wies \emph{Hanna Ebner} darauf hin, dass die Autorisierung in Houston zentral in der Anwendungskonfiguration erfolgt und eine zusätzliche Prüfung an der Seite überflüssig ist.
Der Einwand betrifft mehr als nur doppelten Code. Eine an der Seite hinterlegte Prüfung ist leicht zu übersehen, wenn später eine weitere Seite hinzukommt — genau das wäre bei \texttt{Download} und \texttt{Share} passiert. Die zentrale Registrierung stellt dagegen sicher, dass alle Routen des Moduls derselben Richtlinie unterliegen, ohne dass dies an jeder einzelnen Stelle wiederholt werden muss.
Der Einwand betrifft mehr als doppelten Code: Eine seitenspezifische Prüfung ist leicht zu übersehen, wenn weitere Seiten hinzukommen — genau das wäre bei \texttt{Download} und \texttt{Share} passiert. Die zentrale Registrierung stellt sicher, dass alle Routen des Moduls derselben Richtlinie unterliegen.
\subsection{Gestapelte Pull Requests}
Ein Vorgehen, das sich durch die gesamte Umsetzung zieht und das Verständnis der Reviewhistorie erleichtert, ist die Verkettung der Pull Requests. Der erste Pull Request des Document Explorers ging gegen den Hauptbranch. Der darauf aufbauende Pull Request für die Icons wurde jedoch nicht ebenfalls gegen den Hauptbranch geführt, sondern gegen den Branch des Explorers. Der Suchen-Pull-Request wiederum ging gegen den Icon-Branch, der Download-Pull-Request gegen den Suchen-Branch und der Freigabelink-Pull-Request gegen den Download-Branch.
Ein Vorgehen, das sich durch die gesamte Umsetzung zieht, ist die Verkettung der Pull Requests. Der erste ging gegen den Hauptbranch; jeder darauf aufbauende gegen den Branch seines Vorgängers.
Der Grund ist die Reviewbarkeit. Da die Arbeiten inhaltlich aufeinander aufbauen, hätte ein direkter Vergleich gegen den Hauptbranch bei jedem Pull Request auch sämtliche Änderungen der Vorgänger enthalten. Ein Reviewer hätte die für das jeweilige Backlog Item relevanten Änderungen aus einem stetig wachsenden Gesamtunterschied heraussuchen müssen. Durch die Verkettung enthält jeder Pull Request genau die Änderungen seines eigenen Backlog Items. Auf diesen Umstand wurde jeweils im ersten Kommentar des Pull Requests hingewiesen.
Der Grund ist die Reviewbarkeit. Da die Arbeiten aufeinander aufbauen, hätte ein direkter Vergleich gegen den Hauptbranch auch sämtliche Vorgängeränderungen enthalten. Durch die Verkettung enthält jeder Pull Request genau die Änderungen seines Backlog Items.
Der Preis dieses Vorgehens zeigte sich beim Zusammenführen. Sobald ein Vorgänger in den Hauptbranch übernommen war, musste der Nachfolger auf den Hauptbranch umgestellt werden. Diese Umstellung setzt in Azure DevOps die bereits abgegebenen Freigaben zurück, sodass mehrere Reviewer ein zweites Mal zustimmen mussten. Bei zwei Pull Requests ist dieser Effekt im Ereignisprotokoll dokumentiert. Für künftige Arbeiten wäre abzuwägen, ob der Gewinn an Reviewbarkeit diesen zusätzlichen Abstimmungsaufwand rechtfertigt; bei der vorliegenden Zahl aufeinander aufbauender Backlog Items überwog er deutlich.
Der Preis zeigte sich beim Zusammenführen: Sobald ein Vorgänger in den Hauptbranch übernommen war, musste der Nachfolger umgestellt werden. Diese Umstellung setzt in Azure DevOps die bereits abgegebenen Freigaben zurück. Für künftige Arbeiten wäre abzuwägen, ob der Gewinn an Reviewbarkeit diesen Abstimmungsaufwand rechtfertigt; bei der vorliegenden Zahl aufeinander aufbauender Items überwog er deutlich.