4.6 KiB
4.6 KiB
PHP & Symfony Engineering Guidelines
1. Core PHP Standard
Wir schreiben modernen, typensicheren und expliziten Code. Ziel ist es, Fehler zur Compile-Zeit bzw. via statischer Analyse zu finden.
- Strict Typing: Jede Datei beginnt zwingend mit
declare(strict_types=1);. - Typisierung:
- Konsequentes Type Hinting für alle Parameter und Rückgabewerte (inkl.
void). - Nutzung von Union- und Intersection Types.
mixedist verboten, außer in absolut unvermeidbaren Generics.
- Konsequentes Type Hinting für alle Parameter und Rückgabewerte (inkl.
- Modern Features (PHP 8.2+):
- Readonly: Standard für DTOs, Value Objects und Services (
readonly class). - Constructor Promotion: Nutzung zur Reduktion von Boilerplate.
- Enums: Einsatz anstelle von Konstanten oder Strings für feste Zustände.
- Match Expression: Bevorzugt gegenüber
switch.
- Readonly: Standard für DTOs, Value Objects und Services (
- Anti-Magic: Magic Methods (
__call,__getetc.) und dynamische Properties sind strikt verboten.
2. Control Flow & Readability
Lesbarkeit schlägt akademische Perfektion. Code muss für andere Senioren ohne "Rätselraten" sofort verstehbar sein.
- Control Flow: Nutzung von Early Returns und Guard Clauses. Verschachtelte
if-else-Strukturen sind zu vermeiden, um die kognitive Last gering zu halten. - Self-Explaining Code: Namen müssen den Intent beschreiben (
calculateTotalTax()stattcalc()). Booleans beginnen mitis,hasodercan. - Kommentare: Kommentare werden nur eingesetzt, wenn:
- Der Code aufgrund einer Sonderlösung nicht selbsterklärend ist (Dokumentation des "Warum").
- Arrays/Collections typisiert werden müssen (
/** @var UserDTO[] $users */), sofern PHPStan dies nicht anders erfassen kann.
3. Data Structures & Collections
Wir vermeiden "Mystery Meat"-Datenstrukturen zugunsten von Typsicherheit.
- No Associative Arrays: Die Nutzung von assoziativen Arrays als Pseudo-Objekte/Datencontainer ist verboten. Es werden immer dedizierte Objekte (DTOs) verwendet.
- Collections:
- Transport: Für einfache Listen, die nur durchiteriert werden, reichen typisierte Arrays (
array<T>). - Domain-Logik: Sobald eine Liste fachliche Logik besitzt (z.B. Filterung, Aggregation), wird eine dedizierte Collection-Klasse erstellt (implementiert
IteratorAggregateundCountable).
- Transport: Für einfache Listen, die nur durchiteriert werden, reichen typisierte Arrays (
4. Infrastructure & Symfony Implementation
Symfony ist der Adapter zur Außenwelt, nicht das Zentrum der Applikation.
- Dependency Injection: Ausschließlich Constructor Injection. Kein Service-Locator (
$this->container->get()). DI erfolgt primär gegen Interfaces (Ports). - Controller: "Thin Controller". Aufgaben sind: Request-Daten validieren/extrahieren
\rightarrowApplication-Service aufrufen\rightarrowResponse transformieren. Keine Business-Logik im Controller. - Third-Party SDKs: Alle externen Services/SDKs werden konsequent hinter einem eigenen Interface (Port) in der Infrastructure-Schicht gekapselt. Vendor-Klassen dürfen niemals den Application- oder Domain-Layer erreichen.
5. Persistence & Entity Design
Wir minimieren die Koppelung an das ORM, um Performance und Testbarkeit zu sichern.
- Simple Entities: Entitäten werden flach gehalten.
- Avoid Joins: Gejointe Entitäten (komplexe
@ManyToOne/@OneToMany) sind grundsätzlich zu vermeiden. Referenzen erfolgen über IDs. Die Zusammenführung erfolgt explizit in den Repositories/Services. - Mapping: Transformationen zwischen Infrastructure-Entities und Domain-Modellen erfolgen ausschließlich über dedizierte Mapper-Klassen in der Dataschicht.
6. Validation Pipeline (Shift-Left)
Fehler werden so früh wie möglich abgefangen:
Request \rightarrow DTO Asserts/Validation \rightarrow Application Logic \rightarrow Domain Complex Tests.
7. Quality Gates & Workflow (Definition of Done)
Bevor Code in ein Review geht, müssen folgende lokale Checks erfolgreich durchlaufen sein:
- Syntax Check:
php -l - Statische Analyse:
phpstan analyse(Ziel Level 8/9). Pragmatismus-Regel: Wenn Typisierung die Lesbarkeit massiv zerstört\rightarrowReview-Dialog statt "Force-Typing". - Automatisierte Tests:
phpunit(Unit, Integration, Functional).
Die Golden Rules im Überblick:
- Kein Framework / Keine Vendor-Klassen im Domain.
- Flache Entitäten / Referenzen über IDs.
- Immutability by Default (
readonly). - Keine assoziativen Arrays
\rightarrowDedizierte Objekte. - Early Returns
\rightarrowFlacher Code. - Local Check:
php -l\rightarrowphpstan\rightarrowphpunit.