JavaScript-Module mit klaren Aufgaben und begrenzten Abhängigkeiten
Drei fiktive Aufgaben, vier Modulrollen und ein tatsächlich gescheiterter Importkreis machen Abhängigkeiten konkret.

Ein JavaScript-Projekt wird nicht automatisch übersichtlicher, wenn eine lange Datei auf viele kurze Dateien verteilt wird. Entscheidend ist, welche Verantwortung eine Datei übernimmt und welche anderen Teile sie dafür kennen muss. Eine fachliche Auswahl sollte nicht nebenbei ein Formular suchen. Eine Darstellung sollte nicht eigenständig neue Daten laden. Der Einstieg darf diese Teile zusammenbringen, ohne selbst sämtliche Regeln zu enthalten. An diesen Grenzen lässt sich später nachvollziehen, was eine Änderung tatsächlich beeinflusst.
Dieser Leitfaden entwickelt eine kleine Aufgabenübersicht mit drei ausdrücklich fiktiven Einträgen. Eine Auswahl nach Bereich verändert die angezeigten Aufgaben und ihre geplante Minutensumme. Die Zeitangaben sind Lehrdaten und keine gemessenen Arbeitszeiten. Der vollständige Aufbau wurde mit Node.js und Edge ausgeführt. Die interessantere Frage lautet dabei nicht, ob sich Dateien importieren lassen. Es geht darum, ob die fachliche Regel ohne Browser funktioniert, die Darstellung Texte sicher übernimmt und ein fehlender Zusatzbaustein die ursprünglichen Informationen stehen lässt.
Eine konkrete Änderung als Ausgangspunkt nehmen
Stellen wir uns vor, eine bisher statische Übersicht soll künftig nur Aufgaben aus dem Bereich Planung zeigen können. In einer gewachsenen Datei liegen die Datensätze, das Berechnen der Summe, die Suche nach Elementen und der Ereignislistener direkt nebeneinander. Der erste funktionierende Entwurf ist damit durchaus möglich. Problematisch wird diese Mischung, sobald dieselbe Auswahl für eine andere Darstellung benötigt wird. Ein Test muss dann möglicherweise eine ganze Seite nachbauen, obwohl er lediglich prüfen möchte, welche Aufgaben zu einem Bereich gehören.
Die Trennung folgt deshalb einer tatsächlichen Änderungsfrage. Welche Teile ändern sich, wenn ein zusätzlicher Bereich hinzukommt? Welche ändern sich, wenn aus einer Liste eine Tabelle wird? Welche ändern sich nur bei einer anderen Sprache? Eine vernünftige Grenze hält diese Entscheidungen auseinander. Sie ist kein Selbstzweck und kein allgemeines Rezept für möglichst viele Dateien. In diesem Beispiel reichen ein Datenmodul, eine Auswahlfunktion, ein Darstellungsadapter und ein Einstieg. Eine zweite Abstraktionsschicht wäre erst durch eine weitere konkrete Anforderung zu begründen.
Den öffentlichen Vertrag vor der Dateiaufteilung beschreiben
Die Auswahlfunktion erhält eine Liste von Aufgaben und einen erlaubten Bereich. Sie liefert eine neue, begrenzte Ergebnisstruktur mit den passenden Aufgaben und ihrer Minutensumme. Sie verändert die übergebene Liste nicht. Sie kennt weder ein Auswahlfeld noch eine URL, einen Speicher oder eine Spracheinstellung. Diese wenigen Sätze sind bereits ein nützlicher Vertrag. Ein Aufrufer kann prüfen, ob die Funktion für seine Aufgabe geeignet ist, ohne ihren kompletten Inhalt lesen zu müssen.
Zum Vertrag gehören auch die Grenzen der Eingabe. Unser Lehrmodell akzeptiert höchstens hundert Aufgaben. Jede Aufgabe hat genau die Felder Kennung, Titel, Minuten und Bereich. Kennungen sind positive sichere Ganzzahlen und dürfen innerhalb der Liste nicht doppelt vorkommen. Minuten liegen zwischen null und 480. Titel enthalten mindestens ein sichtbares Zeichen und höchstens achtzig Unicode-Codepunkte. Diese Grenzen sind bewusste Modellentscheidungen. Sie stellen weder eine allgemeine Projektplanung noch einen vollständigen Validator für fremde Datenquellen dar. Andere Aufgaben brauchen andere Regeln, die ebenso deutlich benannt werden sollten.
Vier Verantwortungen mit drei gerichteten Verbindungen
| Datei | Verantwortung | Bewusst fehlende Abhängigkeit |
|---|---|---|
| catalog.mjs | Drei feste Lehrdatensätze bereitstellen | Keine Darstellung und kein Ereignislistener |
| selection.mjs | Eingaben prüfen und passende Aufgaben zusammenstellen | Kein Dokument und kein Browserzustand |
| view.mjs | Ein übergebenes Ergebnis als Liste ausgeben | Keine Auswahlregel und kein Datenladen |
| main-de.mjs | Elemente und Bausteine für die deutsche Ansicht verbinden | Keine zweite Berechnung derselben Fachregel |
Der Einstieg importiert die drei anderen Module. Zwischen den drei Blattmodulen bestehen im Beispiel keine weiteren Importverbindungen. Das bedeutet nicht, dass jedes größere Projekt diese Form besitzen muss. Hier macht die einfache Richtung jedoch sichtbar, wer wen benötigt. Die Regel lässt sich allein ausführen. Die Darstellung lässt sich mit einem vorbereiteten Ergebnis prüfen. Nur der Einstieg muss wissen, wo auf dieser konkreten Seite das Auswahlfeld und die Übersicht stehen.

