Whatsapp Telegram Telegram Call Anrufen

Best Practices und Design Patterns in Symfony


Die Entwicklung hochwertiger Software erfordert nicht nur technische Fähigkeiten, sondern auch ein Verständnis für bewährte Praktiken und Designprinzipien. In diesem Artikel werden wir uns mit Best Practices und Design Patterns in Symfony beschäftigen, um die Qualität, Wartbarkeit und Erweiterbarkeit Ihrer Anwendungen zu verbessern.

Die folgenden Themen werden wir ausführlich behandeln:

  1. Coding-Standards und Konventionen
  2. Umsetzung der SOLID-Prinzipien
  3. Verwendung von Design Patterns (Repository, Service Layer)
  4. Refactoring und Aufrechterhaltung der Codequalität
  5. Dokumentation und Codekommentare

1. Coding-Standards und Konventionen

1.1 Warum sind Coding-Standards wichtig?

Coding-Standards und Konventionen sorgen für Konsistenz im Code, erleichtern die Zusammenarbeit im Team und verbessern die Lesbarkeit und Wartbarkeit des Codes.

1.2 PSR-Standards

Die PHP-FIG (PHP Framework Interop Group) hat mehrere PHP Standard Recommendations (PSR) veröffentlicht, die als Richtlinien dienen.

Wichtige PSRs:

  • PSR-1: Basic Coding Standard
  • PSR-2: Coding Style Guide (wurde durch PSR-12 ersetzt)
  • PSR-12: Extended Coding Style Guide
  • PSR-4: Autoloading Standard

1.3 Implementierung von PSR-Standards in Symfony

Symfony folgt den PSR-Standards, und es wird empfohlen, diese auch in Ihren Projekten umzusetzen.

Beispiel:

  • Datei- und Klassennamen: Jeder Klasse sollte in einer eigenen Datei definiert sein, und der Namespace sollte dem Dateipfad entsprechen.
// src/Controller/DefaultController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class DefaultController extends AbstractController
{
    // ...
}
  • Einrückungen: Verwenden Sie 4 Leerzeichen für Einrückungen, keine Tabs.

  • Klammern: Die Eröffnungsklammer folgt auf die Funktions- oder Klassendeklaration in der nächsten Zeile.

class MyClass
{
    public function myFunction()
    {
        // ...
    }
}

1.4 Automatisierung mit Tools

PHP CS Fixer

Der PHP CS Fixer kann Ihren Code automatisch an die PSR-Standards anpassen.

Installation:

composer require --dev friendsofphp/php-cs-fixer

Verwendung:

php vendor/bin/php-cs-fixer fix src

PHP_CodeSniffer

PHP_CodeSniffer kann Ihren Code auf Verstöße gegen Coding-Standards überprüfen.

Installation:

composer require --dev "squizlabs/php_codesniffer=*"

Verwendung:

php vendor/bin/phpcs --standard=PSR12 src

2. Umsetzung der SOLID-Prinzipien

2.1 Einführung in SOLID

SOLID ist ein Akronym für fünf Prinzipien objektorientierten Designs, die die Lesbarkeit, Wartbarkeit und Erweiterbarkeit des Codes verbessern.

Die fünf SOLID-Prinzipien:

  1. Single Responsibility Principle (SRP)
  2. Open/Closed Principle (OCP)
  3. Liskov Substitution Principle (LSP)
  4. Interface Segregation Principle (ISP)
  5. Dependency Inversion Principle (DIP)

2.2 Single Responsibility Principle (SRP)

Definition: Eine Klasse sollte nur eine einzige Verantwortlichkeit haben.

Beispiel:

Falsch:

class UserManager
{
    public function createUser(array $data)
    {
        // Benutzer erstellen
    }

    public function sendWelcomeEmail(User $user)
    {
        // E-Mail senden
    }
}

Richtig:

class UserManager
{
    public function createUser(array $data)
    {
        // Benutzer erstellen
    }
}

class Mailer
{
    public function sendWelcomeEmail(User $user)
    {
        // E-Mail senden
    }
}

2.3 Open/Closed Principle (OCP)

Definition: Software-Entitäten sollten offen für Erweiterungen, aber geschlossen für Modifikationen sein.

Beispiel:

Verwendung von Schnittstellen und Abstraktionen, um Verhalten zu erweitern, ohne den bestehenden Code zu ändern.

interface PaymentMethodInterface
{
    public function pay(float $amount);
}

class CreditCardPayment implements PaymentMethodInterface
{
    public function pay(float $amount)
    {
        // Zahlung mit Kreditkarte
    }
}

class PaypalPayment implements PaymentMethodInterface
{
    public function pay(float $amount)
    {
        // Zahlung mit PayPal
    }
}

class Checkout
{
    private PaymentMethodInterface $paymentMethod;

