Hallo dedlfix,
Wenn die Funktionalität nicht auf interne Methoden aufgeteilt werden soll, kann man auch ganz auf die Klase verzichten und eine einfache Funktion erstellen.
Das lag mir auch auf der Zunge: So eine Klasse nennt man Funktion 😂
Aber der Nutzen liegt genau in dem, was Du nennst: interne Methoden. Da PHP keine lokalen Funktionen kennt (es sei denn man nutzt anonyme Funktionen), ist eine solche Klasse ein mögliches Mittel, um eine Aufgabe in überschaubare Teilfunktionen zu gliedern und so die Übersicht zu behalten.
Das kann man auch mit einer statischen Klasse machen, ja. Eine statische Klasse hat den Nachteil, dass die internen Methoden alle Daten über Parameter erhalten müssen. Das passt zum funktionalen Paradigma, aber ist PHP für funktionale Programmierung optimiert? Wenn man ein Objekt erzeugt, hat man einen Container für Variablen, die von Konstruktor und Helper-Methoden geteilt werden können.
Ob es sinnvoll ist, die Arbeit im Konstruktor zu erledigen, ist eine andere Frage. Es hängt davon ab, was das Ergebnis der Konstruktoraktivitäten ist. Entsteht nur ein einziger Wert oder eine größere Datenstruktur? Werden Werte aus einer externen Quelle eingelesen? Ist das Objekt bei einem Fehler im Konstruktor lebensfähig? Gerade die letzte Frage ist entscheidend. Ein Konstruktor soll eigentlich nur das Objekt initialisieren. Die Arbeit machen die Methoden. Wenn im Konstruktor etwas schiefgeht, kannst Du keinen Fehlercode zurückgeben. Du kannst nur eine Exception werfen, oder Du musst eine $success-Eigenschaft vorsehen. Code wie diesen finde ich aber nicht so schön:
$foo = new FooTool($data1, $data2, ..., $dependency1, $dependency2, ...);
if ($foo->success) {
$result = $foo->data;
// etc
}
Vor allem die Vermischung von Arbeitsdaten und Dependencies in den Parametern gefällt mir nicht. Ich würde dem Worker-Schema folgen und der Methode, die die Arbeit macht, einen Namen geben, der auf die Art der verrichteten Arbeit klar hinweist. Gute Namen ersparen 90% der Kommentare. FooWorker und CreateBarData sind natürlich wenig sprechend 😉
$worker = new FooWorker($dependency1, $dependency2, ...);
$success = $worker->CreateBarData($data1, $data2, ...);
if ($success) {
$result = $worker->data;
// etc
}
Dependencies gehen in den Konstruktor, das sind Referenzen auf andere Dienste im Programm. Arbeitsdaten gehen als Parameter an die Run-Methode.
Wenn sich für die Run-Methode kein sinnvollerer Name als "Run" findet, ist das Objekt vielleicht besser ein Funktor:
$foo = new BarWorker($dep1, $dep2, ...);
$result = $foo($data1, data2);
Dein "Häää? Wie geht denn das?" beantwortet sich hier (Magic method __invoke
).
Das Ergebnis kann man über Eigenschaften bereitstellen. Man kann hier aber auch PHP-Interfaces wie Iterator oder ArrayAccess einsetzen, um einen "natürlicheren" Zugang zu den Daten zu erhalten.
$worker = new FooWorker();
if ($worker->GetPersons("Müller")) {
foreach ($worker as $person) { // Nutzt das Iterable-Interface
}
// oder
$person = $worker[4]; // Nutzt das ArrayAccess-Interface
}
Rolf
sumpsi - posui - clusi