Dependency Injection, Service Locator, Client Session State, Class Table Inheritance - klingt alles wie der neue heiße Scheiß. Aber es gab Entwurfsmuster schon bevor jeder von Enterprise gesprochen hat. Lernen Sie die fünf wichtigsten Patterns kennen und wie Sie sie für schönere PHP-Architekturen einsetzen können.
9. Definition: Wikipedia
Entwurfsmuster (englisch design patterns)
sind bewährte Lösungsschablonen für
wiederkehrende Entwurfsprobleme sowohl in
der Architektur als auch in der
Softwarearchitektur und -entwicklung. Sie
stellen damit eine wiederverwendbare Vorlage
zur Problemlösung dar, die in einem bestimmten
Zusammenhang einsetzbar ist.
Dienstag, 4. Juni 13
12. Zweck
• Beliebige Zahl von Klassen gleicher Art soll für den Client wie eine
einzige Klasse erscheinen
• Verstecken von Hierarchien vor dem Client
• Logik des Zusammenschlusses soll für Client transparent bleiben
Dienstag, 4. Juni 13
19. Beispiel: Symfony2
$kernel = new HttpKernel($dispatcher, $resolver);
$kernel = new HttpCache($kernel,
new Store(__DIR__.'/cache'));
$kernel->handle($request)->send();
Dienstag, 4. Juni 13
20. Beispiel: Symfony2
$kernel = new HttpKernel($dispatcher, $resolver);
$kernel = new HttpCache($kernel,
new Store(__DIR__.'/cache'));
$kernel->handle($request)->send();
public function handle($request) {
if ($this->hasCachedResponse($request) {
return $this->getCachedResponse($request);
}
$response = $this->originalKernel->handle($request);
$this->store($response);
return $response;
}
Dienstag, 4. Juni 13
21. Beispiel: stackphp
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpKernelHttpCacheStore;
$app = new SilexApplication();
$app->get('/', function () {
return 'Hello World!';
});
$stack = (new StackBuilder())
->push('StackSession')
->push('SymfonyComponentHttpKernelHttpCache
HttpCache', new Store(__DIR__.'/cache'));
$app = $stack->resolve($app);
$request = Request::createFromGlobals();
$response = $app->handle($request)->send();
Dienstag, 4. Juni 13
23. Zweck
• Sicherstellen der Reihenfolge von Schritten, mit der Möglichkeit einzelne
Schritte unterschiedlich zu implementieren
• Einzelschritte können mit Standardmethode bereit gestellt und damit
optional überschrieben werden
Dienstag, 4. Juni 13
25. Beispiel
abstract class Recipe {
public function prepare() {
$this->collectIngredients();
$this->prepareIngredients();
return $this->cook();
}
protected abstract function collectIngredients();
protected abstract function prepareIngredients();
protected abstract function cook();
}
class CheeseburgerRecipe extends Recipe {
protected function collectIngredients() { ... }
protected function prepareIngredients() { ... }
protected function cook() { ... }
}
Dienstag, 4. Juni 13
27. Zweck
• Ausführen von Aktionen ohne dass Client konkrete Aktion kennt
• Beliebige Kombinationen verschiedener Aktionen
• Optional: Bereitstellung von Undo-Funktionalität (jedoch kein Bestandteil
des Patterns selbst)
Dienstag, 4. Juni 13
33. Zweck
• Hinzufügen neuer Operationen zu einer Objektstruktur
• Neue Operationen werden im Visitor gekapselt
• Achtung: gegebenenfalls Aufbruch der Kapselung in Objektstruktur
erforderlich
Dienstag, 4. Juni 13
35. Beispiel: vfsStream
vfsStream::setup(‘root‘, null, $complexStructure);
vfsStream::inspect(new vfsStreamPrintVisitor());
interface vfsStreamVisitor {
function visit(vfsStreamContent $content);
function visitFile(vfsStreamFile $file);
function visitDirectory(vfsStreamDirectory $dir);
}
Dienstag, 4. Juni 13
36. Achtung
• Visitor in vfsStream kennt Datenstruktur - leichte Abwandlung des
Originalpatterns
• Original: Visitor kennt Datenobjekte, aber nicht Datenstruktur
• Datenstruktur reicht Visitor intern durch
Dienstag, 4. Juni 13
37. Beispiel: Original
class RentalAction {
...
public function accept(Visitor $visitor) {
$visitor->visitRentalAction($this);
$this->vehicle->accept($visitor);
$this->customer->accept($visitor);
}
}
interface Visitor {
function visitRentalAction(RentalAction $rent);
function visitVehicle(Vehicle $vehicle);
function visitCustomer(Customer $customer);
}
$visitor = new DebugVisitor();
$rentalAction->accept($visitor);
Dienstag, 4. Juni 13
40. OO in der Königsklasse
• Viele kleine Klassen, die sich miteinander kombinieren lassen
• Große, umfangreiche Klassen führen zu geringer Flexibilität und sind eine
Garantie für die Wartungshölle
• Lieber Massen von Klassen statt viel Masse in einer Klasse
Dienstag, 4. Juni 13
42. Hinweise zum Einsatz
• Design Patterns sollen den Code besser strukturieren und verständlicher
machen
• Zu viel davon und der Code wird ungenießbar
• Das Pattern von heute ist das Anti-Pattern von morgen
Dienstag, 4. Juni 13
44. Funktionen
• Es muss nicht immer eine Methode in einer Klasse sein
• Vorsicht vor Klassen wie Utility, Helper o.ä.
• Autoload?
Dienstag, 4. Juni 13
45. Composer hilft weiter
"autoload": {
"psr-0": {
"examplefoo": "src"
},
"files": ["src/functions.php",
"src/other/functions.php"
]
}
Dienstag, 4. Juni 13
47. Namen
• Code kommuniziert.
• Der erste Name ist immer falsch.
• Wenn sich kein passender Name findet: Fachliches Verständnis falsch?
Code überdenken und umbauen.
Dienstag, 4. Juni 13
49. Mindestens nicht richtig.
• Nie bei der ersten Lösung bleiben - sie mag zwar nicht falsch sein, ist
aber wahrscheinlich auch nicht korrekt.
• Selbst wenn sie richtig ist: es geht immer noch einfacher.
• Mit anderen darüber reden hilft.
Dienstag, 4. Juni 13