    public function __construct(PaymentMethodInterface $paymentMethod)
    {
        $this->paymentMethod = $paymentMethod;
    }

    public function processOrder(float $amount)
    {
        $this->paymentMethod->pay($amount);
    }
}

2.4 Liskov Substitution Principle (LSP)

Definition: Objekte einer Basisklasse sollten durch Objekte ihrer Unterklassen ersetzt werden können, ohne dass das Programm falsch funktioniert.

Beispiel:

Wenn eine Klasse Square von Rectangle erbt, aber die Methoden nicht korrekt überschreibt, kann das LSP verletzt werden.

2.5 Interface Segregation Principle (ISP)

Definition: Viele spezifische Schnittstellen sind besser als eine allgemeine.

Beispiel:

Falsch:

interface WorkerInterface
{
    public function work();
    public function eat();
}

class HumanWorker implements WorkerInterface
{
    public function work()
    {
        // Arbeiten
    }

    public function eat()
    {
        // Essen
    }
}

class RobotWorker implements WorkerInterface
{
    public function work()
    {
        // Arbeiten
    }

    public function eat()
    {
        // Kann nicht essen (Problem)
    }
}

Richtig:

interface WorkableInterface
{
    public function work();
}

interface EatableInterface
{
    public function eat();
}

class HumanWorker implements WorkableInterface, EatableInterface
{
    public function work()
    {
        // Arbeiten
    }

    public function eat()
    {
        // Essen
    }
}

class RobotWorker implements WorkableInterface
{
    public function work()
    {
        // Arbeiten
    }
}

2.6 Dependency Inversion Principle (DIP)

Definition: Abstraktionen sollten nicht von Details abhängen; Details sollten von Abstraktionen abhängen.

Beispiel:

Verwenden von Schnittstellen und Dependency Injection, um Abhängigkeiten zu entkoppeln.

interface LoggerInterface
{
    public function log(string $message);
}

class FileLogger implements LoggerInterface
{
    public function log(string $message)
    {
        // In Datei schreiben
    }
}

class UserController
{
    private LoggerInterface $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function index()
    {
        $this->logger->log('Benutzer besucht die Startseite.');
    }
}

3. Verwendung von Design Patterns (Repository, Service Layer)

3.1 Warum Design Patterns verwenden?

Design Patterns sind wiederverwendbare Lösungen für häufig auftretende Probleme in der Softwareentwicklung. Sie fördern bewährte Praktiken und verbessern die Wartbarkeit des Codes.

3.2 Repository Pattern

Das Repository Pattern trennt die Datenzugriffsschicht von der Geschäftslogik und bietet eine Abstraktion über die Datenquelle.

Implementierung in Symfony:

Symfony verwendet Doctrine ORM, das bereits Repositories unterstützt.

Beispiel:

// src/Repository/ProductRepository.php

namespace App\Repository;

use App\Entity\Product;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class ProductRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Product::class);
    }

    public function findActiveProducts()
    {
        return $this->createQueryBuilder('p')
            ->andWhere('p.isActive = :active')
            ->setParameter('active', true)
            ->getQuery()
            ->getResult();
    }
}

Verwendung im Controller:

// src/Controller/ProductController.php

namespace App\Controller;

use App\Repository\ProductRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class ProductController extends AbstractController
{
    public function index(ProductRepository $productRepository)
    {
        $products = $productRepository->findActiveProducts();

        return $this->render('product/index.html.twig', [
            'products' => $products,
        ]);
    }
}

3.3 Service Layer Pattern

Der Service Layer definiert eine Schicht zwischen Controllern und der Geschäftslogik, um die Verantwortlichkeiten zu trennen und den Code wiederverwendbar zu machen.

Beispiel:

// src/Service/OrderService.php

namespace App\Service;

use App\Entity\Order;
use App\Repository\OrderRepository;

class OrderService
{
    private OrderRepository $orderRepository;
    private MailerService $mailer;

    public function __construct(OrderRepository $orderRepository, MailerService $mailer)
    {
        $this->orderRepository = $orderRepository;
        $this->mailer = $mailer;
    }

    public function createOrder(array $data): Order
    {
        $order = new Order();
        // Setzen von Daten...

        $this->orderRepository->save($order);

        $this->mailer->sendOrderConfirmation($order);

        return $order;
    }
}

Verwendung im Controller:

// src/Controller/OrderController.php

namespace App\Controller;

use App\Service\OrderService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;

class OrderController extends AbstractController
{
    public function create(Request $request, OrderService $orderService)
    {
        $data = $request->request->all();
        $order = $orderService->createOrder($data);

        return $this->redirectToRoute('order_success', ['id' => $order->getId()]);
    }
}

