• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Die Kunst Des Software Design
 

Die Kunst Des Software Design

on

  • 8,393 views

Presentation held at PHP World 2009 in Munich together with Holger Rüprich.

Presentation held at PHP World 2009 in Munich together with Holger Rüprich.

Statistics

Views

Total Views
8,393
Views on SlideShare
8,271
Embed Views
122

Actions

Likes
6
Downloads
81
Comments
1

8 Embeds 122

http://rueprich.de 55
http://www.slideshare.net 23
http://webdev.blog.tennessee.1und1.de 20
http://webdev.blog.tennessee.schlund.de 10
http://planet.blog.tennessee.1und1.de 8
http://planet.blog.tennessee.schlund.de 4
http://webdev.blog.chattanooga.1und1.de 1
http://www.thewebhatesme.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Hallo!
    mit welchem Programm öffne ich nun die heruntergeladene Datei 'die-kunst-des-software-design-091125172000-phpapp02.key'?
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Wissen - Ich muss meine Technologie und die Dom&#xE4;ne kennen <br /> &#xDC;bung - Der erste Entwurf geht schief (&#xDC;berflieger: 1000 Stunden, 1000 Fotos f&#xFC;r die Tonne) <br /> Wahrnehmung - Sehen wo die Probleme liegen, Schnelles Verstehen <br /> Vorstellung - Software ist abstrakt <br /> Intuition - Software-Entwurf ist kein striktes logisches Vorgehen
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt... <br /> Sicher - Online Banking, Sensible Daten im Netz <br /> Flexibel - "640kb reichen f&#xFC;r jeden" <br /> Performance - Twitter Ausfall
  • Hamstert N&#xFC;sse, l&#xE4;sst keinen dran...
  • Seite 120 -129 <br /> 5min -> Holger
  • Seite 129 - 130 <br /> Weitere Themen <br /> 5min -> Stephan
  • Seite 137 - 153 <br /> Wikipedia / Internet <br /> 10min -> Holger
  • YAGNI <br /> Premature Optimization <br /> Emergenz <br /> Negativ Beispiele <br /> 10min -> Holger
  • http://www.xprogramming.com/Practices/PracNotNeed.html <br /> <br /> Spekulatives Programmieren
  • Fallbeispiele <br /> 5-10min Stephan
  • http://www.xprogramming.com/Practices/PracNotNeed.html <br /> <br /> Spekulatives Programmieren
  • Holger
  • Cruise Control haupts&#xE4;chlich f&#xFC;r Java bekannt <br /> phpUnderControl Erweiterung f&#xFC;r PHP <br /> Funktionsweise <br /> - Konfiguration per ant (build.xml) <br /> - Checkout Target -> Neuste SVN Version holen <br /> - PHPDoc Target -> Dokumentation generieren <br /> - CodeSniffer Target -> Coding Guidelines validieren <br /> - PHPUnit Target -> Unit Tests durchf&#xFC;hren
  • Hudson - Haupts&#xE4;chlich f&#xFC;r Java l&#xE4;sst sich aber auch f&#xFC;r PHP einsetzen <br /> Xinc - in PHP f&#xFC;r PHP entwickelt <br /> Bamboo - kostenpflichtig

