Communitygithub.com

Castle-Solutions/landing

Gemeinsames Vokabular für das Design tiefer Module. Verwenden Sie dies, wenn der Benutzer das Interface eines Moduls entwerfen oder verbessern, Vertiefungsmöglichkeiten finden, entscheiden möchte, wo eine Naht verläuft, Code testbarer oder KI-navigierbar machen möchte oder wenn eine andere Fähigkeit das Vokabular für tiefe Module benötigt.

Was ist landing?

Diese Fähigkeit, 'Castle-Solutions/landing', definiert ein präzises, geteiltes Vokabular für das Design tiefer Module – Module mit viel Verhalten hinter einer kleinen Schnittstelle. Anstatt vager Begriffe wie 'Komponente' oder 'Service' zu verwenden, führt sie exakte Konzepte wie Modul, Schnittstelle, Tiefe oder Naht ein. Entwickler können damit Interfaces effizienter entwerfen, überarbeiten und bewerten – sei es für eine einzelne Funktion oder einen systemweiten Dienst. Dabei steht die Nutzenhebelwirkung für Aufrufer und die Lokalität für Wartende im Vordergrund. Die Fähigkeit ist werkzeugagnostisch und kann mit Claude Code, Cursor, Codex oder anderen KI-basierten Entwicklungswerkzeugen genutzt werden. Sie bietet ein gemeinsames Referenzsystem, um Designentscheidungen präzise zu kommunizieren und die Testbarkeit sowie Navigierbarkeit durch KI zu verbessern.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Castle-Solutions/landing/tree/HEAD/.agents/skills/codebase-design

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Codebase-Design

Entwerfen Sie tiefe Module: viel Verhalten hinter einer kleinen Schnittstelle, platziert an einer sauberen Naht, testbar durch diese Schnittstelle. Verwenden Sie diese Sprache und diese Prinzipien, wo immer Code entworfen oder umstrukturiert wird. Das Ziel ist Hebelwirkung für Aufrufer, Lokalität für Wartende und Testbarkeit für alle.

Glossar

Verwenden Sie diese Begriffe genau: Ersetzen Sie nicht durch „Komponente“, „Service“, „API“ oder „Grenze“. Konsistente Sprache ist der entscheidende Punkt.

Modul: alles mit einer Schnittstelle und einer Implementierung. Bewusst skalierungsneutral: eine Funktion, Klasse, ein Paket oder ein bereichsübergreifender Schnitt. Vermeiden Sie: Einheit, Komponente, Service.

Schnittstelle (Interface): alles, was ein Aufrufer wissen muss, um das Modul korrekt zu nutzen: die Typsignatur, aber auch Invarianten, Reihenfolge-Einschränkungen, Fehlermodi, erforderliche Konfiguration und Leistungsmerkmale. Vermeiden Sie: API, Signatur (zu eng; sie beziehen sich nur auf die Typebene).

Implementierung: was sich innerhalb eines Moduls befindet, sein Codekörper. Abzugrenzen von Adapter: ein Ding kann ein kleiner Adapter mit einer großen Implementierung (ein Postgres-Repository) oder ein großer Adapter mit einer kleinen Implementierung (ein In-Memory-Fake) sein. Greifen Sie zu „Adapter“, wenn die Naht das Thema ist; andernfalls „Implementierung“.

Tiefe (Depth): Hebelwirkung an der Schnittstelle. Die Menge an Verhalten, die ein Aufrufer (oder ein Test) pro Einheit der Schnittstelle, die er lernen muss, ausüben kann. Ein Modul ist tief, wenn eine große Menge an Verhalten hinter einer kleinen Schnittstelle steckt; flach, wenn die Schnittstelle fast so komplex ist wie die Implementierung.

Naht (Seam) (Michael Feathers): ein Ort, an dem Sie das Verhalten ändern können, ohne an dieser Stelle zu editieren; der Ort, an dem die Schnittstelle eines Moduls lebt. Wo die Naht platziert wird, ist eine eigene Designentscheidung, getrennt von dem, was dahinter liegt. Vermeiden Sie: Grenze (überladen mit DDDs Bounded Context).

Adapter: ein konkretes Ding, das eine Schnittstelle an einer Naht erfüllt. Beschreibt die Rolle (welchen Slot es füllt), nicht die Substanz (was darin steckt).

Hebelwirkung (Leverage): was Aufrufer aus der Tiefe gewinnen. Mehr Fähigkeit pro Einheit der Schnittstelle, die sie lernen. Eine Implementierung zahlt sich über N Aufrufstellen und M Tests aus.