3.4 Vorteile der Verwendung von Design Patterns

  • Klarere Struktur: Bessere Organisation des Codes.
  • Wiederverwendbarkeit: Komponenten können in verschiedenen Teilen der Anwendung verwendet werden.
  • Testbarkeit: Leichtere Unit-Tests durch Entkopplung.

4. Refactoring und Aufrechterhaltung der Codequalität

4.1 Was ist Refactoring?

Refactoring ist der Prozess der Umgestaltung des Codes, um seine interne Struktur zu verbessern, ohne sein externes Verhalten zu ändern.

4.2 Wann sollte man refaktorisieren?

  • Technische Schulden abbauen.
  • Verbesserung der Lesbarkeit.
  • Vor dem Hinzufügen neuer Funktionen, um die Erweiterbarkeit zu erleichtern.

4.3 Tools für die Codequalität

PHPStan

PHPStan ist ein statischer Analysetool, das Fehler im Code findet.

Installation:

composer require --dev phpstan/phpstan

Verwendung:

php vendor/bin/phpstan analyse src --level=max

Psalm

Psalm ist ein weiteres statisches Analysetool mit Fokus auf Typensicherheit.

Installation:

composer require --dev vimeo/psalm

Verwendung:

php vendor/bin/psalm

4.4 Kontinuierliche Integration

Integrieren Sie Code-Qualitätsprüfungen in Ihre CI/CD-Pipeline, um sicherzustellen, dass der Code immer auf einem hohen Niveau bleibt.

4.5 Code Reviews

Führen Sie regelmäßige Code Reviews im Team durch, um Fehler zu finden und Best Practices zu fördern.

5. Dokumentation und Codekommentare

5.1 Warum ist Dokumentation wichtig?

Gute Dokumentation erleichtert es anderen Entwicklern (und Ihnen selbst), den Code zu verstehen und zu warten.

5.2 Arten von Dokumentation

  • Codekommentare: Erläuterungen direkt im Code.
  • Externe Dokumentation: README-Dateien, Wiki, API-Dokumentation.

5.3 Best Practices für Codekommentare

  • Klar und prägnant: Kommentare sollten den Zweck des Codes erklären.
  • Aktualität: Halten Sie Kommentare aktuell, um Verwirrung zu vermeiden.
  • Vermeiden von offensichtlichen Kommentaren: Kommentieren Sie nicht das Offensichtliche.

Beispiel:

Schlecht:

$i = 0; // Variable i auf 0 setzen

// Schleife über die Benutzerliste
foreach ($users as $user) {
    // Benutzername ausgeben
    echo $user->getName();
}

Gut:

// Initialisiert den Zähler für die Verarbeitung der Benutzer
$i = 0;

// Durchläuft alle aktiven Benutzer und gibt deren Namen aus
foreach ($users as $user) {
    echo $user->getName();
}

5.4 Verwenden von PHPDoc

PHPDoc ist ein Standard für das Kommentieren von PHP-Code, der auch von IDEs und Dokumentationstools verwendet wird.

Beispiel:

/**
 * Berechnet die Summe zweier Zahlen.
 *
 * @param int $a Die erste Zahl.
 * @param int $b Die zweite Zahl.
 *
 * @return int Die Summe von $a und $b.
 */
public function add(int $a, int $b): int
{
    return $a + $b;
}

5.5 Generieren von Dokumentation

Verwenden Sie Tools wie phpDocumentor oder ApiGen, um aus den PHPDoc-Kommentaren eine HTML-Dokumentation zu generieren.

Installation von phpDocumentor:

composer require --dev phpdocumentor/phpdocumentor

Generierung der Dokumentation:

php vendor/bin/phpdoc

Zusammenfassung

  • Coding-Standards und Konventionen: Halten Sie sich an PSR-Standards und nutzen Sie Tools zur Automatisierung.
  • SOLID-Prinzipien: Implementieren Sie diese Prinzipien, um Ihren Code wartbarer und erweiterbarer zu machen.
  • Design Patterns: Nutzen Sie bewährte Muster wie Repository und Service Layer, um die Struktur Ihrer Anwendung zu verbessern.
  • Refactoring und Codequalität: Verwenden Sie statische Analysetools und führen Sie regelmäßige Code Reviews durch.
  • Dokumentation und Codekommentare: Dokumentieren Sie Ihren Code sorgfältig und nutzen Sie Standards wie PHPDoc.

Weiterführende Ressourcen

The Symfony Framework Best Practices 

Coding Standards

PHP-FIG


CEO Image

Ali Ajjoub

info@ajjoub.com

Adresse 0049-15773651670

Adresse Jacob-winter-platz,1 01239 Dresden

Buchen Sie jetzt Ihren Termin für eine umfassende und individuelle Beratung.

Termin Buchen

Kontaktieren Sie uns

Lassen Sie uns K o n t a k t aufnehmen!