Die Kunst des Software-Design
oder was Software-Entwickler von der Tierwelt lernen können

PHP World Kongress 2009
Holger ...
Holger Rüprich

• Head of Sales Processes Consumer
  bei der 1&1 Internet AG


• Clean Code Enthusiast


• Gast-Dozent an ...
Stephan Schmidt

• Head of Web Sales Development
  bei der 1&1 Internet AG


• Design Patterns Enthusiast


• Autor von PH...
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, ...
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 Aut...
... zur programmierten Welt

• Klassen übertragen Dinge aus der realen Welt in die programmierte Welt

 class Car {

     ...
Kapsle den Zugriff auf Daten

 Kapsle den Zugriff auf Daten immer innerhalb
 einer Klasse und biete Methoden an, um diese
...
Kapsle den Zugriff auf Daten

 Kapsle den Zugriff auf Daten immer innerhalb
 einer Klasse und biete Methoden an, um diese
...
Bobs Kunden


              class Customer {
                protected $id;
                protected $name;

            ...
Bobs Firma



 class RentalCompany {

     protected $fleet = array();

     public function addToFleet($id, Car $car) {
 ...
Bobs Geschäft

• Klassen übertragen nicht nur physikalische Dinge, sondern auch Abläufe

  class RentalAction {
      ... ...
Bobs Geschäft

• Klassen übertragen nicht nur physikalische Dinge, sondern auch Abläufe

  class RentalAction {
    ...

 ...
Kapsle auch Algorithmen



 Kapsle nicht nur Daten sondern auch Algorithmen
 in den Methoden deiner Klassen, um komplexe
 ...
Bobs Firma

      class RentalCompany {

          ...

          public function rentCar(Car $car, Customer $customer) {
...
Bobs Firma

       class RentalCompany {

           ...

           public function isCarAvailable(Car $car) {
          ...
Bobs Firma

      class RentalCompany {

          ...

          public function returnCar(Car $car) {
            foreac...
Die Weisheit des Eichhörnchens



                 Schütze deine Daten.
Verberge Implementierungsdetails und unterbinde de...
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. Mart...
Bob will wissen was los ist
 class RentalCompany {
   public function addToFleet($id, Vehicle $vehicle) {
     $this->flee...
Bob will wissen was los ist
 class RentalCompany {
   public function addToFleet($id, Vehicle $vehicle) {
     $this->flee...
Debugging im Produktivbetrieb
class RentalCompany {
  public function addToFleet($id, Vehicle $vehicle) {
    $this->fleet...
Debugging im Produktivbetrieb
class RentalCompany {
  public function addToFleet($id, Vehicle $vehicle) {
    $this->fleet...
Wiederverwendbarkeit statt Copy-and-Paste

class RentalCompany {
  public function addToFleet($id, Vehicle $vehicle) {
   ...
Wiederverwendbarkeit statt Copy-and-Paste

class RentalCompany {
  ...

    protected function debug($message) {
      swi...
Wiederverwendbarkeit statt Copy-and-Paste

class RentalCompany {
  ...

        Weitere Debugging-Ziele, wie E-Mails oder ...
Atomare Probleme lösen

abstract class RentalCompany {
  ... Eigenschaften und Methoden der Klasse ...

    abstract prote...
Atomare Probleme lösen

switch (DEBUG_MODE) {
  case 'echo':
    $company = new EchoingRentalCompany();
    break;
  case ...
Atomare Probleme lösen

switch (DEBUG_MODE) {
  case 'echo':
    $company = new EchoingRentalCompany();
    break;
  case ...
Komposition statt Vererbung

interface Debugger {
  public function debug($message);
}

class DebuggerEcho {
  public func...
Komposition statt Vererbung

class RentalCompany {
  ... Eigenschaften der Klasse ...

    protected $debugger;

    publi...
Die Weisheit des Krokodils



                 Teile und herrsche.
Jedes Modul soll genau eine Verantwortung übernehmen, u...
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 clo...
Komposition statt Vererbung

class RentalCompany {
  ... Eigenschaften der Klasse ...

    protected $debugger;

    publi...
Komposition statt Vererbung

class RentalCompany {
  ... Eigenschaften der Klasse ...

    protected $debugger;

    publi...
Einsatz von Interfaces

 class RentalCompany {
   ... Eigenschaften der Klasse ...

     public function __construct(Debug...
Die Weisheit der Schildkröte



                Schütze deinen Code.
Programmiere immer gegen Schnittstellen, nie gegen ei...
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“


     ...
Dependency Injection

• Objekte erstellen abhängige Objekte nicht selbst


• Abhängige Objekte werden von außen über den K...
Dependency Injection
 $debugger = new DebuggerEcho();
 $company = new RentalCompany($debugger);   Constructor Injection
 $...
Inversion-of-Control-Container

• In der Java-Welt schon weit verbreitet


   • Spring, Google Guice, Tapestry IoC, ...


...
Stubbles IoC Container

• Portierung von Google Guice (Java)


• Entwickelt als Teil des Stubble Frameworks


• Kann auch ...
Rufen Sie Bob nicht an, Bob ruft sie an.

 class RentalCompany {
   ... Eigenschaften der Klasse ...

     /**
       * @I...
Interfaces binden

• Typen werden durch Binder an konkrete Implementierungen gebunden:

 $binder = new stubBinder();
 $bin...
Fortgeschrittene Techniken

• Verwenden einer Standardimplementierung
 /**
  * @ImplementedBy(DateTimeLogger.class)
  */
 ...
Die Weisheit des Erpel



          Verwende ein DI Framework.
Erleichtere dir das Verwalten von komplexen Objektstrukture...
Die Biene
Die Biene

Nutze Design Patterns.
Konkretes Problem




 „Ich möchte Debug-Meldungen auf verschiedene
 Arten verarbeiten und diese auswechseln können,
 ohne...
Abstraktes Problem


 „Ich möchte eine Aufgabe mit verschiedenen
 Algorithmen lösen können. Jede der Lösungen soll
 gekaps...
Konkret vs Abstrakt


          Abstrakt            Konkret

                       Verarbeiten von Debug-
          Aufga...
Konkret vs Abstrakt


          Abstrakt            Konkret

                          Persistieren von
          Aufgabe
...
Bobs erstes Design Pattern




          Strategy-Pattern
Design Patterns

• Lösungsmuster für häufig auftretende Entwurfsaufgaben in der Software-
  Entwicklung


• Keine Code-Bibl...
Erzeugungsmuster

• Erzeugungsmuster werden verwendet, um Objekte zu konstruieren.


• Zu den Erzeugungsmustern gehöhren u...
Factory-Method-Pattern

• Definiert eine Schnittstelle zur Erzeugung von Objekten


• Verlagert die eigentliche Instanziier...
Factory-Method-Pattern

 abstract class AbstractManufacturer {

     protected $name;

     public function __construct($n...
Factory-Method-Pattern



 class CarManufacturer extends AbstractManufacturer {

     public function manufactureVehicle()...
Factory-Method-Pattern



 Das Factory-Method-Pattern definiert eine
 Schnittstelle zur Erzeugung von Objekten. Es
 verlag...
der abstrak
                                                                           lichen Objekte zu
     4. Verwenden...
Prototype-Pattern

• Das Prototype-Pattern erzeugt Objekte durch das Kopieren eines
  prototypischen Exemplars


• Es ermö...
Prototype-Pattern

 class SpecialEditionManufacturer {

     protected $prototypes = array();

     public function addSpe...
Prototype-Pattern

 class Car implements Vehicle { ... }
 class Convertible implements Vehicle { ... }

 $manufacturer = n...
Prototype-Pattern




 Das Prototyp-Muster bestimmt die Arten der zu
 erzeugenden Objekte durch die Verwendung eines
 prot...
Prototype-Pattern
!!"""#$#"%&'()*+,,-../0120.)!!..3
                                    4012567.8*.95:;54.)!!8..<<='&.<<

...
Strukturmuster

• Strukturmuster befassen sich mit der Komposition von Objekten


• Zu den Strukturmustern gehöhren unter ...
Composite-Pattern

• Lässt mehrere Instanzen eines Typs nach außen wie eine Instanz aussehen


• Implementieren einer neue...
Composite-Pattern

 interface Debugger {
   public function debug($message);
 }

 // Implementierungen
 class DebuggerLog ...
Composite-Pattern

 class DebuggerComposite implements Debugger {

     protected $debuggers = array();

     public funct...
Composite-Pattern




 Das Composite-Pattern fügt mehrere Objekte zu
 einer Baumstruktur zusammen und ermöglicht es,
 dies...
Composite-Pattern
  !!"""#$#"%&'()*+,,-../0120.)3)..45
                                    012678.9*.:6;<65.)!!9..33='&.33...
Adapter-Pattern

• Das Adapter-Pattern passt die Schnittstelle eines Objekts an die vom Client
  erwartete Schnittstelle.
...
Adapter-Pattern

 class Automobile {

     const DIRECTION_FORWARD = 0;
     const DIRECTTION_BACKWARD = 1;

     ...

   ...
Adapter-Pattern

 class AutomobileAdapter implements Vehicle {

     protected $automobile;

     public function __constr...
Adapter-Pattern



 Das Adapter-Muster passt die Schnittstelle einer
 Klasse an die vom Client erwartete Schnittstelle
 an...
Sie die Anf
                                                        von Fehlern.
    5. Beachten  Sie Unterschiede beim Si...
Verhaltensmuster

• Verhaltensmuster beschreiben die Interaktion zwischen Objekten.


• Zu den Verhaltensmuster gehöhren u...
Template-Method-Pattern

• Definiert die Schritte eines Algorithmus in einer Methode


• Implementierung der einzelnen Schr...
Template-Method-Pattern

 abstract class AbstractCar implements Vehicle {
   ...

     final public function inspect() {
 ...
Template-Method-Pattern

 class Car extends AbstractCar {

     protected function replaceSparkPlugs() {
       print "Ers...
Template-Method-Pattern



 Das Template-Method-Pattern definiert die
 Schritte eines Algorithmus in einer Methode und
 üb...
Template-Method-Pattern
 !!"""#$#"%&'()*+,,-../0120.)%)..34
                                   012567.8*.95:;54.)!!8..<<='...
Command-Pattern

• Kapselt einen Auftrag als Objekt.


• Aufträge (Objekte) sind parametrisierbar


• Aufträge können in e...
Command-Pattern

 interface CarWashCommand {
   public function execute(Car $car);
 }

 class CarSimpleWashCommand impleme...
Command-Pattern

 class CarWash {

     protected $programmes = array();

     public function addProgramme($name, array $...
Command-Pattern

 $wash = new CarWash();

 $wash->addProgramme('standard', array(
   new CarSimpleWashCommand(),
   new Ca...
Command-Pattern



Das Command-Pattern kapselt einen Auftrag als
Objekt. Dadurch wird ermöglicht, andere Objekte
mit Auftr...
parametrisieren.
                                                                    t, also das Objekt, das die
     Mit ...
Enterprise Patterns

• Kommen aus der Java Welt


• Stark geprägt durch Martin Fowler


• Meistens komplexer als die Gang-...
Die Weisheit der Biene



          Nutze bestehende Lösungen.
Abstrahiere Deine konkreten Probleme und wende Design Patte...
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 th...
You Ain‘t Gonna Need It (YAGNI)

• Anforderungen sind in der Software-Entwicklung notorisch ungenau oder
  wechselnd


• U...
Do the simplest thing that could possibly work.

• YAGNI kann als Ergänzung des XP-Prinzips "Do the simplest thing that co...
Emergenz




„Emergenz ist die spontane Herausbildung von
komplexen Systemen und Strukturen durch eine
Vielzahl von relati...
Saubere Software durch emergentes Design

• Alle Tests bestehen


  • Software muss in erster Linie den gewollten Zweck er...
Saubere Software durch emergentes Design

• Alle Tests bestehen


  • Eine starke Kopplung erschwert das Schreiben von Tes...
Saubere Software durch emergentes Design

• Refactoring nach dem Bestehen eines Tests


  • Duplizierten Code eliminieren
...
Vorsicht: Perfekt ist der Feind von "Gut genug"

• Entwickler tendieren dazu Lösungen danach zu analysieren wie elegant un...
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 Perf...
Premature Optimization

• Was wenn Performance-Optimierung unumgänglich ist?


   • Anwendung & Design entwickeln


   • P...
Die Weisheit der Bulldogge



   Mit kleinen Schritten zum großen Ziel.
Mach es nicht perfekt, mach es gut genug.
Je länge...
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...
Accidential Complexity

• "Accidential Complexity" ist die Komplexität. die durch die technische Lösung
  hinzugefügt wird...
Accidential Complexity
Accidential Complexity

• JPA


• Rules Engine


 Stateful Webservices
 Java Persistence API
Aspect Oriented Programming
•...
Vermeide Accidential Complexity

• Verwende Frameworks, die aus
  produktivem Code entstanden sind.


• Extrahiere Framewo...
Die Weisheit des Regenwurms



       Fokussiere Dich auf das Problem.
Implementiere Lösungen, die Probleme der Domäne lös...
Der Kugelfisch
Der Kugelfisch

Teste, teste, teste.
Unit Tests




 „Im Unit Test werden kleinere Programmteile in
 Isolation von anderen Programmteilen getestet.“
 Frank Wes...
Unit Tests

• Testen eine einzelne Codeeinheit isoliert.


   • Die Granularität der Codeeinheit kann von Methoden über Kl...
Unit Tests

 require_once 'RentalCompany.php';

 class RentalCompanyTest extends PHPUnit_Framework_TestCase {

     protec...
Unit Tests



 $ phpunit RentalCompanyTest
 PHPUnit 3.4.2 by Sebastian Bergmann.

 .

 Time: 0 seconds

 OK (1 test, 1 ass...
Integrationstests


 „There is a vast gulf between the process mappers
 who model business systems pictorially, and the
 p...
FIT - Framework for Integrated Tests

• Framework für Integrations- und Akzeptanz-Tests


• Der Kunde schreibt die Testfäl...
Funktionsweise

• Kunde erstellt eine Tabelle mit Eingabe-Parametern und erwarteten
  Rückgabe-Werten


• FIT parst die HT...
Funktionsweise
Webtests mit Selenium

• Dem Kunden sind Unit-Tests egal, wenn die Website nicht funktioniert


• Selenium prüft die Anwen...
Selenium in Bildern
Selenium in Bildern
Continuous Integration

• Beschreibt den Prozess des regelmäßigen, vollständigen Builds und Testens
  einer Anwendung


• ...
Continuous Integration

      SVN Repository     CI Server
phpUnderControl
Mehr Tools
Die Weisheit des Kugelfischs



                Better safe than sorry.
Schaffe dir Sicherheitsnetze durch automatisierte T...
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 s...
Coding Standards in PHP

• PHP_CodeSniffer kann Code gegen verschiedene Regeln prüfen


• Liefert bereits Regelsets mit, i...
Verwende Name die ihre Absicht aufdecken

• Namen von Variablen, Funktionen oder Klassen, sollten folgende Fragen
  beantw...
Benennung

• Verwende aussprechbare Namen


• Verwende ein Wort pro Konzept (z.B. fetch, retrieve oder get)


• Vermeide "...
Benennung
Benennung
Benennung
Kommentare

• Gute Kommentare                    • Schlechte Kommentare


  • @todo-Kommentare                    • Redund...
DRY - Don‘t Repeat Yourself




 „Every piece of knowlege must have a single,
 unambiguous, authoritative representation
 ...
DRY - Don‘t Repeat Yourself

• Nichts ist einfacher als Copy & Paste


• „Nummer Eins der Gestanksparade“ in Refactoring v...
Fehlerhandling

• Verwende Exceptions


• Reichere deine Exceptions mit sinnvollen Informationen an.


• Definieren Excepti...
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 schlechte...
Die Weisheit des Waschbärs



Dreckiger Code führt zu dreckigem Design.
Lass auch bei Detail-Fragen die gleiche Sorgfalt w...
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.sc...
Die Kunst Des Software Design
Upcoming SlideShare
Loading in …5
×

Die Kunst Des Software Design

8,217 views

Published on

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

Published in: Technology
1 Comment
6 Likes
Statistics
Notes
  • Hallo!
    mit welchem Programm öffne ich nun die heruntergeladene Datei 'die-kunst-des-software-design-091125172000-phpapp02.key'?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
8,217
On SlideShare
0
From Embeds
0
Number of Embeds
129
Actions
Shares
0
Downloads
88
Comments
1
Likes
6
Embeds 0
No embeds

No notes for slide
  • Wissen - Ich muss meine Technologie und die Dom&amp;#xE4;ne kennen
    &amp;#xDC;bung - Der erste Entwurf geht schief (&amp;#xDC;berflieger: 1000 Stunden, 1000 Fotos f&amp;#xFC;r die Tonne)
    Wahrnehmung - Sehen wo die Probleme liegen, Schnelles Verstehen
    Vorstellung - Software ist abstrakt
    Intuition - Software-Entwurf ist kein striktes logisches Vorgehen
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Stabil - Unser Leben basiert auf Software, wenn unserer Software versagt...
    Sicher - Online Banking, Sensible Daten im Netz
    Flexibel - &quot;640kb reichen f&amp;#xFC;r jeden&quot;
    Performance - Twitter Ausfall
  • Hamstert N&amp;#xFC;sse, l&amp;#xE4;sst keinen dran...
  • Seite 120 -129
    5min -&gt; Holger
  • Seite 129 - 130
    Weitere Themen
    5min -&gt; Stephan
  • Seite 137 - 153
    Wikipedia / Internet
    10min -&gt; Holger
  • YAGNI
    Premature Optimization
    Emergenz
    Negativ Beispiele
    10min -&gt; Holger
  • http://www.xprogramming.com/Practices/PracNotNeed.html

    Spekulatives Programmieren
  • Fallbeispiele
    5-10min Stephan
  • http://www.xprogramming.com/Practices/PracNotNeed.html

    Spekulatives Programmieren
  • Holger
  • Cruise Control haupts&amp;#xE4;chlich f&amp;#xFC;r Java bekannt
    phpUnderControl Erweiterung f&amp;#xFC;r PHP
    Funktionsweise
    - Konfiguration per ant (build.xml)
    - Checkout Target -&gt; Neuste SVN Version holen
    - PHPDoc Target -&gt; Dokumentation generieren
    - CodeSniffer Target -&gt; Coding Guidelines validieren
    - PHPUnit Target -&gt; Unit Tests durchf&amp;#xFC;hren
  • Hudson - Haupts&amp;#xE4;chlich f&amp;#xFC;r Java l&amp;#xE4;sst sich aber auch f&amp;#xFC;r PHP einsetzen
    Xinc - in PHP f&amp;#xFC;r PHP entwickelt
    Bamboo - kostenpflichtig
  • Die Kunst Des Software Design

    1. 1. 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
    2. 2. 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
    3. 3. 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
    4. 4. Software Design „Software Design is a process of problem solving and planning for a software solution.“ Wikipedia
    5. 5. Kunst „Das Wort Kunst bezeichnet im weitesten Sinne jede entwickelte Tätigkeit, die auf Wissen, Übung, Wahrnehmung, Vorstellung und Intuition gegründet ist.“ Wikipedia
    6. 6. Ziele von Software Design
    7. 7. Ziele von Software Design Software soll stabil sein.
    8. 8. Ziele von Software Design
    9. 9. Ziele von Software Design Software soll sicher sein.
    10. 10. Ziele von Software Design
    11. 11. Ziele von Software Design Software soll flexibel sein.
    12. 12. Ziele von Software Design
    13. 13. Ziele von Software Design Software soll performant sein.
    14. 14. Ziele von Software Design
    15. 15. Das Eichhörnchen
    16. 16. Das Eichhörnchen Kapsle Daten und Algorithmen.
    17. 17. Von der realen Welt ... • Bob hat eine Autovermietung • Er muss Autos einkaufen • Er vermietet unterschiedliche Modelle • Er vermietet Autos zu verschiedenen Preisen
    18. 18. ... 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() {} }
    19. 19. 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; } }
    20. 20. 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; } }
    21. 21. 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; } }
    22. 22. 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) {} }
    23. 23. 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 ... }
    24. 24. 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; } }
    25. 25. Kapsle auch Algorithmen Kapsle nicht nur Daten sondern auch Algorithmen in den Methoden deiner Klassen, um komplexe Operationen zentral an einer Stelle zu implementieren.
    26. 26. 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; } }
    27. 27. 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; } }
    28. 28. 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; } }
    29. 29. 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.
    30. 30. Das Krokodil
    31. 31. Das Krokodil Achte das Single-Reponsibility-Prinzip.
    32. 32. Das Single-Responsibility-Prinzip „There should never be more than one reason for a class to change“ Robert C. Martin
    33. 33. 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
    34. 34. 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
    35. 35. 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; }
    36. 36. 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; }
    37. 37. 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; } ... }
    38. 38. 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; } } }
    39. 39. 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; } } }
    40. 40. 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'); } }
    41. 41. 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);
    42. 42. 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);
    43. 43. 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'); } }
    44. 44. 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); } }
    45. 45. Die Weisheit des Krokodils Teile und herrsche. Jedes Modul soll genau eine Verantwortung übernehmen, und jede Verantwortung soll genau einem Modul zugeordnet werden.
    46. 46. Die Schildkröte
    47. 47. Die Schildkröte Achte das Open-Closed-Prinzip.
    48. 48. Das Open-Closed-Prinzip „Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.“ Bertrand Meyer
    49. 49. 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); } }
    50. 50. 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); } }
    51. 51. 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);
    52. 52. 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.
    53. 53. Der Erpel
    54. 54. Der Erpel Achte das Hollywood-Prinzip.
    55. 55. Das Hollywood Prinzip „Rufen Sie uns nicht an, wir werden Sie anrufen.“ Das Hollywood Prinzip
    56. 56. 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
    57. 57. 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
    58. 58. 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
    59. 59. 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
    60. 60. 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
    61. 61. 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; } ... }
    62. 62. 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');
    63. 63. 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');
    64. 64. Die Weisheit des Erpel Verwende ein DI Framework. Erleichtere dir das Verwalten von komplexen Objektstrukturen durch den Einsatz eines Dependency Injection Frameworks.
    65. 65. Die Biene
    66. 66. Die Biene Nutze Design Patterns.
    67. 67. 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
    68. 68. 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
    69. 69. Konkret vs Abstrakt Abstrakt Konkret Verarbeiten von Debug- Aufgabe Meldungen Ausgeben per print(), Algorithmen Schreiben eines Logfiles Die Klasse Client RentalCompany
    70. 70. Konkret vs Abstrakt Abstrakt Konkret Persistieren von Aufgabe Gästebucheinträgen Speichern in Datenbank, Algorithmen Speichern in XML-Datei Client Die Klasse Guestbook
    71. 71. Bobs erstes Design Pattern Strategy-Pattern
    72. 72. 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
    73. 73. 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
    74. 74. 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
    75. 75. 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(); }
    76. 76. Factory-Method-Pattern class CarManufacturer extends AbstractManufacturer { public function manufactureVehicle() { return new Car($this->name); } } $bmwManufacturer = new CarManufacturer('BMW'); $bmw = $bmwManufacturer->sellVehicle();
    77. 77. 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.
    78. 78. 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
    79. 79. 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
    80. 80. 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]; } }
    81. 81. 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');
    82. 82. 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.
    83. 83. 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
    84. 84. Strukturmuster • Strukturmuster befassen sich mit der Komposition von Objekten • Zu den Strukturmustern gehöhren unter anderem • Composite-Pattern • Proxy-Pattern • Adapter-Pattern • Facade-Pattern
    85. 85. 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
    86. 86. 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); } }
    87. 87. 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());
    88. 88. 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.
    89. 89. 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
    90. 90. 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.
    91. 91. 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; } } ... }
    92. 92. 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; } }
    93. 93. 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.
    94. 94. 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
    95. 95. Verhaltensmuster • Verhaltensmuster beschreiben die Interaktion zwischen Objekten. • Zu den Verhaltensmuster gehöhren unter anderem • Subject/Observer-Pattern • Template-Method-Pattern • Command-Pattern • Iterator-Pattern
    96. 96. 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
    97. 97. 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; } }
    98. 98. 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; } }
    99. 99. 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.
    100. 100. 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
    101. 101. 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.
    102. 102. 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"; } }
    103. 103. 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); } } }
    104. 104. 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);
    105. 105. 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.
    106. 106. 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
    107. 107. 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
    108. 108. Die Weisheit der Biene Nutze bestehende Lösungen. Abstrahiere Deine konkreten Probleme und wende Design Patterns als Vorlage für Deine Lösung an.
    109. 109. Die Bulldogge
    110. 110. Die Bulldogge Perfektionismus wird P-A-R-A-L-Y-S-E buchstabiert
    111. 111. 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
    112. 112. 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.
    113. 113. 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
    114. 114. Emergenz „Emergenz ist die spontane Herausbildung von komplexen Systemen und Strukturen durch eine Vielzahl von relativ einfachen Interaktionen.“ Wikipedia
    115. 115. 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.
    116. 116. 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
    117. 117. 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
    118. 118. 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
    119. 119. Permature Optimization „Premature optimization is the root of all evil“ Donald Knuth
    120. 120. 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
    121. 121. 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
    122. 122. 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
    123. 123. Der Regenwurm
    124. 124. Der Regenwurm Vermeide Accidential Complexity.
    125. 125. Vermeide Accidential Complexity „Simplify essential complexity; diminish accidental complexity“ Neal Ford
    126. 126. 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
    127. 127. 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
    128. 128. Accidential Complexity
    129. 129. 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
    130. 130. 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.
    131. 131. 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.
    132. 132. Der Kugelfisch
    133. 133. Der Kugelfisch Teste, teste, teste.
    134. 134. Unit Tests „Im Unit Test werden kleinere Programmteile in Isolation von anderen Programmteilen getestet.“ Frank Westphal
    135. 135. 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
    136. 136. 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); } }
    137. 137. Unit Tests $ phpunit RentalCompanyTest PHPUnit 3.4.2 by Sebastian Bergmann. . Time: 0 seconds OK (1 test, 1 assertion)
    138. 138. 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
    139. 139. 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
    140. 140. 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
    141. 141. Funktionsweise
    142. 142. 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
    143. 143. Selenium in Bildern
    144. 144. Selenium in Bildern
    145. 145. 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
    146. 146. Continuous Integration SVN Repository CI Server
    147. 147. phpUnderControl
    148. 148. Mehr Tools
    149. 149. 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.
    150. 150. Der Waschbär
    151. 151. Der Waschbär Halte deinen Code sauber.
    152. 152. 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
    153. 153. 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 --------------------------------------------------------------------------------
    154. 154. 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;
    155. 155. 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/
    156. 156. Benennung
    157. 157. Benennung
    158. 158. Benennung
    159. 159. 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.
    160. 160. DRY - Don‘t Repeat Yourself „Every piece of knowlege must have a single, unambiguous, authoritative representation within a system“ Andrew Hunt and Dave Thomas
    161. 161. 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.
    162. 162. 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.
    163. 163. Die Pfadfinder-Regel „Leave the campground cleaner than you found it“ Robert C. Martin (Clean Code)
    164. 164. 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
    165. 165. 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.
    166. 166. Die Ente
    167. 167. Die Ente Das Ende.
    168. 168. Die Leseratte
    169. 169. Die Leseratte
    170. 170. Die Leseratte
    171. 171. Die Leseratte
    172. 172. Die Leseratte
    173. 173. Die Leseratte
    174. 174. Die Leseratte
    175. 175. Die Leseratte
    176. 176. Die Leseratte
    177. 177. Die Leseratte
    178. 178. Die Leseratte
    179. 179. Die Leseratte
    180. 180. Die Leseratte
    181. 181. Die Leseratte
    182. 182. Die Leseratte
    183. 183. Fragen?
    184. 184. Fragen? Vielen Dank für die Aufmerksamkeit.
    185. 185. Fragen? Vielen Dank für die Aufmerksamkeit. Bildquellen © iStockphoto.com Kontakt holger.rueprich@1und1.de stephan.schmidt@1und1.de

    ×