5.9 KiB
5.9 KiB
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
finalsein, es sei denn, es gibt einen zwingenden Grund für Vererbung - Keine abstrakten Klassen - bevorzuge Interfaces und Kompositionen
- Klassen sollten
readonlysein, wann immer möglich - Interfaces verwenden, um Verträge zwischen Komponenten zu definieren
// Gut
final readonly class AnalyticsManager
{
// ...
}
// Vermeiden
abstract class BaseManager
{
// ...
}
Properties
- Properties sollten
readonlysein, 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
// 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
// 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
// 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
public function findUser(?int $id): ?User
public function process(int|string $identifier): void
Match Expression statt Switch
// 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
$this->createUser(
email: 'user@example.com',
role: 'admin',
sendWelcomeEmail: true
);
Constructor Property Promotion
public function __construct(
private readonly Configuration $config,
private readonly PathProvider $pathProvider
) {}
Fehlerbehandlung
- Spezifische Exceptions werfen
- Typed Exceptions verwenden
- Early Return Pattern bevorzugen
// 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
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
/**
* 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