SlideShare ist ein Scribd-Unternehmen logo
1 von 51
Frank Kleine
Go OO
#IPC13
5 WICHTIGE DESIGN PATTERNS
Dienstag, 4. Juni 13
Lebt in
Karlsruhe
Nicht Stephan
Schmidt
Frank Kleine
Software
Architect
Dienstag, 4. Juni 13
Lebt in
Karlsruhe
Nicht Stephan
Schmidt
Frank Kleine
Software
Architect
Dienstag, 4. Juni 13
Frank Kleine
Go OO
#IPC13
5 WICHTIGE DESIGN PATTERNS
Dienstag, 4. Juni 13
Frank Kleine
Go OO
#IPC13
5 DESIGN PATTERNSvöllig subjektiv
ausgewählte
Dienstag, 4. Juni 13
Design
Patterns
1 2
Hilfreiche
Tipps
Dienstag, 4. Juni 13
5 Design Patterns
1
Dienstag, 4. Juni 13
Design Patterns?
Dienstag, 4. Juni 13
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
Definition: IKEA
Dienstag, 4. Juni 13
Composite
Dienstag, 4. Juni 13
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
Theorie
Dienstag, 4. Juni 13
Beispiel: Conditions
$condition = new AndCondition();
$condition->addCondition(new FooCondition())
$or = new OrCondition();
$or->addCondition(new BarCondition());
$or->addCondition(new BazCondition());
$condition->addCondition($or);
if ($condition->isValid(‘foo.txt‘)) {
echo ‘Is valid!‘;
}
Dienstag, 4. Juni 13
Beispiel: Doctrine
$logger = new LoggerChain();
$logger->addLogger(new EchoSQLLogger());
$logger->addLogger(new DebugStack());
$conn->getConfiguration()->setSQLLogger($logger):
Dienstag, 4. Juni 13
Decorator
Dienstag, 4. Juni 13
Zweck
• Hinzufügen neuer Funktionalität zur Laufzeit
• Vorhandene Funktionalität ändern
• Verschiedene Funktionalitäten kombinieren
• Nutzung von Komposition statt Vererbung
Dienstag, 4. Juni 13
Theorie
Dienstag, 4. Juni 13
Beispiel: Symfony2
$kernel = new HttpKernel($dispatcher, $resolver);
$kernel = new HttpCache($kernel,
new Store(__DIR__.'/cache'));
$kernel->handle($request)->send();
Dienstag, 4. Juni 13
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
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
Template Method
Dienstag, 4. Juni 13
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
Theorie
Dienstag, 4. Juni 13
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
Command
Dienstag, 4. Juni 13
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
Theorie
Dienstag, 4. Juni 13
Beispiel: Cart Mapping
interface MappingCommand {
function execute(Context $context, Cart $cart);
function undo(Context $context, Cart $cart);
}
class Mapping {
...
function applyMapping(Context $context , Cart $cart) {
foreach ($this->mapCommands as $mapCommand) {
$mapCommand->execute($context, $cart);
}
}
}
Dienstag, 4. Juni 13
Moment...
• Command dient zum Herumreichen von Code.
• Das geht doch auch mit Closures...
Dienstag, 4. Juni 13
Beispiel: callable
class Batch {
private $commands = array();
public function addCommand(callable $command) {
$this->commands = $command;
}
public function execute(Directory $dir) {
foreach ($this->commands as $command) {
$command($dir);
}
}
}
$batch = new Batch();
$batch->addCommand(function (Directory $dir) { ... });
$batch->addCommand([‘Example‘, ‘clear‘]);
$batch->execute();
Dienstag, 4. Juni 13
Visitor
Dienstag, 4. Juni 13
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
Theorie
Dienstag, 4. Juni 13
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
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
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
5 Hilfreiche Tipps
2
Dienstag, 4. Juni 13
Klasse statt Masse
Dienstag, 4. Juni 13
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
Design Patterns sind ein Gewürz
Dienstag, 4. Juni 13
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
Manchmal reicht eine Funktion
Dienstag, 4. Juni 13
Funktionen
• Es muss nicht immer eine Methode in einer Klasse sein
• Vorsicht vor Klassen wie Utility, Helper o.ä.
• Autoload?
Dienstag, 4. Juni 13
Composer hilft weiter
"autoload": {
"psr-0": {
"examplefoo": "src"
},
"files": ["src/functions.php",
"src/other/functions.php"
]
}
Dienstag, 4. Juni 13
Namen sind nicht Schall und Rauch
Dienstag, 4. Juni 13
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
Die erste Lösung ist falsch.
Dienstag, 4. Juni 13
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
www. phpdesignpatterns .de
Dienstag, 4. Juni 13
@BOVIGO
HTTPS://JOIND.IN/8776
VIELEN DANK
Dienstag, 4. Juni 13

Weitere ähnliche Inhalte

Go OO! 5 wichtige Design Patterns

  • 1. Frank Kleine Go OO #IPC13 5 WICHTIGE DESIGN PATTERNS Dienstag, 4. Juni 13
  • 2. Lebt in Karlsruhe Nicht Stephan Schmidt Frank Kleine Software Architect Dienstag, 4. Juni 13
  • 3. Lebt in Karlsruhe Nicht Stephan Schmidt Frank Kleine Software Architect Dienstag, 4. Juni 13
  • 4. Frank Kleine Go OO #IPC13 5 WICHTIGE DESIGN PATTERNS Dienstag, 4. Juni 13
  • 5. Frank Kleine Go OO #IPC13 5 DESIGN PATTERNSvöllig subjektiv ausgewählte Dienstag, 4. Juni 13
  • 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
  • 14. Beispiel: Conditions $condition = new AndCondition(); $condition->addCondition(new FooCondition()) $or = new OrCondition(); $or->addCondition(new BarCondition()); $or->addCondition(new BazCondition()); $condition->addCondition($or); if ($condition->isValid(‘foo.txt‘)) { echo ‘Is valid!‘; } Dienstag, 4. Juni 13
  • 15. Beispiel: Doctrine $logger = new LoggerChain(); $logger->addLogger(new EchoSQLLogger()); $logger->addLogger(new DebugStack()); $conn->getConfiguration()->setSQLLogger($logger): Dienstag, 4. Juni 13
  • 17. Zweck • Hinzufügen neuer Funktionalität zur Laufzeit • Vorhandene Funktionalität ändern • Verschiedene Funktionalitäten kombinieren • Nutzung von Komposition statt Vererbung 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
  • 29. Beispiel: Cart Mapping interface MappingCommand { function execute(Context $context, Cart $cart); function undo(Context $context, Cart $cart); } class Mapping { ... function applyMapping(Context $context , Cart $cart) { foreach ($this->mapCommands as $mapCommand) { $mapCommand->execute($context, $cart); } } } Dienstag, 4. Juni 13
  • 30. Moment... • Command dient zum Herumreichen von Code. • Das geht doch auch mit Closures... Dienstag, 4. Juni 13
  • 31. Beispiel: callable class Batch { private $commands = array(); public function addCommand(callable $command) { $this->commands = $command; } public function execute(Directory $dir) { foreach ($this->commands as $command) { $command($dir); } } } $batch = new Batch(); $batch->addCommand(function (Directory $dir) { ... }); $batch->addCommand([‘Example‘, ‘clear‘]); $batch->execute(); 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
  • 41. Design Patterns sind ein Gewürz 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
  • 43. Manchmal reicht eine Funktion 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
  • 46. Namen sind nicht Schall und Rauch 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
  • 48. Die erste Lösung ist falsch. 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