Das Datenmodul ohne versteckten Start halten
Das Datenmodul exportiert die drei Aufgaben. Sowohl die Liste als auch ihre einzelnen Einträge werden eingefroren. Das schützt diese flache Lehrstruktur vor versehentlichen Änderungen durch andere Module. Ein Einfrieren der äußeren Liste allein würde Änderungen an den enthaltenen Objekten nicht automatisch verhindern. Bei verschachtelten Daten müsste der gewünschte Schutz deshalb ausdrücklich weitergeführt werden. Unser Datensatz enthält nur primitive Feldwerte, wodurch die Entscheidung überschaubar bleibt.
Beim Import werden keine Elemente erzeugt und keine Listener registriert. Das ist für diesen Baustein eine überprüfbare Entwurfsentscheidung. Ein Import kann grundsätzlich durchaus Initialisierungscode ausführen. Gerade deshalb sollte ein Datenmodul nicht überraschend eine Benutzeroberfläche starten. Falls später Daten von einem Server kommen sollen, wäre ein ausdrücklich aufgerufener Ladebaustein besser erkennbar als eine versteckte Anfrage beim bloßen Kennenlernen der Datendefinition. Ob diese spätere Anfrage gebraucht wird, entscheidet dann der Anwendungsablauf und nicht die Position einer Importzeile.
Die Fachfunktion kopiert statt gemeinsam zu verändern
Die Auswahlfunktion prüft zunächst die erlaubte Kategorie und die Form der Liste. Anschließend wird jeder Datensatz geprüft und als neues Objekt übernommen. Erst danach findet die eigentliche Auswahl statt. Damit prüft die Funktion auch Aufgaben, die für die gewählte Kategorie am Ende nicht angezeigt werden. Diese Entscheidung ist beabsichtigt: Eine formal ungültige Eingabeliste wird insgesamt abgelehnt. Wer stattdessen beschädigte Einträge überspringen möchte, braucht einen anderen Vertrag mit sichtbarem Fehlerbericht.
Das Ergebnis enthält eine neue eingefrorene Liste und eingefrorene Einträge. Ein anderer Aufrufer kann dadurch nicht nebenbei die ursprünglichen Lehrdaten oder das Ergebnis eines vorherigen Aufrufs verändern. Diese Eigenschaft erleichtert den Vergleich zweier Auswahlen. Sie macht das Modul aber nicht zu einer Berechtigungsgrenze. Vertrauliche Daten dürfen nicht allein deshalb an den Browser geschickt werden, weil eine Auswahlfunktion sie später ausblendet. Die Entscheidung, welche Daten ein Benutzer überhaupt erhalten darf, gehört in eine entsprechend vertrauenswürdige Schicht.
Die Darstellung bekommt das Ergebnis übergeben
Der Darstellungsadapter erhält ein Wurzelelement, eine bereits berechnete Auswahl und kurze Sprachbausteine. Er sucht die Liste und den Status ausschließlich innerhalb dieses Wurzelelements. Damit hängt er nicht von einer globalen Kennung für jede einzelne Ausgabe ab. Ein zweiter Bereich könnte denselben Adapter mit einem anderen Wurzelelement verwenden. Dafür müsste der Einstieg die passenden Elemente verbinden. Der Adapter entscheidet weiterhin nicht, welche Aufgaben fachlich dazugehören.
Neue Listeneinträge entstehen mit den DOM-Methoden des zugehörigen Dokuments. Titel und Minuten werden über Textzuweisung ausgegeben. Ein Aufgabentitel, der wie ein Bild-Tag aussieht, wird deshalb im tatsächlichen Browserversuch als Text sichtbar und erzeugt kein Bildelement. Diese konkrete Eigenschaft ist belegt. Daraus folgt kein allgemeiner Schutz für jede denkbare Ausgabe. Würde derselbe Text später in eine URL, ein Stylesheet oder einen HTML-String eingesetzt, wären die jeweiligen Regeln erneut zu untersuchen. Der einfache Adapter vermeidet diese zusätzlichen Ausgabekontexte.
Der Einstieg ist der sichtbare Ort der Zusammenarbeit
Im Einstieg werden die drei benannten Exporte importiert. Danach werden das Wurzelelement und das Auswahlfeld gesucht. Eine kleine Aktualisierungsfunktion ruft zuerst die Fachfunktion und anschließend die Darstellung auf. Sie läuft einmal zum Start und danach bei einer Änderung der Auswahl. Der Ereignislistener gehört damit zu dem Teil, der tatsächlich den Seitenablauf kennt. Ein Import der Darstellungsdatei allein registriert ihn nicht. Diese Unterscheidung verhindert eine ganze Klasse schwer nachvollziehbarer Mehrfachstarts.
Das Auswahlfeld liegt zunächst in einem verborgenen Container. Erst nachdem die erste Ausgabe erfolgreich erstellt wurde, wird dieser Container angezeigt. Ohne JavaScript bleiben die drei statisch vorhandenen Aufgaben sichtbar. Fehlt im Versuch das Darstellungsmodul, startet der Einstieg nicht und der ebenfalls statische Gesamtbestand bleibt erhalten. Der ausgeblendete Filter verspricht dann keine verfügbare Zusatzfunktion. Das Beispiel behandelt diesen begrenzten Ausfall. Es enthält keine allgemeine Wiederherstellung, keine Fehlertelemetrie und keine dauerhafte Speicherung einer Auswahl.
Die vollständigen Dateien ausführen
Die folgenden Dateien gehören in dasselbe Verzeichnis und werden über einen HTTP-Server ausgeliefert. Die HTML-Datei bindet den Einstieg als Modul ein. Relative Importe enthalten die tatsächlichen Dateinamen einschließlich Endung. Die englische Ausführung verwendet denselben Katalog, dieselbe Auswahlfunktion und denselben Adapter. Lediglich die kurze HTML-Beschriftung und die Sprachbausteine im englischen Einstieg unterscheiden sich. Die deutschen Aufgabennamen bleiben absichtlich identische Lehrdaten, damit nicht versehentlich zwei verschiedene Bestände verglichen werden.
catalog.mjs
export const tasks = Object.freeze([
Object.freeze({ id: 17, title: 'Planung', minutes: 45, category: 'planning' }),
Object.freeze({ id: 8, title: 'Datenabgleich', minutes: 15, category: 'technical' }),
Object.freeze({ id: 22, title: 'Nachweis', minutes: 30, category: 'planning' })
]);
selection.mjs
const categories = new Set(['all', 'planning', 'technical']);
const fields = ['category', 'id', 'minutes', 'title'];
export function selectTasks(records, category) {
if (!categories.has(category) || !Array.isArray(records) || records.length > 100) {
throw new TypeError('Invalid selection input');
}
const seen = new Set();
const copy = records.map(record => {
if (!record || typeof record !== 'object' || Array.isArray(record) ||
Object.keys(record).sort().join('|') !== fields.join('|') ||
!Number.isSafeInteger(record.id) || record.id <= 0 || seen.has(record.id) ||
typeof record.title !== 'string' || !record.title.trim() ||
[...record.title].length > 80 || !Number.isSafeInteger(record.minutes) ||
record.minutes < 0 || record.minutes > 480 ||
!['planning', 'technical'].includes(record.category)) {
throw new TypeError('Invalid task record');
}
seen.add(record.id);
return Object.freeze({ id: record.id, title: record.title,
minutes: record.minutes, category: record.category });
});
const items = Object.freeze(copy.filter(record =>
category === 'all' || record.category === category));
return Object.freeze({ items,
totalMinutes: items.reduce((sum, record) => sum + record.minutes, 0) });
}
view.mjs
export function renderPlan(root, selection, labels) {
const list = root.querySelector('ul');
const summary = root.querySelector('[role="status"]');
if (!list || !summary) throw new TypeError('Missing view elements');
const document = root.ownerDocument;
const rows = selection.items.map(item => {
const row = document.createElement('li');
row.dataset.id = String(item.id);
row.textContent = item.title + ': ' + item.minutes + ' ' + labels.minutes;
return row;
});
list.replaceChildren(...rows);
summary.textContent = selection.items.length + ' ' + labels.tasks +
' · ' + selection.totalMinutes + ' ' + labels.minutes;
}
main-de.mjs
import { tasks } from './catalog.mjs';
import { selectTasks } from './selection.mjs';
import { renderPlan } from './view.mjs';
const root = document.querySelector('#plan');
const filter = document.querySelector('#category');
const labels = {"minutes":"Minuten","tasks":"Aufgaben"};
function update() {
renderPlan(root, selectTasks(tasks, filter.value), labels);
}
filter.addEventListener('change', update);
update();
filter.parentElement.hidden = false;
example-de.html
<!doctype html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Aufgaben nach Bereich</title><link rel="stylesheet" href="./example.css"><script type="module" src="./main-de.mjs"></script></head><body><main><h1>Aufgaben nach Bereich</h1><p>Drei fiktive Aufgaben mit geplanten Minuten. Keine gemessenen Arbeitszeiten.</p><div hidden><label for="category">Bereich</label> <select id="category"><option value="all">Alle Aufgaben</option><option value="planning">Planung</option><option value="technical">Technik</option></select></div><section id="plan" aria-label="Aufgabenübersicht"><ul><li data-id="17">Planung: 45 Minuten</li><li data-id="8">Datenabgleich: 15 Minuten</li><li data-id="22">Nachweis: 30 Minuten</li></ul><p role="status">3 Aufgaben · 90 Minuten</p></section><noscript><p>Die vollständige Aufgabenübersicht steht oben.</p></noscript></main></body></html>
example.css
[hidden]{display:none!important}:root{font-family:Arial,sans-serif;color:#192329;background:#fffaf3;color-scheme:light dark}body{max-width:46rem;margin:2rem auto;padding:0 1rem;line-height:1.6}select{font:inherit;padding:.4rem;max-width:100%}:focus-visible{outline:3px solid #b80024;outline-offset:4px}li{padding:.4rem 0}section{border:1px solid #77838b;padding:1rem;border-radius:.6rem}[role=status]{font-weight:bold}@media(prefers-color-scheme:dark){:root{color:#fffaf3;background:#192329}:focus-visible{outline-color:#ff7794}}
Benannte Exporte machen den verwendeten Vertrag auffindbar
In diesem Aufbau heißen die Exporte ausdrücklich tasks, selectTasks und renderPlan. Beim Lesen des Einstiegs ist dadurch erkennbar, welche Fähigkeit aus welcher Datei verwendet wird. Benannte Exporte sind hier eine praktische Entwurfswahl und kein Verbot anderer Modulformen. Auch ein Standardexport kann sinnvoll sein. Entscheidend ist, dass seine Bedeutung am Aufruf verständlich bleibt und Änderungen am öffentlichen Vertrag bewusst erfolgen. Ein kurzer Dateiname wie Hilfen ersetzt diese fachliche Aussage nicht.
Zusammenfassende Exportdateien verdienen dieselbe Aufmerksamkeit. Eine zentrale Datei, die vorsorglich alles aus allen Bereichen weiterreicht, kann tatsächliche Abhängigkeiten verdecken. Eine kleine fachliche Schnittstelle kann dagegen einen stabilen Einstieg für einen zusammengehörenden Bereich bilden. Im Beispiel wäre eine solche Zusammenfassung zusätzlicher Aufwand ohne nachgewiesenen Nutzen. Die direkten Importe zeigen den gesamten kleinen Aufbau bereits vollständig. Erst eine größere tatsächliche Verwendung würde eine weitere öffentliche Grenze rechtfertigen.
Importbindungen sind keine vollständige Unveränderlichkeit
Eine importierte Bindung kann vom importierenden Modul nicht einfach neu zugewiesen werden. Daraus folgt jedoch nicht, dass ein exportiertes Objekt automatisch unveränderlich wäre. Andere Module könnten seine Eigenschaften verändern, wenn die Objektstruktur solche Änderungen zulässt. Die getrennte Entscheidung zum Einfrieren unserer Lehrdaten ist deshalb wesentlich. Wer nur auf das Schlüsselwort für den Import schaut, übersieht möglicherweise gemeinsam veränderten Zustand.
Für eine Anwendung mit veränderlichem Zustand wäre ein klar benannter Besitzer hilfreicher. Dieser Besitzer könnte Änderungen über definierte Funktionen durchführen und anderen Teilen passende Momentaufnahmen liefern. Das ist eine mögliche Weiterentwicklung und im vorliegenden Beispiel bewusst nicht eingebaut. Es gibt hier weder einen globalen Datenspeicher noch ein Ereignissystem für fachliche Änderungen. Die Auswahl ist eine Ableitung aus drei unveränderten Aufgaben. Diese kleine Anforderung rechtfertigt eine kleine Zustandslösung.
Zyklische Abhängigkeiten an einem echten Gegenfall verstehen
Für eine Gegenprobe wurden zwei zusätzliche Module erstellt. Das erste importiert einen Wert aus dem zweiten und berechnet daraus sofort seinen eigenen exportierten Wert. Das zweite importiert wiederum den ersten Wert und versucht ebenfalls sofort zu rechnen. Der tatsächliche Node-Lauf endet mit einem Referenzfehler, weil eine benötigte Bindung zu diesem Zeitpunkt noch nicht initialisiert ist. Diese Gegenprobe wird getrennt vom funktionierenden Aufgabenbeispiel aufbewahrt.
Der Versuch beweist nicht, dass jeder Importkreis in JavaScript grundsätzlich verboten wäre. Manche zyklischen Beziehungen lassen sich ausführen, solange die betroffenen Werte erst zu einem passenden späteren Zeitpunkt verwendet werden. Für eine kleine fachliche Anwendung ist ein solcher Kreis dennoch ein guter Anlass, die Verantwortungen zu prüfen. Häufig gehört die gemeinsame Regel in einen dritten, unabhängigen Baustein. Eine Verzögerung mit Zeitgebern würde den Ablauf schwerer verständlich machen und wäre ohne weitere Begründung keine saubere fachliche Lösung.
Die Prüfungen auf beobachtbare Eigenschaften ausrichten
| Prüfbereich | Tatsächlich untersuchte Eigenschaft | Begrenzung |
|---|---|---|
| Fachfunktion | Vier Bestandsgrößen mit je drei Kategorien, Reihenfolge, Summe und unveränderte Eingabe | Eigenes begrenztes Aufgabenmodell |
| Eingabefehler | Doppelte Kennung, zusätzliche Felder, ungültige Werte und unbekannter Bereich werden abgewiesen | Keine allgemeine Prüfung beliebiger Fremdobjekte |
| Browserausgabe | Auswahl, Summe, erhaltener Fokus und wörtliche Ausgabe eines HTML-artigen Titels | Ein tatsächlicher DOM-Ausgabekontext |
| Ausfall | Ohne JavaScript und bei fehlendem Adapter bleiben drei statische Aufgaben sichtbar | Keine automatische Reparatur oder erneute Ladefunktion |
Insgesamt wurden 231 Prüfbedingungen ausgeführt. Die Browserstrecke umfasst sechzehn Fälle in beiden Sprachen. Reguläre Ansichten wurden bei 320, 390 und 1440 Pixeln sowie in heller und dunkler Darstellung untersucht. Weitere Fälle betreffen fehlendes JavaScript und einen gezielt erzeugten Modulfehler. Die Zahlen beschreiben den tatsächlich ausgeführten Prüfumfang. Sie sind keine Qualitätsnote und keine Aussage über sämtliche Browser oder assistiven Technologien.
Eine Änderung entlang ihrer Grenze weiterentwickeln
Soll künftig ein zusätzlicher Bereich angeboten werden, betrifft das den erlaubten Wertebereich der Fachfunktion, passende Daten und das Auswahlfeld. Eine andere Gestaltung der Liste betrifft dagegen den Adapter und das Stylesheet. Eine andere Sprache betrifft die Beschriftungen und den Einstieg. Diese Zuordnung ist beim tatsächlichen kleinen Aufbau sichtbar. Sie verspricht nicht, dass jede zukünftige Anforderung nur genau eine Datei verändern wird. Manche fachlichen Änderungen betreffen berechtigt mehrere Schichten.
Ein Review sollte deshalb fragen, ob jede veränderte Datei einen nachvollziehbaren Grund hat. Muss die Darstellung plötzlich Berechtigungen berechnen oder der Katalog ein Dialogfenster öffnen, ist die Grenze wahrscheinlich verrutscht. Muss die Fachfunktion für eine andere Sprache kopiert werden, wurde möglicherweise Inhalt mit Beschriftung verwechselt. Solche Beobachtungen sind konkreter als eine pauschale Forderung nach sauberer Architektur. Sie helfen auch einem kleinen Team, Änderungen ohne zusätzliche Rahmenwerke zu beurteilen.
Modulstruktur und Auslieferung getrennt entscheiden
Mehrere Module bedeuten nicht automatisch, dass Zusatzcode erst bei Bedarf geladen wird. Der statische Einstieg dieses Beispiels benötigt seine drei Abhängigkeiten unmittelbar für den Start. Wer einen wirklich späteren Ladevorgang benötigt, muss diese Grenze ausdrücklich mit einem passenden Ablauf verbinden. Ebenso wenig folgt aus der Dateiaufteilung eine bestimmte Übertragungsgröße oder Ladezeit. Solche Aussagen verlangen eigene Messungen unter benannten Bedingungen.
Beim Veröffentlichen müssen zusammenpassende Dateifassungen erreichbar bleiben. Eine bereits geöffnete Seite kann noch einen älteren Einstieg besitzen. Werden zugehörige Dateien ersatzlos entfernt oder öffentliche Exportnamen ohne passenden Übergang verändert, entsteht trotz guter Quellstruktur ein Laufzeitfehler. Die Modulgrenzen helfen dabei, den Vertrag zu erkennen. Die Entscheidung über Versionierung, Cache-Regeln und Rückwege bleibt eine zusätzliche Betriebsaufgabe. Sie sollte ebenso ausdrücklich geprüft werden wie die Funktion im Entwicklungsverzeichnis.
Checkliste für verständliche Modulgrenzen
Vor einer Übernahme in ein anderes Projekt lohnt sich außerdem ein genauer Blick auf die Modellgrenzen. Die Funktion akzeptiert gewöhnliche Datensätze, wie sie im eigenen Beispiel erzeugt werden. Sie ist kein Schutz gegen beliebigen ausführbaren JavaScript-Code. Ein fremdes Objekt könnte etwa spezielle Eigenschaftszugriffe besitzen. Für eine nicht vertrauenswürdige Datenquelle wäre deshalb bereits das Einlesen und Umwandeln in ein begrenztes Datenformat zu regeln. Diese Aufgabe wird durch die schöne Form einer Modulschnittstelle weder erledigt noch überflüssig.
Auch eine vollständig eingefrorene Ergebnisstruktur ersetzt keine fachliche Prüfung der Planung. Die Summe von 75 Minuten für die Kategorie Planung stimmt mit den beiden erfundenen Einträgen überein. Ob solche Zeiten für einen wirklichen Auftrag angemessen wären, wurde nicht untersucht. Gerade kleine Lehrbeispiele sollten ihre Zahlen nicht stillschweigend zu Erfahrungswerten aufwerten. Der Nutzen liegt hier in der reproduzierbaren Auswahl und in der unveränderten Eingabe. Eine reale Aufwandsschätzung braucht einen eigenen fachlichen Kontext.
Für das Team lässt sich aus dieser Trennung eine kurze Änderungsbeschreibung ableiten. Statt lediglich neue Dateien aufzuzählen, benennt sie die neue Entscheidung und den dazugehörigen Nachweis. Beispielsweise könnte eine Änderung erklären, dass die technische Kategorie nun eine weitere Aufgabe enthält und alle bisherigen Kategorien weiterhin dieselben Einträge behalten. Ein Gestaltungswechsel könnte zeigen, dass nur die Darstellung geändert wurde und dieselben fachlichen Ergebnisse ankommen. Solche Beschreibungen machen eine Prüfung wesentlich gezielter als eine allgemeine Meldung über überarbeiteten Code.
Die Schichten müssen dabei nicht größer sein als ihre Aufgabe. Wenn zwei Funktionen immer gemeinsam geändert werden und denselben kleinen Vertrag umsetzen, können sie sinnvoll in einer Datei bleiben. Wenn ein Adapter nur an einer Stelle verwendet wird, braucht er nicht vorsorglich ein erweiterbares Stecksystem. Eine weitere Grenze ist dann nützlich, wenn sie eine tatsächliche Unabhängigkeit sichtbar macht. Das Beispiel verwendet bewusst einfache Funktionen und normale Modulimporte. Seine Aussagen hängen weder von einem bestimmten Paketverzeichnis noch von einer zusätzlichen Baukonfiguration ab.
- Die konkrete Änderungsfrage vor dem Aufteilen der Dateien formulieren.
- Eingabe, Ergebnis und Fehlerverhalten jeder öffentlichen Funktion benennen.
- Fachliche Regeln ohne Dokument und Browserzustand ausführbar halten.
- Darstellung mit einem bereits berechneten Ergebnis versorgen.
- Listener und Startentscheidungen an einem erkennbaren Einstieg bündeln.
- Gemeinsam veränderte Objekte ausdrücklich vermeiden oder einem Besitzer zuordnen.
- Importverbindungen tatsächlich aufzeichnen und unerwartete Kreise untersuchen.
- Statische Grundinformationen bei fehlender Erweiterung erhalten.
- Ausgeführten Prüfumfang von allgemeinen Qualitätsversprechen trennen.
- Zusammenpassende Dateiversionen und einen kontrollierten Rückweg veröffentlichen.
Eine tragfähige Modulstruktur zeigt am Ende, wer die Entscheidung trifft, wer das Ergebnis darstellt und wer beide verbindet. Im Aufgabenbeispiel lässt sich diese Aussage mit denselben Dateien im Browser und ohne Browser überprüfen. Genau diese Nachvollziehbarkeit ist der Nutzen der Aufteilung. Die Anzahl der Dateien allein erklärt ihn nicht.
Quellen und fachliche Einordnung
Die folgenden offiziellen Quellen wurden am 9. November 2026 tatsächlich aufgerufen. Sie erklären Sprache und Laufzeit. Der konkrete Aufgabenaufbau und seine Ergebnisse stammen aus dem eigenen ausgeführten Beispiel.







