Duplicate Code (auf Deutsch: "doppelter Code" oder "Code-Duplizierung") bezeichnet das mehrfache Vorhandensein identischer oder sehr ähnlicher Codeabschnitte in einem Programm. Es wird als schlechte Praxis angesehen, weil es zu Problemen in der Wartbarkeit, Lesbarkeit und Fehleranfälligkeit des Codes führen kann.
1. Exakter Duplikat: Der Code ist vollständig identisch. Dies tritt häufig auf, wenn ein Entwickler denselben Code kopiert und an mehreren Stellen einfügt.
Beispiel:
def calculate_area_circle(radius):
return 3.14 * radius * radius
def calculate_area_sphere(radius):
return 3.14 * radius * radius # Identischer Code
2. Strukturelle Duplikate: Der Code ist nicht exakt gleich, aber in seiner Struktur und Funktionalität ähnlich. Lediglich Variablen oder Namen wurden geändert.
Beispiel:
def calculate_area_circle(radius):
return 3.14 * radius * radius
def calculate_area_square(side):
return side * side # Ähnlich strukturiert
3. Logische Duplikate: Der Code macht funktional das Gleiche, sieht aber syntaktisch unterschiedlich aus.
Beispiel:
def calculate_area_circle(radius):
return 3.14 * radius ** 2
def calculate_area_circle_alt(radius):
return 3.14 * radius * radius # Funktional gleich, aber anderer Stil
1. Refactoring: Ähnlichen oder identischen Code in eine gemeinsame Funktion oder Methode auslagern.
Beispiel:
def calculate_area(shape, dimension):
if shape == 'circle':
return 3.14 * dimension * dimension
elif shape == 'square':
return dimension * dimension
2. Modularisierung: Funktionen und Klassen verwenden, um Wiederholungen zu reduzieren.
3. DRY-Prinzip anwenden: "Don't Repeat Yourself" – Entwickle so, dass keine Information oder Logik doppelt implementiert wird.
4. Tools verwenden: Tools wie SonarQube oder CodeClimate können Duplicate Code automatisch erkennen.
Duplicate Code zu reduzieren, verbessert die Codequalität, erleichtert die Wartung und minimiert das Risiko von Fehlern in der Software.
PSR-12 ist ein Standard der PHP-Fig (PHP Framework Interoperability Group), der Coding-Style-Guidelines für PHP definiert. Es baut auf PSR-1 (Basic Coding Standard) und PSR-2 (Coding Style Guide) auf und erweitert diese, um modernere Anforderungen und Best Practices zu berücksichtigen.
PSR-12 zielt darauf ab, einen einheitlichen und lesbaren Code-Stil für PHP-Projekte zu schaffen. Dies erleichtert die Zusammenarbeit zwischen Entwicklern und sorgt für Konsistenz in der Codebasis.
namespace-Deklaration muss eine Leerzeile stehen.use-Anweisungen werden nach der namespace-Deklaration gruppiert.namespace App\Controller;
use App\Service\MyService;
use Psr\Log\LoggerInterface;
{ einer Klasse oder Methode steht in der nächsten Zeile.public, protected, private) sind bei allen Methoden und Eigenschaften zwingend erforderlich.class MyClass
{
private string $property;
public function myMethod(): void
{
// code
}
}
public function myFunction(
int $param1,
string $param2
): string {
return 'example';
}
{ muss in derselben Zeile wie die Kontrollstruktur stehen.if ($condition) {
// code
} elseif ($otherCondition) {
// code
} else {
// code
}
[]) geschrieben werden.$array = [
'first' => 'value1',
'second' => 'value2',
];
? vor dem Typ deklariert.public function getValue(?int $id): ?string
{
return $id !== null ? (string) $id : null;
}
<?php-Tag beginnen und dürfen kein schließendes ?>-Tag enthalten.PSR-12 erweitert PSR-2 um:
PSR-12 ist der Standard für modernen und konsistenten PHP-Code. Es bringt Klarheit und Struktur in PHP-Projekte, besonders bei Teams, die gemeinsam an einer Codebasis arbeiten. Mit Tools wie PHP_CodeSniffer oder PHP-CS-Fixer kannst du PSR-12 problemlos einhalten.
PSR-11 ist eine PHP-Standard-Empfehlung (PHP Standard Recommendation), die sich mit der Container-Interface-Definition beschäftigt. Sie beschreibt ein einheitliches Interface für Dependency Injection Container, das in PHP-Projekten verwendet werden kann. Dependency Injection Container sind Werkzeuge, die Klassen und ihre Abhängigkeiten verwalten und auflösen.
PSR-11 wurde eingeführt, um sicherzustellen, dass verschiedene Frameworks, Bibliotheken und Tools interoperabel mit Dependency Injection Containern arbeiten können. Durch die Einhaltung dieses Standards wird es möglich, verschiedene Container in einem Projekt zu verwenden, ohne den Code ändern zu müssen.
PSR-11 definiert zwei Interfaces:
ContainerInterface
namespace Psr\Container;
interface ContainerInterface {
public function get(string $id);
public function has(string $id): bool;
}
get(string $id): Gibt die Instanz (oder den Service) zurück, die im Container unter einer bestimmten ID registriert ist.has(string $id): Prüft, ob der Container eine Instanz mit der angegebenen ID enthält.2. NotFoundExceptionInterface
namespace Psr\Container;
interface NotFoundExceptionInterface extends ContainerExceptionInterface {
}
3. ContainerExceptionInterface
PSR-11 wird häufig in Frameworks wie Symfony, Laravel, oder Zend Framework (jetzt Laminas) verwendet, die Dependency Injection Container bereitstellen. Auch Tools wie PHP-DI oder Pimple unterstützen PSR-11.
Ein einfaches Beispiel für den Einsatz von PSR-11:
use Psr\Container\ContainerInterface;
class MyService {
public function __construct(private string $message) {}
public function greet(): string {
return $this->message;
}
}
$container = new SomePSR11CompliantContainer();
$container->set('greeting_service', function() {
return new MyService('Hello, PSR-11!');
});
if ($container->has('greeting_service')) {
$service = $container->get('greeting_service');
echo $service->greet(); // Ausgabe: Hello, PSR-11!
}
PSR-11 ist eine wichtige Schnittstelle für modernes PHP-Entwickeln, da sie Abhängigkeiten und deren Auflösung standardisiert. Dies führt zu flexibleren und besser wartbaren Anwendungen.
PSR-7 ist eine PHP Standard Recommendation (PSR), die sich auf HTTP-Nachrichten in PHP bezieht. Sie wurde von der PHP-FIG (Framework Interoperability Group) entwickelt und definiert Schnittstellen für das Arbeiten mit HTTP-Nachrichten, wie sie von Webservern und -Clients verwendet werden.
Request und Response:
PSR-7 standardisiert, wie HTTP-Requests und -Responses in PHP dargestellt werden. Es stellt Schnittstellen für:
Unveränderlichkeit (Immutability):
Alle Objekte sind unveränderlich. Das bedeutet, dass Änderungen an einem HTTP-Objekt ein neues Objekt erzeugen, anstatt das bestehende zu modifizieren. Dies verbessert die Vorhersagbarkeit und erleichtert Debugging.
Streams:
PSR-7 verwendet Stream-Objekte, um HTTP-Nachrichtenkörper zu handhaben. Die StreamInterface definiert Methoden für die Arbeit mit Streams (z. B. read(), write(), seek()).
ServerRequest:
Die Schnittstelle ServerRequestInterface erweitert RequestInterface, um zusätzliche Daten wie Cookies, Server-Parameter und hochgeladene Dateien zu behandeln.
Kompatibilität mit Middleware:
PSR-7 ist der Grundstein für Middleware-Architekturen in PHP. Es erleichtert die Entwicklung von Middleware-Komponenten, die HTTP-Anfragen verarbeiten und Antworten manipulieren.
PSR-7 ist in modernen PHP-Frameworks und -Libraries weit verbreitet, darunter:
Das Ziel von PSR-7 ist es, die Interoperabilität zwischen verschiedenen PHP-Bibliotheken und -Frameworks zu verbessern, indem ein gemeinsamer Standard für HTTP-Nachrichten definiert wird.
PSR-6 ist ein Standard des PHP-FIG (PHP Framework Interoperability Group), der eine gemeinsame Schnittstelle für das Caching in PHP-Anwendungen definiert. Diese Spezifikation, die als „Caching Interface“ bekannt ist, zielt darauf ab, Interoperabilität zwischen verschiedenen Caching-Bibliotheken zu fördern, indem sie eine standardisierte API bereitstellt.
Wichtige Bestandteile von PSR-6 sind:
Cache Pool Interface (CacheItemPoolInterface): Stellt eine Sammlung von Cache-Elementen dar. Es ist verantwortlich für das Verwalten, Abrufen, Speichern und Löschen von Cache-Daten.
Cache Item Interface (CacheItemInterface): Repräsentiert einzelne Cache-Elemente innerhalb des Pools. Jedes Cache-Element enthält einen eindeutigen Schlüssel und einen gespeicherten Wert und kann so konfiguriert werden, dass es nach einer bestimmten Zeit abläuft.
Standardisierte Methoden: PSR-6 definiert Methoden wie getItem(), hasItem(), save() und deleteItem() im Cache-Pool sowie get(), set() und expiresAt() im Cache-Element-Interface, um Cache-Operationen zu standardisieren und Konsistenz sicherzustellen.
Durch die Definition dieser Schnittstellen ermöglicht PSR-6 Entwicklern das einfache Austauschen von Caching-Bibliotheken oder das Integrieren verschiedener Caching-Lösungen, ohne die Kernlogik der Anwendung ändern zu müssen.
PSR-4 ist eine PHP-Standard-Empfehlung für das Autoloading von Klassen basierend auf Namespaces und Dateipfaden. Dieser Standard wurde von der PHP-FIG (PHP Framework Interop Group) entwickelt und beschreibt, wie vollständig qualifizierte Klassennamen zu den entsprechenden Dateipfaden gemappt werden. Dadurch kann PHP Klassen automatisch finden und laden, ohne dass manuelle require- oder include-Anweisungen nötig sind.
Namespace-Zuordnung: PSR-4 verlangt, dass der Namespace und Klassenname mit der Verzeichnisstruktur und dem Dateinamen übereinstimmen. Jeder Namespace-Präfix wird mit einem Basisverzeichnis verknüpft, und innerhalb dieses Verzeichnisses entspricht die Verzeichnisstruktur dem Namespace.
Basisverzeichnis: Für jeden Namespace-Präfix wird ein Basisverzeichnis definiert, und die Klassen werden in Unterverzeichnissen des Basisverzeichnisses entsprechend ihrer Namespace-Struktur abgelegt. Zum Beispiel:
App\Controllers ist, sollte die Datei in einem Verzeichnis wie /path/to/project/src/Controllers liegen.Dateibenennung: Der Klassenname muss genau mit dem Dateinamen übereinstimmen und mit .php enden.
Kompatibilität mit Autoloadern: Die Implementierung von PSR-4 gewährleistet Kompatibilität mit modernen Autoloadern wie dem von Composer, wodurch PHP Klassen automatisch ohne manuelle Einbindung findet.
Angenommen, Sie haben die Klasse App\Controllers\UserController, so sollte die Verzeichnisstruktur wie folgt aussehen:
/path/to/project/src/Controllers/UserController.php
In der composer.json von Composer wird diese Zuordnung wie folgt angegeben:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Dies weist Composer an, die Klassen im App-Namespace aus dem src/-Verzeichnis zu laden. Wenn Sie composer dump-autoload ausführen, wird Composer das Autoloading gemäß dem PSR-4-Standard konfigurieren.
PSR-4 hat den älteren PSR-0-Standard abgelöst und ist nun der bevorzugte Autoloading-Standard für moderne PHP-Projekte.
PSR-3 ist eine Empfehlung der PHP-FIG (PHP Framework Interoperability Group), die ein standardisiertes Interface für Logging-Bibliotheken in PHP-Anwendungen festlegt. Das Ziel ist es, Entwicklern eine einheitliche und flexible Schnittstelle für das Logging bereitzustellen, die unabhängig von der verwendeten Bibliothek funktioniert. Dadurch können Log-Bibliotheken leicht ersetzt oder geändert werden, ohne dass bestehender Code angepasst werden muss.
Standardisiertes Logger-Interface: PSR-3 definiert das Interface Psr\Log\LoggerInterface mit verschiedenen Methoden für unterschiedliche Log-Level wie emergency(), alert(), critical(), error(), warning(), notice(), info() und debug().
Log-Level: Die acht vordefinierten Log-Level (z. B. emergency, alert, error) basieren auf dem weit verbreiteten Syslog-Protokoll RFC 5424, was die Kompatibilität mit vielen Logging-Systemen sicherstellt.
Nachrichteninterpolation: PSR-3 erlaubt es, Platzhalter in Log-Nachrichten (z. B. {platzhalter}) durch tatsächliche Werte zu ersetzen. Beispiel:$logger->error("Benutzer {username} nicht gefunden", ['username' => 'johndoe']);Dadurch werden Log-Nachrichten konsistent und lesbar formatiert, ohne dass aufwendige String-Manipulation nötig ist.
Flexible Implementierung: Jede Logging-Bibliothek, die LoggerInterface implementiert, kann in PSR-3-kompatiblem Code verwendet werden, wie etwa die weit verbreitete Bibliothek Monolog.
Dynamische Log-Level: Mit der log()-Methode kann man Nachrichten auch dynamisch auf jedem gewünschten Log-Level protokollieren, indem der Level als Parameter übergeben wird.
Hier ein Beispiel, wie ein PSR-3-konformer Logger verwendet wird:
use Psr\Log\LoggerInterface;
class UserService
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function findUser($username)
{
$this->logger->info("Suche nach Benutzer {username}", ['username' => $username]);
// ...
}
}
Mehr Informationen und Details finden sich auf der offiziellen PHP-FIG-Seite zur PSR-3-Spezifikation.
PSR-2 ist eine Richtlinie für den Programmierstil in PHP, die von der PHP-Fig (Framework Interop Group) als Empfehlung erstellt wurde. Die Abkürzung „PSR“ steht für „PHP Standards Recommendation“. PSR-2 wurde speziell entwickelt, um den Code lesbarer und einheitlicher zu machen, sodass verschiedene Entwicklerteams besser zusammenarbeiten können.
{ für Klassen und Methoden gehört in die nächste Zeile, die für Kontrollstrukturen wie if oder for in dieselbe Zeile.=, +, etc., wird ein Leerzeichen verwendet.Hier ist ein einfaches Beispiel, das die Richtlinien zeigt:
<?php
namespace Vendor\Package;
class ExampleClass
{
public function exampleMethod($arg1, $arg2 = null)
{
if ($arg1 === $arg2) {
throw new \Exception('Arguments cannot be equal');
}
return $arg1;
}
}
PSR-2 wurde inzwischen von PSR-12 erweitert und ersetzt, das zusätzliche Regeln zur Verbesserung der Code-Konsistenz einführt.
"Lines of Code" (LOC) ist eine Metrik in der Softwareentwicklung, die die Anzahl der geschriebenen Codezeilen in einem Programm oder einer Anwendung zählt. Diese Metrik wird oft zur Einschätzung des Umfangs, der Komplexität und des Entwicklungsaufwands eines Projekts verwendet. LOC wird auf verschiedene Arten eingesetzt:
Code-Komplexität und Wartbarkeit: Eine höhere Anzahl von LOC kann auf ein komplexeres oder schwer wartbares Projekt hinweisen. Entwickler versuchen oft, den Code schlank und effizient zu halten, weil weniger Zeilen potenziell weniger Fehlerquellen und einfachere Wartung bedeuten.
Produktivitätsbewertung: In manchen Organisationen wird LOC genutzt, um die Produktivität von Entwicklern zu messen, wobei jedoch die Qualität des Codes und nicht nur die Quantität berücksichtigt werden sollte. Denn viele Zeilen Code könnten auch durch ineffiziente Lösungen oder Redundanzen entstehen.
Projektfortschritt und Schätzungen: LOC kann helfen, den Fortschritt eines Projekts zu messen oder eine grobe Schätzung des Entwicklungsaufwands für zukünftige Projekte zu erstellen.
Obwohl LOC eine einfache und weitverbreitete Metrik ist, hat sie ihre Grenzen, da sie nichts über die tatsächliche Effizienz, Lesbarkeit oder Qualität des Codes aussagt.
Die zyklomatische Komplexität ist eine Kennzahl zur Bewertung der Komplexität eines Programmcodes oder eines Softwaremoduls. Sie misst die Anzahl der unabhängigen Ausführungspfade in einem Programm, basierend auf seiner Kontrollflussstruktur. Diese Metrik wurde von Thomas J. McCabe entwickelt und hilft, die Testbarkeit, Wartbarkeit und Fehleranfälligkeit eines Programms einzuschätzen.
Die zyklomatische Komplexität V(G)V(G) lässt sich mithilfe des Kontrollflussgraphen eines Programms berechnen. Dieser Graph besteht aus Knoten (für Anweisungen oder Blöcke) und Kanten (für die Kontrollflusswege zwischen den Blöcken). Die Formel lautet:
V(G)=E−N+2PV(G) = E - N + 2P
In der Praxis wird oft eine vereinfachte Berechnung verwendet, bei der die Anzahl der Verzweigungspunkte (wie If-, While-, For-Schleifen) addiert wird.
Die zyklomatische Komplexität gibt Auskunft darüber, wie viele Testfälle mindestens nötig sind, um jeden Pfad im Programm einmal zu durchlaufen. Eine höhere zyklomatische Komplexität deutet auf einen komplexeren und möglicherweise fehleranfälligeren Code hin.
Durch die Messung der zyklomatischen Komplexität können Entwickler frühzeitig potenzielle Wartungsprobleme identifizieren und gezielt Bereiche des Codes für Vereinfachung und Refactoring auswählen.