CommunitySchreiben & Editierengithub.com

BESSER-PEARL/BESSER-Skills

Agent-Fähigkeiten für BESSER – tiefgehendes BESSER-Wissen für KI-Codierungsagenten: UML-Klassenmodellierung, Code-Generatoren, Fehlerbehebung und Mitwirkenden-Workflows.

Was ist BESSER-Skills?

Diese Skill-Datei bietet KI-Codierungsagenten (wie Claude Code, Cursor oder Codex) eine umfassende Anleitung zur effektiven Mitarbeit am BESSER-Projekt. Sie deckt das gesamte Spektrum der Entwicklung ab: von der Einrichtung der Umgebung, dem Hinzufügen neuer Code-Generatoren und Metamodelle bis hin zu Tests, Dokumentation und den Prozessen für Commits und Pull-Requests. Die Anleitung ist besonders wertvoll für Entwickler, die das B-UML-Metamodell erweitern oder neue Generatoren für verschiedene Ausgabeformate erstellen möchten. Sie enthält detaillierte Code-Beispiele und Workflows, wie z. B. das Erstellen von Generator-Paketen mit Jinja2-Templates und das Registrieren im Web-Editor. Der Skill stellt sicher, dass Agenten konsistent und fehlerfrei zum Projekt beitragen können, indem er Konventionen, Fallstricke und die Zusammenarbeit zwischen verschiedenen Repos klar definiert. Die Unterstützung umfasst Python 3.10+, Django 5.x und Sphinx für die Dokumentation.

Funktioniert mit✓Claude Code~Codex CLI✓Cursor✓Windsurf
npx skills add BESSER-PEARL/BESSER-Skills

Installed? Explore more Schreiben & Editieren skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

In Ihrer bevorzugten KI fragen

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

Dokumentation

Mitwirken an BESSER

Diese Skill-Datei beschreibt die prozessualen Arbeitsabläufe für die Mitarbeit an der BESSER-Codebasis. Informationen zur Architektur und zu den Code-Konventionen finden Sie auch in der Datei CLAUDE.md des Projekts, die automatisch in den Kontext geladen wird.


Entwicklungseinrichtung

git clone https://github.com/<dein-benutzername>/BESSER.git
cd BESSER
python -m venv venv
# Windows: venv\Scripts\activate
# macOS/Linux: source venv/bin/activate
pip install -r requirements.txt
pip install -r docs/requirements.txt  # zum Erstellen der Dokumentation
pip install -e .                       # editierbare Installation

Überprüfen: python tests/BUML/metamodel/structural/library/library.py

Python 3.10+ ist erforderlich (Django 5.x-Abhängigkeit).


Hinzufügen eines neuen Generators

Dies ist die häufigste Art von Beitrag. Um das Boilerplate zu überspringen, führen Sie das gebündelte Gerüst aus:

python scripts/scaffold_generator.py <name> <pfad/zu/BESSER/repo>
# z.B.: python scripts/scaffold_generator.py graphql ~/code/BESSER

Dies erstellt ein funktionsfähiges Stub-Paket (Generator-Klasse + Jinja-Template + Pytest), das sofort ausführbar ist. Sie müssen dennoch die eigentliche Logik implementieren, den Generator in der Web-Editor-Konfiguration registrieren und eine Dokumentation hinzufügen – dies wird in den folgenden Schritten behandelt.

Wenn Sie es lieber von Hand machen möchten, folgen Sie diesen 6 Schritten:

Schritt 1: Erstellen Sie das Generator-Paket

besser/generators/mein_generator/
  __init__.py               # Export: from .mein_generator import MeinGenerator
  mein_generator.py         # die Generator-Klasse
  templates/                # Jinja2-Templates
    ausgabe_template.py.j2

Kopieren Sie das Gerüst von einem vorhandenen einfachen Generator (z.B. python_classes/).

Schritt 2: Implementieren Sie GeneratorInterface

# besser/generators/mein_generator/mein_generator.py
import os
from jinja2 import Environment, FileSystemLoader
from besser.generators import GeneratorInterface

class MeinGenerator(GeneratorInterface):

    def __init__(self, model, output_dir: str = None):
        super().__init__(model, output_dir)

    def generate(self):
        """Erzeuge Ausgabe aus dem B-UML-Modell."""
        templates_path = os.path.join(os.path.dirname(__file__), "templates")
        env = Environment(
            loader=FileSystemLoader(templates_path),
            trim_blocks=True,
            lstrip_blocks=True,
        )
        template = env.get_template("ausgabe_template.py.j2")
        output = template.render(
            classes=self.model.get_classes(),
            associations=self.model.associations,
        )
        file_path = self.build_generation_path("meine_ausgabe.py")
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(output)

