Skill: Feature-Design vorschlagen
Zweck
Erstellen eines technischen Design-Dokuments, das die Implementierung leitet. Dies liefert Architektur, Muster und Designentscheidungen, ohne den eigentlichen Code zu schreiben.
Wann verwenden
- Feature-Konzept und Anforderungen existieren
- Bereit, den Implementierungsansatz zu planen
- Benötigt Dokumentation von Architektur und Entwurfsmustern
Voraussetzungen
- Feature-Konzept existiert in
docs/features/NNNN-feature-name/concept.md - Anforderungen existieren in
docs/features/NNNN-feature-name/requirements.md - Benutzer versteht den technischen Ansatz
Vorgehen
1. Voraussetzungen prüfen
# Prüfen, ob Konzept und Anforderungen existieren
ls ./docs/features/NNNN-feature-name/concept.md
ls ./docs/features/NNNN-feature-name/requirements.md
Wenn eines davon fehlt, diese Schritte zuerst ausführen.
2. Prüfen auf Idea-Honing-Dokument
ls ./planning/NNNN-feature-name/idea-honing.md 2>/dev/null
Falls vorhanden, auf Design-Einblicke und technische Überlegungen prüfen, die während des Idea-Honings besprochen wurden.
3. Design-Vorlage kopieren
cp ./docs/features/0000-templates/design.md ./docs/features/NNNN-feature-name/
4. Übersicht ausfüllen
Eine allgemeine Beschreibung der Architektur und des Design-Ansatzes schreiben. Auf das Konzept und die Anforderungen verweisen.
5. Kritische Randbedingungen identifizieren
Für jede Schlüsseloperation fragen:
- Was wäre ein FALSCHER Weg, dies zu implementieren?
- Welche Leistungsmerkmale sind erforderlich?
- Welche Invarianten müssen gelten?
Die Tabelle der kritischen Randbedingungen ausfüllen mit:
- ID: CC-1, CC-2, usw.
- Randbedingung: Was MUSS auf eine bestimmte Weise gemacht werden
- Begründung: Warum (Leistung, Korrektheit, Sicherheit)
- Anti-Pattern: Der falsche Ansatz, der bei der Überprüfung abgelehnt werden soll
Dies ist der wichtigste Abschnitt, um Implementierungsfehler zu vermeiden. Sei konkret – vage Randbedingungen helfen nicht.
6. Architektur definieren
Die Gesamtstruktur beschreiben:
- Komponentenbeziehungen
- Datenfluss
- Schichtenverantwortlichkeiten
- Integrationspunkte
Einfache Diagramme mit ASCII-Art verwenden, falls hilfreich.
7. Lösungsmechanik erklären
Dieser Abschnitt überbrückt das „Warum“ (Konzept) mit dem „Was“ (Architektur). Für jede im Konzept identifizierte Kernherausforderung erklären, wie das Design sie adressiert.
Für jede Herausforderung beantworten:
- Was ist das grundlegende Problem? (aus concept.md)
- Welches architektonische Element adressiert es?
- Warum funktioniert dieser Ansatz?
- Was würde fehlschlagen, wenn wir es anders machen würden?
Als Tabelle oder strukturierte Liste formatieren:
| Herausforderung | Architektonisches Element | Warum es funktioniert |
|---|---|---|
| Herausforderung aus Konzept | Komponente/Muster, die es adressiert | Erklärung des Mechanismus |
Hilfreiche Fragen für Autoren:
- „Wenn jemand fragt ‚Wie löst dies X?‘, kann ich auf eine bestimmte Komponente zeigen?“
- „Würde ein neuer Ingenieur verstehen, warum dieses Design gegenüber Alternativen ausgewählt wurde?“
- „Hat jede Hauptkomponente einen klaren Grund für ihre Existenz, der mit einem Problem verbunden ist?“
Dieser Abschnitt sollte Prüfern das Vertrauen geben, dass das Design die genannten Probleme tatsächlich löst und nicht nur eine plausible Codestruktur beschreibt.
8. Domänenmodell definieren
Die Kern-Typen und -Operationen festlegen:
Typen
- Zweck und Rolle
- Schlüsseleigenschaften
- Validierungsregeln
- Beziehungen zu anderen Typen
Operationen
- Funktionssignaturen (konzeptionell)
- Was sie tun
- Wichtige Verhaltensweisen
- Invarianten (was immer wahr sein muss)
9. Modulstruktur definieren
Zeigen, wie der Code organisiert sein sollte:
- Verzeichnisstruktur
- Modulverantwortlichkeiten
- Dateiorganisation
- Trennung der Belange
Modulgrößenlimit: Dieses Projekt erzwingt ein Limit von 550 Zeilen pro Modul (siehe scripts/lint_loc.py).
Beim Entwerfen von Modulen bedenken, ob eine Komponente dieses Limit überschreiten könnte.
Falls ja, die interne Aufteilung vorausplanen – nach Fähigkeit aufteilen (z. B. builder.rs, searcher.rs), nicht nach Artefakttyp.
Die Ausgabe des Linters enthält bei Überschreitung des Limits eine Umstrukturierungsanleitung.
Impl-Blöcke zusammenhalten: Alle impl-Blöcke eines Typs sollten in einer Datei leben.
Das Verteilen von impl-Blöcken auf verschiedene Dateien erschwert es Lesern (und KI), ein vollständiges Bild davon zu bekommen, was ein Typ tut.
Wenn die Implementierung eines Typs zu groß ist, an Hilfsfunktionen oder interne Komponententypen delegieren, anstatt den impl-Block selbst aufzuteilen.
// ✅ Gut: Ein einzelner impl-Block delegiert an Helfer
impl KnowledgeIndex {
pub fn build(&self, path: &Path) -> Result<()> {
self.builder.build(path) // delegiert an interne Komponente
}
}
// ❌ Schlecht: impl-Blöcke aufgeteilt auf mehrere Dateien
// facade/mod.rs: impl KnowledgeIndex { fn new() ... }
// facade/build.rs: impl KnowledgeIndex { fn build() ... }
// facade/search.rs: impl KnowledgeIndex { fn search() ... }
10. Entwurfsmuster dokumentieren
Relevante Muster beschreiben und warum sie anwendbar sind:
- Welche Muster verwenden
- Wie sie zum Problem passen
- Implementierungsleitfaden
11. Designentscheidungen dokumentieren
Für bedeutende Entscheidungen zwischen Alternativen Einträge im Abschnitt Designentscheidungen hinzufügen:
- Was entschieden wurde
- Welche Alternativen in Betracht gezogen wurden
- Warum diese Option gewählt wurde
- Was dies für die Implementierung bedeutet
Dies schafft eine Aufzeichnung, die Implementierern hilft, die Überlegungen zu verstehen.
12. Implementierungsleitfaden hinzufügen
Wichtige Überlegungen für Implementierer:
- Auf kritische Randbedingungen per ID verweisen
- Leistungsüberlegungen
- Testansatz
- Grenzfälle, die behandelt werden müssen
13. Code minimal halten
Erinnern:
- Minimalen erläuternden Code verwenden
- Fokus auf Architektur und Entscheidungen
- Implementierer leiten, nicht implementieren
- Bei Bedarf auf Anforderungen per ID verweisen
Validierung
Das Design-Dokument überprüfen:
# Prüfen, ob Datei existiert
ls ./docs/features/NNNN-feature-name/design.md
# Prüfen, ob Inhalt vorhanden ist
head -50 ./docs/features/NNNN-feature-name/design.md
Häufige Probleme
Zu viel Code: Wenn große Codeblöcke vorhanden sind, diese entfernen und auf Leitlinien konzentrieren.
Zu abstrakt: Wenn das Design vage ist, konkrete Typnamen und Modulstruktur hinzufügen.
Fehlende Architektur: Sicherstellen, dass die Gesamtstruktur klar ist, bevor in Details eingetaucht wird.
Kein Bezug zu Anforderungen: Designentscheidungen mit spezifischen Anforderungs-IDs verknüpfen.
Fehlende Lösungsmechanik: Wenn das Design die Struktur beschreibt, aber nicht, warum es das Problem löst, den Abschnitt Lösungsmechanik hinzufügen, der Herausforderungen auf architektonische Elemente abbildet.
Nächste Schritte
Nach dem Erstellen des Designs:
- Mit Implementierern auf Machbarkeit prüfen
- Basierend auf Feedback verfeinern
- Sobald das Design solide ist, Testplan mit dem Skill
propose-feature-test-planerstellen - Dann Implementierungsplan mit dem Skill
propose-implementation-planerstellen