# Coding Guidelines

## Allgemeine Prinzipien

Diese Guidelines definieren die Standards für die Entwicklung und Wartung des Projekts. Sie sorgen für Konsistenz, Lesbarkeit und Wartbarkeit des Codes.

## PHP-Version

- **PHP 8.4**: Die Codebase nutzt stets die neueste stabile PHP-Version (aktuell PHP 8.4)
- Alle neuen PHP-Sprachfeatures sollten, wo sinnvoll, genutzt werden

## Abhängigkeiten

- **Externe Abhängigkeiten vermeiden**: Das Projekt soll möglichst ohne externe Bibliotheken auskommen
- **Eigene Implementierungen bevorzugen**: Anstatt externe Pakete einzubinden, sollten eigene Lösungen entwickelt werden
- **Erlaubte Abhängigkeiten**: Nur die bereits in composer.json definierten Pakete dürfen verwendet werden
- **Neue Abhängigkeiten**: Müssen explizit genehmigt werden und sollten nur in Ausnahmefällen hinzugefügt werden

## Klassenstruktur

### Klassen

- **Alle Klassen müssen `final` sein**, es sei denn, es gibt einen zwingenden Grund für Vererbung
- **Keine abstrakten Klassen** - bevorzuge Interfaces und Kompositionen
- **Klassen sollten `readonly` sein**, wann immer möglich
- Interfaces verwenden, um Verträge zwischen Komponenten zu definieren

```php
// Gut
final readonly class AnalyticsManager
{
    // ...
}

// Vermeiden
abstract class BaseManager
{
    // ...
}
```

### Properties

- **Properties sollten `readonly` sein**, wann immer möglich
- Private Visibility für alle Properties, es sei denn, es gibt einen zwingenden Grund
- Typisierung ist obligatorisch für alle Properties

```php
// Gut
private readonly StorageInterface $storage;

// Vermeiden
public array $config;
```

## Methoden und Funktionen

- Typisierung ist obligatorisch für alle Parameter und Rückgabewerte
- Methoden sollten klein und fokussiert sein (Single Responsibility)
- Verwende named arguments für bessere Lesbarkeit

```php
// Gut
public function track(string $event, array $properties = [], ?string $userId = null): void
{
    // ...
}

// Vermeiden
public function process($data)
{
    // ...
}
```

## Dependency Injection

- Constructor Injection für alle Abhängigkeiten
- Keine Service Locator oder globale Zustände
- Verwende das `#[Initializer]`-Attribut für Service-Registrierung

```php
// Gut
public function __construct(
    private readonly Configuration $config,
    private readonly StorageInterface $storage
) {}

// Vermeiden
public function __construct()
{
    $this->config = Container::get(Configuration::class);
}
```

## Moderne PHP-Features

### Nullable Types und Union Types

```php
public function findUser(?int $id): ?User
public function process(int|string $identifier): void
```

### Match Expression statt Switch

```php
// Gut
return match($storageType) {
    'file' => new FileStorage($path),
    'redis' => new RedisStorage($connection),
    default => throw new \InvalidArgumentException("Nicht unterstützter Storage-Typ: {$storageType}")
};

// Vermeiden
switch ($storageType) {
    case 'file':
        return new FileStorage($path);
    // ...
}
```

### Named Arguments

```php
$this->createUser(
    email: 'user@example.com',
    role: 'admin',
    sendWelcomeEmail: true
);
```

### Constructor Property Promotion

```php
public function __construct(
    private readonly Configuration $config,
    private readonly PathProvider $pathProvider
) {}
```

## Fehlerbehandlung

- Spezifische Exceptions werfen
- Typed Exceptions verwenden
- Early Return Pattern bevorzugen

```php
// Gut
if (!$this->isValid()) {
    throw new ValidationException('Ungültige Daten');
}

// Vermeiden
if ($this->isValid()) {
    // Lange Verarbeitung...
} else {
    throw new Exception('Fehler');
}
```

## Testing

- Tests mit Pest-Framework schreiben
- Für jede öffentliche Methode sollte mindestens ein Test existieren
- Mocking nur für externe Abhängigkeiten verwenden

```php
test('track method records events correctly', function () {
    $analytics = new Analytics($manager, $dispatcher);
    $analytics->track('test_event', ['key' => 'value']);

    expect($manager->getEvents())->toHaveCount(1);
});
```

## Dokumentation

- PHPDoc für alle öffentlichen Methoden und Klassen
- Typen in PHPDoc sollten den tatsächlichen Typen entsprechen
- Klare, beschreibende Kommentare für komplexe Logik

```php
/**
 * Zeichnet ein Event auf und wendet Middleware an
 *
 * @param string $event Event-Name
 * @param array $properties Event-Eigenschaften
 * @param string|null $userId Benutzer-ID (optional)
 */
public function track(string $event, array $properties = [], ?string $userId = null): void
```

## Namenskonventionen

- **Klassen**: PascalCase (`AnalyticsManager`)
- **Methoden/Funktionen**: camelCase (`getEventStats()`)
- **Variablen**: camelCase (`$eventData`)
- **Konstanten**: SNAKE_CASE (`MAX_BATCH_SIZE`)
- **Dateien**: Klassenname.php (`AnalyticsManager.php`)

## Architektur

- Dependency Inversion Principle befolgen
- Interfaces für alle externen Abhängigkeiten
- Vermeide zirkuläre Abhängigkeiten zwischen Modulen
- Services sollten eine klare, fokussierte Verantwortung haben

## Performance

- Lazy Loading für ressourcenintensive Operationen
- Caching wo sinnvoll
- Datenstrukturen sorgfältig auswählen

## Security

- Alle Benutzereingaben validieren und bereinigen
- Prepared Statements für Datenbankabfragen
- Vermeidung von `eval()` und ähnlichen unsicheren Funktionen
- Sensible Daten niemals in Logs schreiben

## Best Practices

- **Immutability**: Bevorzuge unveränderliche Objekte
- **Pure Functions**: Bevorzuge reine Funktionen ohne Seiteneffekte
- **Enums**: Verwende Enums statt String-Konstanten für feste Optionssätze
- **DTOs**: Verwende Data Transfer Objects für Datentransport
- **Value Objects**: Verwende Value Objects für semantisch reiche Datentypen

## Refactoring

- Code, der diese Guidelines nicht erfüllt, sollte beim Bearbeiten aktualisiert werden
- Tests müssen vor und nach dem Refactoring bestehen
- Große Refactorings sollten in kleinen, separaten Commits erfolgen