Wichtige Anforderungen:

  • Rufen Sie super().__init__(model, output_dir) auf – dies richtet self.model und self.output_dir ein.
  • Verwenden Sie self.build_generation_path(dateiname), um den korrekten Ausgabedateipfad zu erhalten.
  • Verwenden Sie self.build_generation_dir(), wenn Sie nur den Verzeichnispfad benötigen.
  • Jinja2-Templates sollten sich in einem Unterverzeichnis templates/ neben dem Generator befinden.
  • Die Ausgabe muss deterministisch sein – dasselbe Modell erzeugt jedes Mal dieselbe Ausgabe (keine Zeitstempel, Zufallswerte usw.).
  • Wiederverwendbare Hilfsfunktionen gehören in besser/utilities/, nicht in den Generator.

Schritt 3: Schreiben Sie Jinja2-Templates

{# besser/generators/mein_generator/templates/ausgabe_template.py.j2 #}
# Generiert von BESSER MeinGenerator
{% for cls in classes %}
class {{ cls.name }}:
    {% for attr in cls.attributes %}
    {{ attr.name }}: {{ attr.type.name }}
    {% endfor %}

{% endfor %}

Wenn Sie JSX/React generieren, verwenden Sie nicht standardmäßige Trennzeichen, um Konflikte zu vermeiden:

env = Environment(
    loader=FileSystemLoader(templates_path),
    variable_start_string="[[",
    variable_end_string="]]",
)

Schritt 4: Im Web-Editor-Backend registrieren

Fügen Sie Ihren Generator zu besser/utilities/web_modeling_editor/backend/config/generators.py hinzu:

from besser.generators.mein_generator import MeinGenerator

GENERATORS = {
    # ... bestehende Generatoren ...
    "mein_generator": GeneratorInfo(
        generator_class=MeinGenerator,
        output_type="file",           # "file" für einzelne Datei, "zip" für mehrere Dateien
        file_extension=".py",         # Dateierweiterung der Ausgabe
        category="meine_kategorie",   # Gruppenbezeichnung
        requires_class_diagram=True,  # True, wenn ein DomainModel benötigt wird
    ),
}

Aktualisieren Sie auch get_filename_for_generator() in derselben Datei, wenn der Generator einen bestimmten Dateinamen erzeugt.

Schritt 5: Tests schreiben

Erstellen Sie tests/generators/mein_generator/test_mein_generator.py:

import os
import shutil
import pytest
from besser.BUML.metamodel.structural import (
    DomainModel, Class, Property, BinaryAssociation,
    Multiplicity, StringType, IntegerType,
)
from besser.generators.mein_generator import MeinGenerator


@pytest.fixture
def domain_model():
    """Erstelle ein kleines Testmodell."""
    name_prop = Property(name="name", type=StringType)
    age_prop = Property(name="alter", type=IntegerType)
    person = Class(name="Person", attributes={name_prop, age_prop})
    model = DomainModel(name="TestModel", types={person})
    return model


@pytest.fixture
def output_dir(tmp_path):
    return str(tmp_path)


def test_generate_erzeugt_ausgabedatei(domain_model, output_dir):
    gen = MeinGenerator(model=domain_model, output_dir=output_dir)
    gen.generate()
    assert os.path.exists(os.path.join(output_dir, "meine_ausgabe.py"))


def test_generate_enthält_klassennamen(domain_model, output_dir):
    gen = MeinGenerator(model=domain_model, output_dir=output_dir)
    gen.generate()
    with open(os.path.join(output_dir, "meine_ausgabe.py")) as f:
        content = f.read()
    assert "Person" in content
    assert "name" in content
    assert "alter" in content

Testmuster, die in der gesamten Codebasis verwendet werden:

  • Verwenden Sie tmp_path oder tmpdir-Fixtures für Ausgabeverzeichnisse (werden automatisch bereinigt).
  • Erstellen Sie kleine Inline-Modelle als Fixtures – verlassen Sie sich nicht auf externe Dateien.
  • Testen Sie sowohl die Struktur (Dateien existieren, Klassennamen vorhanden) als auch den Inhalt (Geschäftslogik).
  • Verwenden Sie für Generatoren, die importierbares Python erzeugen, importlib, um den generierten Code dynamisch zu importieren und zu testen.
  • Bereinigen Sie mit shutil.rmtree(), wenn Sie keine Pytest-tmp-Fixtures verwenden.

Schritt 6: Dokumentieren

Fügen Sie Dokumentation in docs/source/generators/mein_generator.rst hinzu:

MeinGenerator
=============

Der MeinGenerator erzeugt ... aus einem B-UML-Domänenmodell.

Voraussetzungen
---------------

- BESSER installiert
- ...

Verwendung
----------

.. code-block:: python

   from besser.generators.mein_generator import MeinGenerator

   gen = MeinGenerator(model=mein_model, output_dir="./output")
   gen.generate()

Ausgabe
-------

Der Generator erzeugt eine einzelne Datei ``meine_ausgabe.py`` mit ...

Fügen Sie es zum Generatoren-Index in docs/source/generators.rst hinzu.


Hinzufügen eines neuen Metamodells / Sub-DSL

Schritt 1: Entwerfen Sie das Metamodell

Erstellen Sie neue Klassen in besser/BUML/metamodel/ihre_dsl/:

besser/BUML/metamodel/ihre_dsl/
  __init__.py
  ihre_dsl.py    # Metamodell-Klassen

Folgen Sie den vorhandenen Mustern:

  • Erweitern Sie NamedElement oder Element als Basisklassen.
  • Verwenden Sie private Eigenschaften mit Getter/Setter-Validierung.
  • Halten Sie die Namensgebung konsistent mit den vorhandenen Metamodell-Paketen.

Schritt 2: Konverter hinzufügen (falls Web-Editor-Integration erforderlich)

Konverter übersetzen zwischen Frontend-JSON und B-UML-Objekten:

besser/utilities/web_modeling_editor/backend/services/converters/
  json_to_buml/process_ihre_dsl.py    # JSON → BUML
  buml_to_json/ihre_dsl_to_json.py    # BUML → JSON

Konverter müssen symmetrisch sein: Jedes in einer Richtung unterstützte Feature muss auch in der anderen funktionieren. Testen Sie Round-Trips: JSON → BUML → JSON sollte das Original ergeben.

Schritt 3: Validierung hinzufügen

Falls das Metamodell Einschränkungen hat, die über die Setter hinausgehen:

def validate(self, raise_exception=True):
    errors = []
    warnings = []
    # Strukturelle Regeln prüfen
    if some_bad_condition:
        errors.append("Beschreibende Fehlermeldung")
    result = {"success": len(errors) == 0, "errors": errors, "warnings": warnings}
    if raise_exception and errors:
        raise ValueError("\n".join(errors))
    return result

Schritt 4: Ins Backend einbinden

  • Fügen Sie Endpunkt(e) in besser/utilities/web_modeling_editor/backend/backend.py hinzu.
  • Fügen Sie Pydantic-Anfrage-/Antwortmodelle in backend/models/ hinzu.
  • Fügen Sie ggf. eine Validierungsroute unter /validate-diagram hinzu.

Schritt 5: Tests schreiben

Platzieren Sie Tests in tests/BUML/metamodel/ihre_dsl/:

  • Tests zur Konstruktion gültiger Modelle.
  • Tests für ungültige Modelle (erwarten Sie ValueError, TypeError).
  • Round-Trip-Konverter-Tests, falls zutreffend.

Schritt 6: Dokumentieren

  • Metamodell-Dokumentation: docs/source/buml_language/ihre_dsl.rst
  • Fügen Sie es zum Index docs/source/buml_language.rst hinzu.

Testen

Alle Tests ausführen

python -m pytest

Bestimmte Tests ausführen

# Nach Verzeichnis
python -m pytest tests/generators/sqlalchemy/

# Nach Schlüsselwort
python -m pytest -k "test_django"

# Mit ausführlicher Ausgabe
python -m pytest -v tests/BUML/metamodel/structural/

# Beim ersten Fehler anhalten
python -m pytest -x

Testkonventionen

  • Testdateien: test_*.py
  • Testfunktionen: test_*
  • Verwenden Sie @pytest.fixture für wiederverwendbare Modelle und Verzeichnisse.
  • Verwenden Sie tmp_path für Ausgabeverzeichnisse (werden von Pytest automatisch bereinigt).
  • Überprüfen Sie bestimmte Inhalte, nicht nur die Existenz von Dateien.
  • Testen Sie Fehlerbedingungen mit pytest.raises(ValueError).

Was zu testen ist

Für Metamodell-Änderungen: Konstruktionsvalidierung, Setter-Einschränkungen, erwartete Fehler bei ungültiger Eingabe, Ergebnisse von validate().

Für Generatoren: Existenz der Ausgabedatei, Schlüsselinhalte in der Ausgabe (Klassennamen, Beziehungszuordnungen), Randfälle (leeres Modell, tiefe Vererbung, viele-zu-viele).

Für Konverter: Round-Trip-Treue (JSON → BUML → JSON sollte äquivalent sein).


Dokumentation erstellen

cd docs

# Windows:
make.bat html

# macOS/Linux:
make html

# Anzeigen:
# Öffnen Sie docs/build/html/index.html in Ihrem Browser

Die Dokumentation verwendet Sphinx mit dem Furo-Theme. Quelldateien sind reStructuredText (".rst") in docs/source/.

Dokumentationsstruktur

PfadEnthält
docs/source/buml_language/Metamodell-Dokumentation
docs/source/generators/Generator-Dokumentation
docs/source/web_editor.rstWeb-Editor-API-Dokumentation
docs/source/utilities/Hilfsprogramm-Dokumentation
docs/source/contributing/Mitwirkenden-Anleitungen
docs/source/releases/Versionshinweise
docs/source/_static/Gemeinsame Bilder und Assets
docs/source/img/Diagramme und Screenshots

Querverweise

Verwenden Sie Sphinx-Rollen für Querverweise:

  • :doc:\generators/django`` — Link zu einer anderen Dokumentationsseite
  • :mod:\besser.generators.django`` — Link zur Modul-API
  • :class:\besser.BUML.metamodel.structural.Class`` — Link zur Klassen-API
  • :ref:\label-name`` — Link zu einem markierten Abschnitt

Code-Stil

  • PEP 8 mit 4 Leerzeichen Einzug.
  • 120 Zeichen Zeilenlänge (konfiguriert in pyproject.toml unter [tool.pylint.'FORMAT']).
  • Typannotationen für öffentliche APIs.
  • PEP 257 Docstrings.
  • Importreihenfolge: Standardbibliothek, Drittanbieter, lokale Module.
  • snake_case für Funktionen/Variablen, PascalCase für Klassen, UPPER_CASE für Konstanten.
  • Keine Wildcard-Importe, keine impliziten Re-Exports.
  • Linting: pylint (derzeit keine ruff/black/pre-commit-Hooks konfiguriert).

Commit- und PR-Konventionen

Commit-Nachrichten

Verwenden Sie Conventional Commits:

feat: Terraform-Generator für AWS EKS hinzugefügt
fix: Multiplizitätsparsing für 0..*-Assoziationen korrigiert
refactor: Gemeinsame Template-Helfer in besser.utilities extrahiert
docs: QiskitGenerator-Verwendung dokumentiert
test: Round-Trip-Tests für GUI-Modellkonverter hinzugefügt

Pull-Request-Workflow

  1. Erstellen Sie einen Themenbranch: git checkout -b feature/füge-meinen-generator-hinzu.
  2. Machen Sie fokussierte, logisch gruppierte Commits.
  3. Führen Sie lokale Tests aus: python -m pytest.
  4. Erstellen Sie die Dokumentation: cd docs && make html.
  5. Rebasen Sie auf den neuesten master: git fetch origin && git rebase origin/master.
  6. Pushen und öffnen Sie einen PR gegen master.
  7. Füllen Sie die PR-Vorlage aus: Beschreibung, ausgeführte Tests, zusätzlicher Kontext.
  8. Für die Zusammenführung sind zwei Maintainer-Zustimmungen erforderlich (eine Zustimmung reicht nach 14 Tagen aus).

Änderungen über Repos hinweg (BESSER + Frontend)

Wenn Änderungen sowohl BESSER als auch das Web-Editor-Frontend betreffen:

  1. Implementieren und committen Sie WME-Änderungen im WME-Repo.
  2. Implementieren Sie BESSER-Änderungen in diesem Repo.
  3. Aktualisieren Sie den Submodule-Zeiger:
    cd besser/utilities/web_modeling_editor/frontend
    git fetch && git checkout <commit>
    cd ../../../..
    git add besser/utilities/web_modeling_editor/frontend
    
  4. Verlinken Sie die beiden PRs, damit die Reviewer in der richtigen Reihenfolge mergen.

CI / Release

  • CI: Es gibt keinen automatisierten Test-Workflow – Tests werden vor PRs lokal ausgeführt.
  • Release: Wird durch das Erstellen eines GitHub-Releases ausgelöst. Der python-publish.yml-Workflow erstellt und veröffentlicht auf PyPI unter Verwendung von PYPI_API_TOKEN.
  • Version: Definiert in setup.cfg unter [metadata] version.
  • Versionshinweise: Werden als RST-Dateien in docs/source/releases/ hinzugefügt.

Häufige Fallstricke bei Beiträgen

  1. Logik nicht duplizieren – gemeinsame Helfer gehören in besser/utilities/, nicht in einzelne Generatoren.
  2. Determinismus wahren – Generatoren müssen für identische Eingabe identische Ausgabe erzeugen.
  3. Konverter symmetrisch halten – wenn JSON → BUML ein Feature unterstützt, muss BUML → JSON es ebenfalls unterstützen.
  4. Dokumentation aktualisieren – jede Backend-Änderung erfordert wahrscheinlich Aktualisierungen in docs/source/.
  5. Das Frontend-Submodule nicht berühren – es sei denn, es ist ausdrücklich erforderlich. UI-Änderungen gehen an das übergeordnete WME-Repo.
  6. Ressourcen bereinigen – immer try/finally für temporäre Verzeichnisse und Dateihandles verwenden.
  7. Round-Trips testen – insbesondere für Konverter (JSON → BUML → JSON sollte identisch sein).

Verwandte Skills