Lokalität (Locality): was Wartende aus der Tiefe gewinnen. Änderungen, Fehler, Wissen und Verifikation konzentrieren sich an einem Ort, anstatt sich über Aufrufer zu verteilen. Einmal repariert, überall repariert.

Tief vs. flach

Tiefes Modul = kleine Schnittstelle + viel Implementierung:

┌─────────────────────┐
│   Kleine Schnittst. │  ← Wenige Methoden, einfache Parameter
├─────────────────────┤
│                     │
│ Tiefe Implementierung│  ← Komplexe Logik verborgen
│                     │
└─────────────────────┘

Flaches Modul = große Schnittstelle + wenig Implementierung (vermeiden):

┌─────────────────────────────────┐
│       Große Schnittstelle       │  ← Viele Methoden, komplexe Parameter
├─────────────────────────────────┤
│  Dünne Implementierung          │  ← Leitet nur durch
└─────────────────────────────────┘

Wenn Sie eine Schnittstelle entwerfen, fragen Sie:

  • Kann ich die Anzahl der Methoden reduzieren?
  • Kann ich die Parameter vereinfachen?
  • Kann ich mehr Komplexität im Inneren verbergen?

Prinzipien

  • Tiefe ist eine Eigenschaft der Schnittstelle, nicht der Implementierung. Ein tiefes Modul kann intern aus kleinen, mockbaren, austauschbaren Teilen bestehen; sie sind nur nicht Teil der Schnittstelle. Ein Modul kann interne Nähte (privat für seine Implementierung, von seinen eigenen Tests verwendet) sowie die externe Naht an seiner Schnittstelle haben.
  • Der Löschtest. Stellen Sie sich vor, Sie löschen das Modul. Wenn die Komplexität verschwindet, war es ein Durchgangsstück. Wenn die Komplexität an N Aufrufern wieder auftaucht, hat es sich bezahlt gemacht.
  • Die Schnittstelle ist die Testoberfläche. Aufrufer und Tests überqueren dieselbe Naht. Wenn Sie hinter die Schnittstelle testen wollen, hat das Modul wahrscheinlich die falsche Form.
  • Ein Adapter bedeutet eine hypothetische Naht. Zwei Adapter bedeuten eine echte. Führen Sie keine Naht ein, es sei denn, etwas variiert tatsächlich über sie hinweg.

Entwerfen für Testbarkeit

Gute Schnittstellen machen das Testen natürlich:

  1. Abhängigkeiten akzeptieren, nicht erzeugen.

    // Testbar
    function processOrder(order, paymentGateway) {}
    
    // Schwer zu testen
    function processOrder(order) {
      const gateway = new StripeGateway();
    }
    
  2. Ergebnisse zurückgeben, keine Seiteneffekte erzeugen.

    // Testbar
    function calculateDiscount(cart): Discount {}
    
    // Schwer zu testen
    function applyDiscount(cart): void {
      cart.total -= discount;
    }
    
  3. Kleine Oberfläche. Weniger Methoden = weniger benötigte Tests. Weniger Parameter = einfachere Testeinrichtung.

Beziehungen

  • Ein Modul hat genau eine Schnittstelle (die Oberfläche, die es Aufrufern und Tests präsentiert).
  • Tiefe ist eine Eigenschaft eines Moduls, gemessen an seiner Schnittstelle.
  • Eine Naht ist der Ort, an dem die Schnittstelle eines Moduls lebt.
  • Ein Adapter sitzt an einer Naht und erfüllt die Schnittstelle.
  • Tiefe erzeugt Hebelwirkung für Aufrufer und Lokalität für Wartende.

Abgelehnte Rahmen

  • Tiefe als Verhältnis von Implementierungszeilen zu Schnittstellenzeilen (Ousterhout): belohnt das Aufblähen der Implementierung. Wir verwenden stattdessen Tiefe-als-Hebelwirkung.
  • „Schnittstelle“ als das TypeScript-interface-Schlüsselwort oder die öffentlichen Methoden einer Klasse: zu eng: Schnittstelle umfasst hier jede Tatsache, die ein Aufrufer wissen muss.
  • „Grenze“: überladen mit DDDs Bounded Context. Sagen Sie Naht oder Schnittstelle.

Tiefer gehen

  • Vertiefen eines Clusters bei gegebenen Abhängigkeiten, siehe DEEPENING.md: Abhängigkeitskategorien, Nahtdisziplin und Testen durch Ersetzen statt Schichten.
  • Alternative Schnittstellen erkunden, siehe DESIGN-IT-TWICE.md: parallele Sub-Agenten starten, um die Schnittstelle auf mehrere radikal unterschiedliche Weisen zu entwerfen, dann anhand von Tiefe, Lokalität und Nahtplatzierung vergleichen.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Verwandte Skills