Die Kunst Des Software Design Die Kunst Des Software Design Presentation Transcript

  • Die Kunst des Software-Design oder was Software-Entwickler von der Tierwelt lernen können PHP World Kongress 2009 Holger Rüprich und Stephan Schmidt
  • Holger Rüprich • Head of Sales Processes Consumer bei der 1&1 Internet AG • Clean Code Enthusiast • Gast-Dozent an der Berufs- Akademie Mosbach • Autor für die Zeitschrift T3N
  • Stephan Schmidt • Head of Web Sales Development bei der 1&1 Internet AG • Design Patterns Enthusiast • Autor von PHP Design Patterns sowie anderen Büchern und über 30 Fachartikeln • Redner auf internationalen Konferenzen
  • Software Design „Software Design is a process of problem solving and planning for a software solution.“ Wikipedia
  • Kunst „Das Wort Kunst bezeichnet im weitesten Sinne jede entwickelte Tätigkeit, die auf Wissen, Übung, Wahrnehmung, Vorstellung und Intuition gegründet ist.“ Wikipedia
  • Ziele von Software Design
  • Ziele von Software Design Software soll stabil sein.
  • Ziele von Software Design
  • Ziele von Software Design Software soll sicher sein.
  • Ziele von Software Design
  • Ziele von Software Design Software soll flexibel sein.
  • Ziele von Software Design
  • Ziele von Software Design Software soll performant sein.
  • Ziele von Software Design
  • Das Eichhörnchen
  • Das Eichhörnchen Kapsle Daten und Algorithmen.
  • Von der realen Welt ... • Bob hat eine Autovermietung • Er muss Autos einkaufen • Er vermietet unterschiedliche Modelle • Er vermietet Autos zu verschiedenen Preisen
  • ... zur programmierten Welt • Klassen übertragen Dinge aus der realen Welt in die programmierte Welt class Car { protected $manufacturer; protected $color; protected $milage; protected $engineStarted = false; public function startEngine() {} public function driveForward($miles) {} public function stopEngine() {} public function getManufacturer() {} public function getColor() {} public function getMilage() {} }
  • Kapsle den Zugriff auf Daten Kapsle den Zugriff auf Daten immer innerhalb einer Klasse und biete Methoden an, um diese Daten abzufragen. class Car { ... Eigenschaften und Methoden ... public function getDailyRate($days = 1) { return 75.5; } }
  • Kapsle den Zugriff auf Daten Kapsle den Zugriff auf Daten immer innerhalb einer Klasse und biete Methoden an, um diese Daten abzufragen. class Car { ... Eigenschaften und Methoden ... public function getDailyRate($days = 1) { if ($days >= 7) { return 65.9; } return 75.5; } }
  • Bobs Kunden class Customer { protected $id; protected $name; public function __construct($id, $name) { $this->id = $id; $this->name = $name; } public function getId() { return $this->id; } public function getName() { return $this->name; } }
  • Bobs Firma class RentalCompany { protected $fleet = array(); public function addToFleet($id, Car $car) { $this->fleet[$id] = $vehicle; } public function rentCar(Car $car, Customer $customer) {} public function returnCar(Car $car) {} }
  • Bobs Geschäft • Klassen übertragen nicht nur physikalische Dinge, sondern auch Abläufe class RentalAction { ... Eigenschaften ... public function __construct(Car $car, Customer $customer, $date = null) { if ($date === null) { $date = date('Y-m-d H:i:s'); } $this->car = $car; $this->customer = $customer; $this->rentDate = $date; } ... Getter ... }
  • Bobs Geschäft • Klassen übertragen nicht nur physikalische Dinge, sondern auch Abläufe class RentalAction { ... public function markCarReturned($date = null) { if ($date === null) { $date = date('Y-m-d H:i:s'); } $this->returnDate = $date; } public function isReturned() { return $this->returnDate !== null; } }
  • Kapsle auch Algorithmen Kapsle nicht nur Daten sondern auch Algorithmen in den Methoden deiner Klassen, um komplexe Operationen zentral an einer Stelle zu implementieren.
  • Bobs Firma class RentalCompany { ... public function rentCar(Car $car, Customer $customer) { $carId = array_search($car, $this->fleet); if ($carId === false) { throw new UnknownCarException(); } if (!$this->isCarAvailable($car)) { throw new CarNotAvailableException(); } $rentalAction = new RentalAction($car, $customer); $this->rentalActions[] = $rentalAction; return $rentalAction; } }
  • Bobs Firma class RentalCompany { ... public function isCarAvailable(Car $car) { foreach ($this->rentalActions as $rentalAction) { if ($rentalAction->getCar() !== $car) { continue; } if ($rentalAction->isReturned()) { continue; } return false; } return true; } }
  • Bobs Firma class RentalCompany { ... public function returnCar(Car $car) { foreach ($this->rentalActions as $rentalAction) { if ($rentalAction->getCar() !== $car) { continue; } if ($rentalAction->isReturned()) { continue; } $rentalAction->markCarReturned(); return true; } return false; } }
  • Die Weisheit des Eichhörnchens Schütze deine Daten. Verberge Implementierungsdetails und unterbinde den Zugriff auf interne Datenstrukturen. Wähle Klassen- und Methodennamen sinnvoll und achte darauf, dass der resultierende Code sich wie ein Satz lesen lässt.
  • Das Krokodil
  • Das Krokodil Achte das Single-Reponsibility-Prinzip.
  • Das Single-Responsibility-Prinzip „There should never be more than one reason for a class to change“ Robert C. Martin
  • Bob will wissen was los ist class RentalCompany { public function addToFleet($id, Vehicle $vehicle) { $this->fleet[$id] = $vehicle; print "Neues Auto im Fuhrpark: " . $vehicle->getManufacturer() . "n"; } public function rentVehicle(Vehicle $vehicle, Customer $customer) { ... print "Neuer Mietvorgang: " . $customer->getName() . " leiht " . $vehicle->getManufacturer() . "n"; return $rentalAction; } ... } > Neues Auto im Fuhrpark: BMW > Neuer Mietvorgang: Stephan Schmidt leiht BMW > Rückgabe: Stephan Schmidt gibt BMW zurück > Neuer Mietvorgang: Gerd Schaufelberger leiht BMW
  • Bob will wissen was los ist class RentalCompany { public function addToFleet($id, Vehicle $vehicle) { $this->fleet[$id] = $vehicle; print "Neues Auto im Fuhrpark: " . $vehicle->getManufacturer() . "n"; } Was ist mit Problemen im Produktivbetrieb? public function rentVehicle(Vehicle $vehicle, Customer $customer) { ... print "Neuer Mietvorgang: " . $customer->getName() . " leiht " . $vehicle->getManufacturer() . "n"; return $rentalAction; } ... } > Neues Auto im Fuhrpark: BMW > Neuer Mietvorgang: Stephan Schmidt leiht BMW > Rückgabe: Stephan Schmidt gibt BMW zurück > Neuer Mietvorgang: Gerd Schaufelberger leiht BMW
  • Debugging im Produktivbetrieb class RentalCompany { public function addToFleet($id, Vehicle $vehicle) { $this->fleet[$id] = $vehicle; switch (DEBUG_MODE) { case 'echo': print "Neues Auto im Fuhrpark: " . $vehicle->getManufacturer() . "n"; break; case 'log': error_log("Neues Auto im Fuhrpark: " . $vehicle->getManufacturer() . "n", 3, '.RentalCompany.log'); break; } } public function rentVehicle(Vehicle $vehicle, Customer $customer) { ... switch (DEBUG_MODE) { case 'echo': print "Neuer Mietvorgang: " . $customer->getName() . " leiht " . $vehicle->getManufacturer() . "n"; break; ... return $rentalAction; }
  • Debugging im Produktivbetrieb class RentalCompany { public function addToFleet($id, Vehicle $vehicle) { $this->fleet[$id] = $vehicle; switch (DEBUG_MODE) { case 'echo': print "Neues Auto im Fuhrpark: " . $vehicle->getManufacturer() . "n"; break; case 'log': error_log("Neues Auto im Fuhrpark: " . $vehicle->getManufacturer() . "n", Code Duplizierung macht die Anwendung 3, '.RentalCompany.log'); break; langsamer und schwerer zu warten } } public function rentVehicle(Vehicle $vehicle, Customer $customer) { ... switch (DEBUG_MODE) { case 'echo': print "Neuer Mietvorgang: " . $customer->getName() . " leiht " . $vehicle->getManufacturer() . "n"; break; ... return $rentalAction; }
  • Wiederverwendbarkeit statt Copy-and-Paste class RentalCompany { public function addToFleet($id, Vehicle $vehicle) { $this->fleet[$id] = $vehicle; $this->debug("Neues Auto im Fuhrpark: " . $vehicle->getManufacturer()); } public function rentVehicle(Vehicle $vehicle, Customer $customer) { ... $this->debug("Neuer Mietvorgang: " . $customer->getName() . " leiht " . $vehicle->getManufacturer()); return $rentalAction; } ... }
  • Wiederverwendbarkeit statt Copy-and-Paste class RentalCompany { ... protected function debug($message) { switch (DEBUG_MODE) { case 'echo': print "{$message}n"; break; case 'log': error_log("{$message}n", 3, './RentalCompany.log'); break; } } }
  • Wiederverwendbarkeit statt Copy-and-Paste class RentalCompany { ... Weitere Debugging-Ziele, wie E-Mails oder SMS, protected function debug($message) { switch (DEBUG_MODE) { machen die debug()-Methode komplexer case 'echo': print "{$message}n"; break; case 'log':und somit fehleranfälliger. error_log("{$message}n", 3, './RentalCompany.log'); break; } } }
  • Atomare Probleme lösen abstract class RentalCompany { ... Eigenschaften und Methoden der Klasse ... abstract protected function debug($message); } class EchoingRentalCompany extends RentalCompany { protected function debug($message) { echo "{$message}n"; } } class LoggingRentalCompany extends RentalCompany { protected function debug($message) { error_log("{$message}n", 3, './RentalCompany.log'); } }
  • Atomare Probleme lösen switch (DEBUG_MODE) { case 'echo': $company = new EchoingRentalCompany(); break; case 'log': $company = new LoggingRentalCompany(); break; } $bmw = new Car('BMW', 'blau'); $stephan = new Customer(1, 'Stephan Schmidt'); $gerd = new Customer(2, 'Gerd Schaufelberger'); $company->addToFleet('bmw1', $bmw); $company->rentVehicle($bmw, $stephan); $company->returnVehicle($bmw);
  • Atomare Probleme lösen switch (DEBUG_MODE) { case 'echo': $company = new EchoingRentalCompany(); break; case 'log': Die debug()-Methode steht nur Unterklassen von $company = new LoggingRentalCompany(); break; } RentalCompany zur Verfügung. $bmw = new Car('BMW', 'blau'); $stephan = new Customer(1, 'Stephan Schmidt'); $gerd = new Customer(2, 'Gerd Schaufelberger'); $company->addToFleet('bmw1', $bmw); $company->rentVehicle($bmw, $stephan); $company->returnVehicle($bmw);
  • Komposition statt Vererbung interface Debugger { public function debug($message); } class DebuggerEcho { public function debug($message) { echo "{$message}n"; } } class DebuggerLog { public function debug($message) { error_log("{$message}n", 3, './RentalCompany.log'); } }
  • Komposition statt Vererbung class RentalCompany { ... Eigenschaften der Klasse ... protected $debugger; public function __construct() { switch (DEBUG_MODE) { case 'echo': $this->debugger = new DebuggerEcho(); break; case 'log': $this->debugger = new DebuggerLog(); break; } } public function debug($message) { $this->debugger->debug($message); } }
  • Die Weisheit des Krokodils Teile und herrsche. Jedes Modul soll genau eine Verantwortung übernehmen, und jede Verantwortung soll genau einem Modul zugeordnet werden.
  • Die Schildkröte
  • Die Schildkröte Achte das Open-Closed-Prinzip.
  • Das Open-Closed-Prinzip „Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.“ Bertrand Meyer
  • Komposition statt Vererbung class RentalCompany { ... Eigenschaften der Klasse ... protected $debugger; public function __construct() { switch (DEBUG_MODE) { case 'echo': $this->debugger = new DebuggerEcho(); break; case 'log': $this->debugger = new DebuggerLog(); break; } } public function debug($message) { $this->debugger->debug($message); } }
  • Komposition statt Vererbung class RentalCompany { ... Eigenschaften der Klasse ... protected $debugger; public function __construct() { switch (DEBUG_MODE) { Die RentalCompany Klassen ist von case 'echo': $this->debugger = new DebuggerEcho(); break; case 'log': anderen Klassen abhängig $this->debugger = new DebuggerLog(); break; } } public function debug($message) { $this->debugger->debug($message); } }
  • Einsatz von Interfaces class RentalCompany { ... Eigenschaften der Klasse ... public function __construct(Debugger $debugger) { $this->debugger = $debugger; } ... weitere Methoden der Klasse ... } $debugger = new DebuggerEcho(); $company = new RentalCompany($debugger);
  • Die Weisheit der Schildkröte Schütze deinen Code. Programmiere immer gegen Schnittstellen, nie gegen eine konkrete Implementierung. Vermeide feste Abhängigkeiten zwischen einzelnen Klassen deiner Anwendungen und ziehe immer lose Kopplung der Klassen vor.
  • Der Erpel
  • Der Erpel Achte das Hollywood-Prinzip.
  • Das Hollywood Prinzip „Rufen Sie uns nicht an, wir werden Sie anrufen.“ Das Hollywood Prinzip
  • Das Hollywood Prinzip • Auch bekannt als „Inversion of Control“ • Objekte sollen sich ihre Abhängigkeiten nicht selbst holen oder erzeugen • Objekte sollen unabhängig von ihrer Umgebung sein
  • Dependency Injection • Objekte erstellen abhängige Objekte nicht selbst • Abhängige Objekte werden von außen über den Konstruktor (Constructor Injection) oder über Setter-Methoden (Setter Injection) injiziert • Abhängige Objekte sind dadurch sehr leicht austauschbar
  • Dependency Injection $debugger = new DebuggerEcho(); $company = new RentalCompany($debugger); Constructor Injection $logger = new DateTimeLogger(); $company->setLogger($logger); Setter Injection • RentalCompany weiß weder, welche Implementierung des Debugger-Interface noch welche Implementierung des Logger-Interface sie verwendet • RentalCompany steuert nicht, wie sie an ihre Abhängigkeiten kommt, der Kontrollfluss wird von außerhalb gesteuert • Aber: Sehr viel zusätzlicher Client Code, durch Instanziieren und Injizieren der Objekte nötig
  • Inversion-of-Control-Container • In der Java-Welt schon weit verbreitet • Spring, Google Guice, Tapestry IoC, ... • In PHP noch nicht weit verbreitet • Stubbles, Garden, XJConf for PHP
  • Stubbles IoC Container • Portierung von Google Guice (Java) • Entwickelt als Teil des Stubble Frameworks • Kann auch außerhalb der Frameworks verwendet werden • Basiert auf Type Hints und Annotations • Keine native Unterstützung durch PHP • Annotations als Teil der PHP-Doc-Kommentare
  • Rufen Sie Bob nicht an, Bob ruft sie an. class RentalCompany { ... Eigenschaften der Klasse ... /** * @Inject Constructor Injection */ public function __construc(Debugger $debugger) { $this->debugger = $debugger; } /** * @Inject Setter Injection */ public function setLogger(Logger $logger) { $this->logger = $logger; } ... }
  • Interfaces binden • Typen werden durch Binder an konkrete Implementierungen gebunden: $binder = new stubBinder(); $binder->bind('Debugger')->to('DebuggerEcho'); $binder->bind('Logger')->to('DateTimeLogger'); • Binder kann Injector liefern, der Instanzen erzeugt: $injector = $binder->getInjector(); $company = $injector->getInstance('RentalCompany');
  • Fortgeschrittene Techniken • Verwenden einer Standardimplementierung /** * @ImplementedBy(DateTimeLogger.class) */ interface Logger { • Mehrere Implementierungen für ein Interface /** * @Inject * @Named("Debugger") public function setLogger(Logger $logger) $binder = new stubBinder(); $binder->bind('Logger')->to('DateTimeLogger'); $binder->bind('Logger')->named('Debugger')->to('SimpleLogger');
  • Die Weisheit des Erpel Verwende ein DI Framework. Erleichtere dir das Verwalten von komplexen Objektstrukturen durch den Einsatz eines Dependency Injection Frameworks.
  • Die Biene
  • Die Biene Nutze Design Patterns.
  • Konkretes Problem „Ich möchte Debug-Meldungen auf verschiedene Arten verarbeiten und diese auswechseln können, ohne den Code der RentalCompany Klasse anpassen zu müssen.“ Bob
  • Abstraktes Problem „Ich möchte eine Aufgabe mit verschiedenen Algorithmen lösen können. Jede der Lösungen soll gekapselt sein und nichts von den anderen wissen. Die einzelnen Lösungen sollen gegeneinander austauschbar sein, ohne den nutzenden Client anzupassen.“ Abstract Bob
  • Konkret vs Abstrakt Abstrakt Konkret Verarbeiten von Debug- Aufgabe Meldungen Ausgeben per print(), Algorithmen Schreiben eines Logfiles Die Klasse Client RentalCompany
  • Konkret vs Abstrakt Abstrakt Konkret Persistieren von Aufgabe Gästebucheinträgen Speichern in Datenbank, Algorithmen Speichern in XML-Datei Client Die Klasse Guestbook
  • Bobs erstes Design Pattern Strategy-Pattern
  • Design Patterns • Lösungsmuster für häufig auftretende Entwurfsaufgaben in der Software- Entwicklung • Keine Code-Bibliothek • Organisiert in Pattern-Katalogen (z.B. Gang-of-Four Buch) • Verschiedene Kategorien: Erzeugungsmuster, Strukturmuster, Verhaltensmuster, Enterprise-Patterns
  • Erzeugungsmuster • Erzeugungsmuster werden verwendet, um Objekte zu konstruieren. • Zu den Erzeugungsmustern gehöhren unter anderem • Singleton-Pattern • Factory-Method-Pattern • Prototype-Pattern • Abstract-Factory-Pattern
  • Factory-Method-Pattern • Definiert eine Schnittstelle zur Erzeugung von Objekten • Verlagert die eigentliche Instanziierung in Unterklassen • Lässt Unterklassen entscheiden, welche konkrete Implementierung verwendet wird
  • Factory-Method-Pattern abstract class AbstractManufacturer { protected $name; public function __construct($name) { $this->name = $name; } public function sellVehicle() { $vehicle = $this->manufactureVehicle(); // weitere Operationen möglich return $vehicle; } public abstract function manufactureVehicle(); }
  • Factory-Method-Pattern class CarManufacturer extends AbstractManufacturer { public function manufactureVehicle() { return new Car($this->name); } } $bmwManufacturer = new CarManufacturer('BMW'); $bmw = $bmwManufacturer->sellVehicle();
  • Factory-Method-Pattern Das Factory-Method-Pattern definiert eine Schnittstelle zur Erzeugung von Objekten. Es verlagert aber die eigentliche Instanziierung in Unterklassen; es lässt die Unterklassen entscheiden, welche konkreten Implementierungen verwendet werden.
  • der abstrak lichen Objekte zu 4. Verwenden Sie nun diese konk reten Unterklassen, um die tatsäch ementierungen zu instanziieren und Ihren Applik ationscode von den konkreten Impl lösen. fach darauf, die verwenden möchten, achten Sie ein Factory-Method-Pattern Wann immer Sie eine Fabrikmetho de hier gezeigten Schritte durchzuführe n, und dem Erfolg Ihres Vorhabens steht nichts mehr teiligten des Fac- n die Beziehungen zwischen den Be im Weg. Abbildung 4-2 zeigt Ihne f die Erzeugung der tory-Method-Patterns und illustri ert noch einmal, wie das Pattern au cle-Implementierungen angewa ndt wurde. Vehi sell Vehicle-Methode, ruft Vehicle-Interface Fabrikmethode auf Creator Product +FactoryMethod() : Product +MethodA() AbstractManufacturer- CarManufacturer und Klasse ConvertibleManufacturer ConcreteCreator ConcreteProduct +FactoryMethod() : Product Implementierungen des Vehicle- Fabrikmethode manufactureVehicle anzen Interfaces wie Car, Convertible et c. erzeugt Car- bzw. Convertible-Inst s Factory-Method-Patterns Abbildung 4-2: UML-Diagramm de Das Factory-Method-Pattern | 177
  • Prototype-Pattern • Das Prototype-Pattern erzeugt Objekte durch das Kopieren eines prototypischen Exemplars • Es ermöglicht das Hinzufügen neuer "Klassen" zur Laufzeit ohne Programmierung • Es hält die Anzahl der benötigten Klassen klein
  • Prototype-Pattern class SpecialEditionManufacturer { protected $prototypes = array(); public function addSpecialEdition($edition, Vehicle $prototype) { $this->prototypes[$edition] = $prototype; } public function manufactureVehicle($edition) { if (!isset($this->prototypes[$edition])) { throw new UnknownSpecialEditionException( 'No prototype for special edition ' . $edition . ' registered'); } return clone $this->prototypes[$edition]; } }
  • Prototype-Pattern class Car implements Vehicle { ... } class Convertible implements Vehicle { ... } $manufacturer = new SpecialEditionManufacturer(); $GolfElvis = new Car('VW', 'silber'); $GolfElvis->setAirConditioned(true); $GolfElvis->setGraphics('Gitarre'); $manufacturer->addSpecialEdition('Golf Elvis Presley Edition', $GolfElvis); $GolfStones = new Convertible('VW', 'rot'); $GolfStones->setAirConditioned(false); $GolfStones->setGraphics('Zunge'); $manufacturer->addSpecialEdition('Golf Rolling Stones Edition', $GolfStones); $golf1 = $manufacturer->manufactureVehicle('Golf Elvis Presley Edition'); $golf2 = $manufacturer->manufactureVehicle('Golf Rolling Stones Edition');
  • Prototype-Pattern Das Prototyp-Muster bestimmt die Arten der zu erzeugenden Objekte durch die Verwendung eines prototypischen Exemplars, das zur Erzeugung neuer Instanzen kopiert wird.
  • Prototype-Pattern !!"""#$#"%&'()*+,,-../0120.)!!..3 4012567.8*.95:;54.)!!8..<<='&.<< Vehicle-Interface SpecialEditionManufacturer __clone()-Methode kennt alle verfügbaren in PHP nicht immer nötig Prototypen rface wie Implementierungen des Vehicle-Inte Car, Convertible etc. e-Patterns Abbildu ng 4-6: UML-Diagramm des Prototyp plikation reduziert die Anzahl der Klassen, die Ihre Ap Der Einsatz des Prototype-Patterns ukte zu sen bilden müssen, um die einzelnen Prod benötigt, da Sie weniger Unterklas en von einer Klasse erzeugen. Stattdessen werden al le Produkte auf Basis der Prototyp
  • Strukturmuster • Strukturmuster befassen sich mit der Komposition von Objekten • Zu den Strukturmustern gehöhren unter anderem • Composite-Pattern • Proxy-Pattern • Adapter-Pattern • Facade-Pattern
  • Composite-Pattern • Lässt mehrere Instanzen eines Typs nach außen wie eine Instanz aussehen • Implementieren einer neuen Klasse, die die einzelnen Instanzen aufnimmt • Muss die selbe Schnittstelle implementieren wie die entsprechenden Instanzen
  • Composite-Pattern interface Debugger { public function debug($message); } // Implementierungen class DebuggerLog implements Debugger { public function debug($message) { error_log($mssage, 3, 'debug.log'); } } class DebuggerMail implements Debugger { public function debug($message) { mail('schst@php.net', 'Error happened', $message); } }
  • Composite-Pattern class DebuggerComposite implements Debugger { protected $debuggers = array(); public function addDebugger(Debugger $debugger) { $this->debuggers[] = $debugger; } public function debug($message) { foreach ($this->debuggers as $debugger) { $debugger->debug($message); } } } $debuggerComposite = new DebuggerComposite(); $debuggerComposite->addDebugger(new DebuggerLog()); $debuggerComposite->addDebugger(new DebuggerMail());
  • Composite-Pattern Das Composite-Pattern fügt mehrere Objekte zu einer Baumstruktur zusammen und ermöglicht es, diese von außen wie ein einzelnes zu verwenden.
  • Composite-Pattern !!"""#$#"%&'()*+,,-../0120.)3)..45 012678.9*.:6;<65.)!!9..33='&.33 DebuggerComposite kann Debugger-Schnittstelle mit beliebig viele Debugger Methode debug() speichern Component +methodA() +methodB() Konkrete Debugger- Implementierungen Composite ConcreteComponent +addChild(child : Component) +methodA() +removeChild(child : Component) +methodB() +methodA() +methodB() DebuggerComposite-Klasse debug()-Methode delegiert Aufruf an die anderen Debugger s Composite-Patterns Abbildung 5-3: UML-Diagramm de Weitere Anwendungen e Anwendung des haben Sie bereits eine sehr beliebt Mit der Debugging-Funktionalität e ähnliche etet das PEAR-Paket Log , das ein 2 Kompositum-Patterns kenn engelernt. So bi si- llt, auch eine Klasse, die als Kompo
  • Adapter-Pattern • Das Adapter-Pattern passt die Schnittstelle eines Objekts an die vom Client erwartete Schnittstelle. • Es erleichtert die Nutzung von Fremdcode in eigenen Systemen. • Das Adapter-Pattern arbeitet ähnlich wie ein Adapter für Steckdosen.
  • Adapter-Pattern class Automobile { const DIRECTION_FORWARD = 0; const DIRECTTION_BACKWARD = 1; ... public function drive($direction, $miles) { if ($this->ignited !== true) { throw new AutomobileException('Zündung ist nicht an.'); $this->milesDriven = $this->milesDriven + $miles; } } ... }
  • Adapter-Pattern class AutomobileAdapter implements Vehicle { protected $automobile; public function __construct(Automobile $automobile) { $this->automobile = $automobile; } ... public function moveForward($miles) { try { $this->automobile->drive(Automobile::DIRECTION_FORWARD, $miles); return true; } catch (AutomobileException $e) { return false; } }
  • Adapter-Pattern Das Adapter-Muster passt die Schnittstelle einer Klasse an die vom Client erwartete Schnittstelle an. Es ermöglicht die Zusammenarbeit von Klassen, die eigentlich aufgrund inkompatibler Schnittstellen nicht zusammenarbeiten können.
  • Sie die Anf von Fehlern. 5. Beachten Sie Unterschiede beim Signalisieren prungsobjekt zu ion das Adapter-Objekt, um das Urs 6. Verwenden Sie in Ihrer Applikat ummanteln. Adapter-Pattern Wenn Sie diese einfachen Schritte Ab befolgen, adaptieren Sie leicht die verschiedensten bildung 5-4 zeigt Ihnen noch einmal die am Adap- Schnittstellen in Ihrer Applikation. oblem der Interfaces und wie das Pattern auf das Pr ter-Pattern beteiligten Klassen und wandt wurde. abweichenden Schn ittstelle der Automobile-Klasse ange Klassen, die das Vehicle- Interface nutzen, z.B. Vehicle-Interface RentalCompany Client «interface» Target +methodA() Automobile-Klasse Adaptee Adapter +methodB() +methodA() AutomobileAdapter Adapter ruft die entsprechenden Methoden auf dem Automobile- Objekt auf s Ad apter-Patterns Abbildung 5-4: UML-Diagramm de
  • Verhaltensmuster • Verhaltensmuster beschreiben die Interaktion zwischen Objekten. • Zu den Verhaltensmuster gehöhren unter anderem • Subject/Observer-Pattern • Template-Method-Pattern • Command-Pattern • Iterator-Pattern
  • Template-Method-Pattern • Definiert die Schritte eines Algorithmus in einer Methode • Implementierung der einzelnen Schritte bleibt Unterklassen vorbehalten • Gemeinsames Verhalten muss nur einmal implementiert werden: Änderungen am Algorithmus nur an einer Stelle notwendig • Neue Unterklassen müssen nur die konkreten Schritte implementieren
  • Template-Method-Pattern abstract class AbstractCar implements Vehicle { ... final public function inspect() { print "Führe Inspektion durch"; $this->replaceSparkPlugs(); $this->checkTires(); if ($this->isOilLevelLow()) { $this->refillOil(); } } abstract protected function replaceSparkPlugs(); abstract protected function checkTires(); abstract protected function isOilLevelLow(); protected function refillOil() { print "Fülle ". (300 - $this->oilLevel) . "ml Öl nach.n"; $this->oilLevel = 300; } }
  • Template-Method-Pattern class Car extends AbstractCar { protected function replaceSparkPlugs() { print "Ersetze Zündkerzen durch Modell AF34.n"; } protected function checkTires() { print "Überprüfe Reifendruck, muss 2,0 bar sein.n"; } protected function isOilLevelLow() { if ($this->oilLevel < 200) { return true; } return false; } }
  • Template-Method-Pattern Das Template-Method-Pattern definiert die Schritte eines Algorithmus in einer Methode und überlässt die Implementierung der einzelnen Schritte den Unterklassen. Diese können somit Teile des Algorithmus modifizieren, ohne dessen Struktur zu verändern.
  • Template-Method-Pattern !!"""#$#"%&'()*+,,-../0120.)%)..34 012567.8*.95:;54.)!!8..<<='&.<< AbstractCar-Klasse AbstractClass +templateMethod() #primitiveOperation() inspect()-Methode, ruft die abstrakten Methoden auf, die in Unterklassen implementiert werden Car- und Convertible-Klassen ConcreteClass Implementieren checkTires #primitiveOperation() replaceSparkPlugs etc. e-Method-Patterns Abbildu ng 6-2: UML-Diagramm des Templat faktorieren und es, gemeinsamen Code herauszu Schablonenmethoden ermöglichen n zu müssen. somit gemeinsames Verhalten nur einmal implementiere
  • Command-Pattern • Kapselt einen Auftrag als Objekt. • Aufträge (Objekte) sind parametrisierbar • Aufträge können in einer Queue nacheinander abgearbeitet werden • Aufträge können rückgängig gemacht werden.
  • Command-Pattern interface CarWashCommand { public function execute(Car $car); } class CarSimpleWashCommand implements CarWashCommand { public function execute(Car $car) { echo "Das Auto wird gewaschen"; } } class CarDryingCommand implements CarWashCommand { public function execute(Car $car) { echo "Das Auto wird getrocknet"; } }
  • Command-Pattern class CarWash { protected $programmes = array(); public function addProgramme($name, array $commands) { $this->programmes[$name] = $commands; } public function wash($prog, Car $car) { foreach ($this->programmes[$prog] as $command) { $command->execute($car); } } }
  • Command-Pattern $wash = new CarWash(); $wash->addProgramme('standard', array( new CarSimpleWashCommand(), new CarDryingCommand() )); $wash->addProgramme('komfort', array( new CarSimpleWashCommand(), new CarEngineWashCommand(), new CarDryingCommand(), new CarWaxingCommand() )); $wash->wash('standard', $bmw);
  • Command-Pattern Das Command-Pattern kapselt einen Auftrag als Objekt. Dadurch wird ermöglicht, andere Objekte mit Aufträgen zu parametrisieren, Aufträge in eine Queue zu stellen oder diese rückgängig zu machen.
  • parametrisieren. t, also das Objekt, das die Mit Client ist im aktuell en Beispiel die Waschanlage gemein Warteschlange gestellt Befehle verwendet. Dabei müs sen die Befehle nicht immer in eine denkbar, dass nur des Command-Patterns ist es auch werden. Bei anderen Anwendungen ausgeführt i Eint reten einer bestimmten Bedingung ein Befehl übergeben wird, der be Command-Pattern wird. Es handelt sich trotzdem um ein Command-Pattern, da der Au zeit ausgetauscht werden kann. Ab ftrag in einer Klasse bildung 6-3 zeigt gekapselt wird und somit zur Lauf se miteinander in Verbin- Ihnen die im Command-Pa ttern beteiligten Akteure und wie die dung stehen. CarWash, also CarWashCommand- die Waschanlage Interface «interface» Client Invoker Command +execute() Car-Objekte, die gewaschen werden Receiver ConcreteCommand -state +execute() +action() Konkrete Implementierungen der Wasch-Befehle, z.B. CarMotorWashCommand Command-Patterns Abbildung 6-3: UML-Diagramm des 290 | Kapitel 6: Verhaltensmuster
  • Enterprise Patterns • Kommen aus der Java Welt • Stark geprägt durch Martin Fowler • Meistens komplexer als die Gang-of-Four Patterns • Deswegen ab hier keine Beispiele mehr • Mehr zu Enterprise Patterns in PHP im Buch "PHP Design Patterns" http://www.phpdesignpatterns.de
  • Die Weisheit der Biene Nutze bestehende Lösungen. Abstrahiere Deine konkreten Probleme und wende Design Patterns als Vorlage für Deine Lösung an.
  • Die Bulldogge
  • Die Bulldogge Perfektionismus wird P-A-R-A-L-Y-S-E buchstabiert
  • You Ain‘t Gonna Need It (YAGNI) „Always implement things when you actually need them, never when you just foresee that you need them“ Ronald E Jeffries
  • You Ain‘t Gonna Need It (YAGNI) • Anforderungen sind in der Software-Entwicklung notorisch ungenau oder wechselnd • Ungenaue Anforderungen werden oft durch möglichst flexible und funktionsfähige Software kompensiert • Es werden Features entwickelt die keine Anwendung finden • Dinge die niemand braucht, haben keinen Wert.
  • Do the simplest thing that could possibly work. • YAGNI kann als Ergänzung des XP-Prinzips "Do the simplest thing that could possibly work." verstanden werden • Wann ist ein Design am einfachsten? • Es verkörpert die Absicht des Entwicklers und besteht alle Tests. • Es enthält kein Duplizierungen. • Es enthält das Minimum an Klassen und Methoden
  • Emergenz „Emergenz ist die spontane Herausbildung von komplexen Systemen und Strukturen durch eine Vielzahl von relativ einfachen Interaktionen.“ Wikipedia
  • Saubere Software durch emergentes Design • Alle Tests bestehen • Software muss in erster Linie den gewollten Zweck erfüllen. • Software, die nicht testbar ist, kann nicht verifiziert werden. • Klassen die dem Single Responsibility Prinzip folgen sind leichter zu testen. • Je mehr Tests wir schreiben, desto mehr bemühen wir uns Code zu schreiben, der einfacher zu testen ist.
  • Saubere Software durch emergentes Design • Alle Tests bestehen • Eine starke Kopplung erschwert das Schreiben von Tests • Je mehr Tests wir schreiben, desto mehr bemühen wir uns, die Kopplung zu minimieren
  • Saubere Software durch emergentes Design • Refactoring nach dem Bestehen eines Tests • Duplizierten Code eliminieren • Ausdrucksstärke des Codes verbessern • Anzahl der Klassen und Methoden minimieren • Tests sichern das bisherige Ergebnis ab
  • Vorsicht: Perfekt ist der Feind von "Gut genug" • Entwickler tendieren dazu Lösungen danach zu analysieren wie elegant und optimal sie für die Problemstellung sind. • Software Entwicklung ist kein Schönheitswettbewerb • Der Code ist klar, ausdrucksstark, gut dokumentiert und getestet. Geht es noch besser? • Klar. Aber es er ist gut genug. • Verschwende keine Zeit auf der Suche nach dem perfekten Design
  • Permature Optimization „Premature optimization is the root of all evil“ Donald Knuth
  • Permature Optimization • Premature Optimization beschreibt die Situation in der Design Entscheidungen aufgrund von Performance-Optimierungen getroffen werden • Solche Optimierungen resultieren oft in unleserlicherem Code • M. A. Jackson über Optimierung • Dont't do it. • (For experts only) - Don't do it yet
  • Premature Optimization • Was wenn Performance-Optimierung unumgänglich ist? • Anwendung & Design entwickeln • Profiler / Benchmarks einsetzen • Flaschenhälse identifizieren • Ein einfaches und elegantes Design ist oft leichter zu optimieren
  • Die Weisheit der Bulldogge Mit kleinen Schritten zum großen Ziel. Mach es nicht perfekt, mach es gut genug. Je länger Entscheidungen aufgeschoben werden, desto mehr Wissen hat man darüber
  • Der Regenwurm
  • Der Regenwurm Vermeide Accidential Complexity.
  • Vermeide Accidential Complexity „Simplify essential complexity; diminish accidental complexity“ Neal Ford
  • Essential Complexity • "Essential Complexity" ist die Komplexität, die dem eigentlichen Problem innewohnt • Am besten mit "notwendige Komplexität" übersetzt • Die Komplexität ist durch das Business getrieben und kann nicht ignoriert werden
  • Accidential Complexity • "Accidential Complexity" ist die Komplexität. die durch die technische Lösung hinzugefügt wird, mit der Absicht, die notwendige Komplexität zu kontrollieren • Häufiges Problem von eingekauften Lösungen und generischen Frameworks • Entwickler werden von Komplexität angezogen • Entwickler wollen komplexe Probleme lösen und lösen damit oft Probleme, die die Lösung erst eingeführt hat
  • Accidential Complexity
  • Accidential Complexity • JPA • Rules Engine Stateful Webservices Java Persistence API Aspect Oriented Programming • Aspect Oriented Programming MultiRules Engine Module Build • komplexes Build System • Stateful Webservices
  • Vermeide Accidential Complexity • Verwende Frameworks, die aus produktivem Code entstanden sind. • Extrahiere Frameworks aus bestehendem Code. • Prüfe, wie viel Prozent des Codes das tatsächlich vorhandene Problem adressiert • Triff keine Entscheidungen aus dem Elfenbeinturm.
  • Die Weisheit des Regenwurms Fokussiere Dich auf das Problem. Implementiere Lösungen, die Probleme der Domäne lösen, ohne unnötige Komplexität einzuführen.
  • Der Kugelfisch
  • Der Kugelfisch Teste, teste, teste.
  • Unit Tests „Im Unit Test werden kleinere Programmteile in Isolation von anderen Programmteilen getestet.“ Frank Westphal
  • Unit Tests • Testen eine einzelne Codeeinheit isoliert. • Die Granularität der Codeeinheit kann von Methoden über Klassen bis hin zu Komponenten reichen. • Unit Test-Frameworks für PHP • PHPUnit - JUnit Portierung für PHP von Sebastian Bergmann • SimpleTest - von Marcus Baker
  • Unit Tests require_once 'RentalCompany.php'; class RentalCompanyTest extends PHPUnit_Framework_TestCase { protected $rentalCompany; protected function setUp() { $this->rentalCompany = new RentalCompany(); } public function testAddToFleet() { $this->rentalCompany->addToFleet(new Car('VW', 'silber')); $carCount = $this->rentalCompany->countCarsInFleet(); $this->assertEquals(1, $carCount); } }
  • Unit Tests $ phpunit RentalCompanyTest PHPUnit 3.4.2 by Sebastian Bergmann. . Time: 0 seconds OK (1 test, 1 assertion)
  • Integrationstests „There is a vast gulf between the process mappers who model business systems pictorially, and the programmers who grind out the C++ or Java or .Net services that support those business systems. Between the two camps lies a fertile land of opportunity. It's time to jointly explore it.“ Ward Cunningham
  • FIT - Framework for Integrated Tests • Framework für Integrations- und Akzeptanz-Tests • Der Kunde schreibt die Testfälle in HTML, Word oder Excel • Bezieht den Kunden in den Entwicklungsprozess ein und fördert agiles Vorgehen • Mittlerweile für sehr viele Sprachen verfügbar, für PHP innerhalb von PEAR
  • Funktionsweise • Kunde erstellt eine Tabelle mit Eingabe-Parametern und erwarteten Rückgabe-Werten • FIT parst die HTML-Tabelle und interpretiert diese als Testfälle • FIT reicht die Eingabeparameter an den Testcode (Fixture) weiter • Der Testcode führt den zu testenden Code aus • FIT holt die das Ergebnis aus dem Testcode • FIT markiert Abweichungen in der HTML-Tabelle
  • Funktionsweise
  • Webtests mit Selenium • Dem Kunden sind Unit-Tests egal, wenn die Website nicht funktioniert • Selenium prüft die Anwendung auf der Ebene, die der Kunde sieht • Steuert den Browser fern und prüft gegen das erwartete Verhalten • Funktioniert in allen großen Browsern, auch im IE6 • Tests können über Firefox-Extension aufgezeichnet werden • Selenium RC ermöglicht Fernsteuerung aus PHPUnit Tests
  • Selenium in Bildern
  • Selenium in Bildern
  • Continuous Integration • Beschreibt den Prozess des regelmäßigen, vollständigen Builds und Testens einer Anwendung • Vorteile durch den Einsatz von CI • Integrations-Probleme werden frühzeitig entdeckt • Fehler werden nicht verschleppt • Code Qualität ist über den gesamten Entwicklungsprozess sichtbar
  • Continuous Integration SVN Repository CI Server
  • phpUnderControl
  • Mehr Tools
  • Die Weisheit des Kugelfischs Better safe than sorry. Schaffe dir Sicherheitsnetze durch automatisierte Tests auf verschiedenen Ebenen deiner Applikation. Integriere regelmäßig und stelle Fehler frühzeitig fest.
  • Der Waschbär
  • Der Waschbär Halte deinen Code sauber.
  • Coding Standards • Legen fest, wie lang eine Zeile sein darf, wie eingerückt wird, wo geklammert wird, wo Leerzeichen stehen, wann Großbuchstaben oder Kleinbuchstaben verwendet werden, wie eine Funktionsdefinition aussehen soll, wie eine Klassendefinition aussehen soll, wie eine Methodendefinition aussehen soll, wie und wo Includes verwendet werden sollen, und, und, und, … • Haben religiöse Sprengkraft • Sorgen dafür, dass der Code für alle Entwickler lesbar bleibt • Entwickler haben dadurch Zeit, sich auf das Wesentliche zu fokussieren
  • Coding Standards in PHP • PHP_CodeSniffer kann Code gegen verschiedene Regeln prüfen • Liefert bereits Regelsets mit, ist jedoch erweiterbar (hört auf die Schildkröte) $ phpcs --standard=pear badClass.php FILE: /var/www/phpcodesniffer/badClass.php -------------------------------------------------------------------------------- FOUND 5 ERROR(S) AND 0 WARNING(S) AFFECTING 3 LINE(S) -------------------------------------------------------------------------------- 2 | ERROR | Missing file doc comment 3 | ERROR | Class name must begin with a capital letter 5 | ERROR | Line indented incorrectly; expected at least 4 spaces, found 1 5 | ERROR | Spaces must be used to indent lines; tabs are not allowed 5 | ERROR | Class constants must be uppercase; expected MYCONSTANT but found | | MyConstant --------------------------------------------------------------------------------
  • Verwende Name die ihre Absicht aufdecken • Namen von Variablen, Funktionen oder Klassen, sollten folgende Fragen beantworten: • Warum existiert die Variable (Funktion oder Klasse)? • Was macht sie? • Wie wird sie verwendet? • $d = 1; // elapsed time in days $elapsedTimeInDays = 1;
  • Benennung • Verwende aussprechbare Namen • Verwende ein Wort pro Konzept (z.B. fetch, retrieve oder get) • Vermeide "Nerd Names" in Klassennamen • ...Helper, ...Manager oder ...Util • http://www.classnamer.com/
  • Benennung
  • Benennung
  • Benennung
  • Kommentare • Gute Kommentare • Schlechte Kommentare • @todo-Kommentare • Redundante Kommentare • Informative Kommentare • Postionsmarkierungen • PHPDocs in öffentlichen APIs • Auskommentierter Code Kommentare sind keine Ausrede für schlechten Code.
  • DRY - Don‘t Repeat Yourself „Every piece of knowlege must have a single, unambiguous, authoritative representation within a system“ Andrew Hunt and Dave Thomas
  • DRY - Don‘t Repeat Yourself • Nichts ist einfacher als Copy & Paste • „Nummer Eins der Gestanksparade“ in Refactoring von Martin Fowler • Jede Doppelung von Code leistet Inkonsistenzen und Fehlern Vorschub.
  • Fehlerhandling • Verwende Exceptions • Reichere deine Exceptions mit sinnvollen Informationen an. • Definieren Exception-Klassen nach den Bedürfnissen der aufrufenden Systeme. • Verwende Exceptions nicht als billige Alternative für goto. • Gib niemals null zurück.
  • Die Pfadfinder-Regel „Leave the campground cleaner than you found it“ Robert C. Martin (Clean Code)
  • Die Pfadfinder-Regel • „Don‘t live with Broken Windows“ • Fixe schlechte Designs, falsche Entscheidungen und schlechten Code sobald du ihn siehst • Es muss nichts großes sein • Ändere den Namen einer Variable in einen besseren Breche eine Funktion auf, die zu groß ist Eliminiere ein kleine Duplizierung • Software muss dauerhaft sauber gehalten werden
  • Die Weisheit des Waschbärs Dreckiger Code führt zu dreckigem Design. Lass auch bei Detail-Fragen die gleiche Sorgfalt walten wie bei großen Design-Entscheidungen.
  • Die Ente
  • Die Ente Das Ende.
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Die Leseratte
  • Fragen?
  • Fragen? Vielen Dank für die Aufmerksamkeit.
  • Fragen? Vielen Dank für die Aufmerksamkeit. Bildquellen © iStockphoto.com Kontakt holger.rueprich@1und1.de stephan.schmidt@1und1.de