Suche/Ein Framework entwickeln, das eine API für mehrere Programmiersprachen bereitstellt

Ein Framework entwickeln, das eine API für mehrere Programmiersprachen bereitstellt

Für Frameworks, die aus einer Codebasis Pakete für mehrere Sprachen erzeugen. Legt Regeln fest für das JSON-Protokoll zwischen Prozessen, exportierbare Typen, Codeerzeugung und Tests, die gleiches Verhalten in allen Sprachen prüfen.

Diese KI-Regeln verwenden
## In jeder Sprache gleiches Verhalten und Abwärtskompatibilität bewahren Ein sprachübergreifendes Framework muss auf Verhalten ausgerichtet sein, das in jeder unterstützten Sprache verständlich und gleichwertig bleibt, und nicht auf jede Ausdrucksform, die in seiner Implementierungssprache verfügbar ist. ### Zentrale Invarianten - Bewahren Sie die Abwärtskompatibilität des Assembly-Formats, des Laufzeitprotokolls und der öffentlichen APIs. - Verlangen Sie ein gleichwertiges beobachtbares Verhalten in allen unterstützten Zielsprachen. - Erzeugen Sie Code, der den üblichen Benennungs-, Paketierungs- und Typkonventionen der jeweiligen Zielsprache folgt. - Akzeptieren Sie nur Merkmale der Ausgangssprache, die sich in jeder Zielsprache getreu darstellen lassen. - Geben Sie Korrektheit und Interoperabilität den Vorrang vor zielsprachenspezifischen Abkürzungen zur Leistungssteigerung. ### Paketgrenzen - Trennen Sie Protokollkern, Hostlaufzeiten, Schemadefinitionen, Codegeneratoren, Reflexionswerkzeuge, Kompatibilitätsprüfungen und Testvorrichtungen voneinander. - Halten Sie Buildwerkzeuge und Konformitätsberichte aus den Laufzeitpaketen heraus. - Behandeln Sie jede Sprachlaufzeit und jede optionale Integration als eigenständig verantwortetes Paket. - Platzieren Sie gemeinsame Testvorrichtungen so, dass alle Compiler-, Generator- und Laufzeittests dieselben Verhaltensfälle verwenden können. - Binden Sie Komponenten, die in getrennten Repositories gepflegt werden, über ausdrückliche versionierte Abhängigkeiten ein. ## Code in einem Kernel-Prozess ausführen, der per JSON mit jeder Sprache spricht Verwenden Sie ein zweiseitiges Laufzeitmodell, wenn Hostsprachen die Implementierungssprache nicht direkt ausführen können. Der Hostprozess kommuniziert über JSON-Nachrichten auf der Standardeingabe und Standardausgabe mit einem Kernelprozess, während die gesamte Ausführung in der Implementierungssprache im Kernel verbleibt. ### Prozessgrenze - Versehen Sie jede Anfrage mit einer eindeutigen Operationskennung. - Decken Sie das Laden von Assemblies, den Objektlebenszyklus, Methodenaufrufe, Eigenschaftszugriffe, asynchrone Arbeit, Statistiken und Rückrufe durch getrennte Protokolloperationen ab. - Verwenden Sie einen zusätzlichen Wrapperprozess nur dann, wenn eine Hostlaufzeit die vom Kernprozess benötigten Dateideskriptoren nicht beibehalten kann. - Leiten Sie Diagnoseausgaben über den Fehlerausgabestrom, damit sie den Protokollstrom nicht beschädigen können. ### Rückrufabfolge Wenn Code in der Implementierungssprache eine von der Hostsprache überschriebene Methode oder Eigenschaft erreicht: 1. Der Kernel sendet anstelle der ursprünglichen Antwort eine Rückrufanfrage. 2. Der Host führt die Überschreibung aus und gibt eine Abschlussnachricht mit entweder dem Ergebnis oder dem Fehler zurück. 3. Der Kernel setzt die ursprüngliche Operation fort und gibt deren tatsächliche Antwort zurück. ### Protokollweiterentwicklung - Behandeln Sie Anfragenamen, Feldbedeutungen, Antwortreihenfolge und Rückrufabfolge als Kompatibilitätsverträge. - Aktualisieren Sie bei Protokolländerungen alle Hostlaufzeiten gemeinsam. - Fügen Sie Kompatibilitätstests hinzu, bevor Sie die Form einer Nachricht oder eine Lebenszyklusregel ändern. ## Festlegen, ob Werte zwischen Sprachen als Kopie oder als Referenz übergeben werden Definieren Sie für jede portable Wertekategorie eine Übertragungsdarstellung und machen Sie die Eigentumssemantik sichtbar. Ein Wert, der als Kopie übertragen wird, darf nicht mit einem Objekt verwechselt werden, das weiterhin dem Kernel gehört. ### Übertragungsdarstellung - Übertragen Sie boolesche Werte, Zahlen und Zeichenketten als Wert in ihrer JSON-Darstellung. - Übertragen Sie Listen und Zuordnungen als Wert und verwenden Sie bei Bedarf eine ausdrücklich gekennzeichnete Hülle, um sie von anderen Objekten zu unterscheiden. - Codieren Sie Aufzählungswerte mit einer vollständig qualifizierten Elementkennung. - Codieren Sie Datumswerte mit einer gekennzeichneten, eindeutigen Zeitstempeldarstellung. - Codieren Sie reine Datenstrukturen mit ihrem vollständig qualifizierten Typ und ihren Felddaten. - Codieren Sie Klasseninstanzen als Referenz mit einer stabilen Objektkennung. ### Grenzregeln - Bewahren Sie UTF-8-Zeichenketten, das Verhalten von Gleitkommazahlen, die Null-Zulässigkeit und die Kopiersemantik von Sammlungen sprachübergreifend. - Halten Sie gekennzeichnete Übertragungsschlüssel stabil, sobald Verbraucher von ihnen abhängen. - Geben Sie Objektreferenzen ausdrücklich frei, wenn das Protokoll den entfernten Lebenszyklus verwaltet. - Testen Sie Hin- und Rückübertragungen durch jede Hostlaufzeit und nicht nur auf der Seite der Implementierungssprache. ## Nur Typen exportieren, die jede Sprache abbilden kann Wenden Sie Portabilitätsbeschränkungen auf Deklarationen an, die vom Haupteinstiegspunkt des Moduls exportiert werden, während interner Implementierungscode weitergehende Sprachmerkmale verwenden darf. ### Portable API-Oberfläche - Unterstützen Sie primitive Typen, Listen, Zuordnungen, Aufzählungen, Datumswerte, Klassen, Schnittstellen, Datenstrukturen, Promises und opake Werte nur dort, wo jede Zielsprache über eine typsichere Darstellung verfügt. - Unterscheiden Sie verhaltensbezogene Schnittstellen von reinen Datenstrukturen durch eine ausdrückliche Benennungs- oder Schemaregel. - Verlangen Sie, dass reine Datenstrukturen ausschließlich schreibgeschützte Eigenschaften und keine Methoden enthalten. - Erlauben Sie Promises nur an Positionen, die jede Zielsprache einheitlich bereitstellen kann, etwa als Rückgabetypen von Methoden. - Behandeln Sie opake Werte als implizit nullzulässig, wenn statisch typisierte Zielsprachen keinen genaueren Typ ermitteln können. - Übergeben Sie Klassen als Referenz und wertähnliche Strukturen als Kopie. ### Beschränkungen - Lehnen Sie nicht unterstützte exportierte Konstrukte wie Tupel, unbewohnbare Typen, Ganzzahlen beliebiger Genauigkeit, Symbole und Methodenüberladungen ab. - Verlangen Sie für überschreibende Methoden exakt kompatible Signaturen; verlassen Sie sich weder auf kovariante Rückgabetypen noch auf kontravariante Parameter. - Vermeiden Sie Vereinigungen, wenn sie in statisch typisierten Zielsprachen zu einem untypisierten Objekt zusammenfallen. - Lassen Sie keine Vererbung zwischen verhaltensbezogenen Schnittstellen und reinen Datenstrukturen zu. ## Das Paket jeder Sprache aus derselben kompilierten Assembly erzeugen Erzeugen Sie jedes Sprachziel aus derselben kompilierten Assembly, damit für alle Zielpakete dieselbe maßgebliche API-Quelle gilt. ### Erzeugungskette 1. Lesen Sie die Assembly aus dem kompilierten Paket der Implementierungssprache. 2. Erzeugen Sie idiomatischen Quellcode für die ausgewählte Zielsprache. 3. Kompilieren Sie den erzeugten Quellcode mit der Werkzeugkette dieser Sprache. 4. Paketieren Sie das Ergebnis mit dem üblichen Paketmanager des Zielökosystems. ### Gestaltung der Zielsprachen - Statten Sie jede Zielsprachanbindung mit einem eigenen Adapter aus, der auf einer gemeinsamen Traversierungsabstraktion aufbaut. - Verwenden Sie beim Hinzufügen einer neuen Zielsprachanbindung eine ausgereifte Anbindung als Referenz, bewahren Sie jedoch die Idiome der neuen Sprache. - Bündeln Sie das ursprüngliche Implementierungsartefakt nur dann, wenn die Laufzeitarchitektur es erfordert. - Nehmen Sie die Assembly-Metadaten auf, die nachgelagerte Reflexions- oder Erzeugungswerkzeuge benötigen. - Verwenden Sie gemeinsame Hilfsfunktionen für Formatierung, Einrückung, Dateierstellung und Codeblöcke in allen Zielsprachen. - Aktualisieren Sie die Momentaufnahmen des erzeugten Codes bei jeder Änderung einer Zielsprachanbindung. ## Im Monorepo mit den festgelegten Werkzeugversionen bauen und testen Führen Sie Installation, Builds, Tests, statische Prüfungen, Aktualisierungen von Momentaufnahmen und die Erstellung von Konformitätsberichten über die im Repository festgelegte Arbeitsbereichswerkzeugkette aus. ### Umgebung und Umfang - Beginnen Sie für die vollständige Einrichtung und die Validierung des gesamten Repositories im Stammverzeichnis. - Führen Sie für gezielte Iterationen paketspezifische Skripte aus dem jeweiligen Paketverzeichnis aus. - Halten Sie die festgelegten Versionen von Paketmanager und Orchestrierungswerkzeugen ein. - Begrenzen Sie die Buildparallelität, wenn paketübergreifende Abhängigkeiten eine parallele Ausführung unsicher machen. ### Änderungsablauf - Ermitteln Sie vor dem Bearbeiten oder Ausführen von Befehlen, welches Paket für die Änderung verantwortlich ist. - Erstellen und testen Sie zuerst das betroffene Paket und führen Sie anschließend eine breitere Validierung der gemeinsamen Verträge durch. - Bearbeiten Sie den Quellcode statt erzeugter Bündel und erstellen Sie diese über die vorgesehene Verarbeitungskette neu. - Belassen Sie vorübergehende Laufzeitüberschreibungen und Debuggereinstellungen lokal. - Aktualisieren Sie Momentaufnahmen erst, nachdem Sie bestätigt haben, dass die erzeugte Änderung beabsichtigt ist. ## Mit Snapshots und einer gemeinsamen Testsuite für alle Sprachen prüfen Kombinieren Sie schnelle Tests auf Paketebene mit Regressionsprüfungen der erzeugten Ausgaben und einer sprachübergreifenden Konformitätsprüfsammlung. ### Validierungsebenen - Verwenden Sie Unit-Tests für Paketlogik und Grenzfälle des Protokolls. - Verwenden Sie Momentaufnahmen, um unbeabsichtigte Änderungen am erzeugten Quellcode zu erkennen. - Verwenden Sie gemeinsame Testvorrichtungen, die Klassen, Schnittstellen, Datenstrukturen, Aufzählungen, Sammlungen, asynchrone Aufrufe und Überschreibungen abdecken. - Verwenden Sie Konformitätstests, um gleichwertiges Verhalten in jeder Sprachanbindung zu überprüfen. ### Testvorrichtungen und Berichte - Kompilieren Sie gemeinsame Testvorrichtungen mit demselben Compiler, den tatsächliche Verbraucher verwenden. - Aktualisieren Sie bei Änderungen an Testvorrichtungen alle betroffenen Momentaufnahmen von Generatoren, Reflexionswerkzeugen und Laufzeiten. - Definieren Sie jeden Konformitätsfall einmal und verlangen Sie dann von jeder Sprachanbindung, ihn umzusetzen oder ausdrücklich einzuordnen. - Erzeugen Sie den Konformitätsbericht neu und nehmen Sie ihn in die Versionsverwaltung auf, sobald sich Fälle oder Ergebnisse ändern. - Lassen Sie die Validierung fehlschlagen, wenn eine Sprachanbindung einen Fall hinzufügt, der in der Prüfsammlungsdefinition fehlt, oder wenn der Bericht veraltet ist. ## Änderungen mit aktuellen Snapshots und Berichten veröffentlichen, ohne Force-Push Behandeln Sie erzeugten Code, Protokollformate, Laufzeitbibliotheken und Berichte als aufeinander abgestimmte Veröffentlichungsoberflächen. ### Unverhandelbare Beschränkungen - Schwächen Sie die Beschränkungen für exportierte Typen nicht ab, ohne sie in allen Zielsprachen zu validieren. - Ändern Sie Protokolloperationen oder gekennzeichnete Serialisierungsformate nicht ohne abgestimmte Aktualisierungen der Hostlaufzeiten. - Ändern Sie Erzeugungsmuster nicht, ohne die Momentaufnahmen zu aktualisieren und zu prüfen. - Setzen Sie keine Threadsicherheit voraus, wenn Laufzeitbibliotheken bewusst für einen einzelnen Thread ausgelegt sind. - Führen Sie keine zyklischen Paketabhängigkeiten ein, wenn der Buildabhängigkeitsgraph Zyklen ablehnt. - Ändern Sie gebündelte Ausgaben nicht direkt. ### Pull-Request und Übergabe - Verwenden Sie das vorgeschriebene Titelformat, die Umfangskonventionen und die Bestätigung der Beitragslizenz des Repositories. - Fügen Sie alle vom geänderten Quellcode erforderlichen erzeugten Momentaufnahmen und Konformitätsberichte bei. - Halten Sie nicht zugehörige erzeugte Dateien, Änderungen an Abhängigkeitssperrdateien und lokale Einstellungen aus der Änderung heraus. - Wenn der Remote-Branch neue Änderungen enthält, rufen Sie sie ab und führen Sie einen Rebase oder Merge durch, lösen Sie Konflikte, validieren Sie und pushen Sie anschließend normal; verwenden Sie niemals einen Force-Push. - Halten Sie die Synchronisierung nachgelagerter Repositories oder Dokumentationen in der Veröffentlichungsprüfliste fest, statt sich auf das Gedächtnis zu verlassen.