Im Rahmen einer Forschungsarbeit haben Fabian Schmengler und Dr. Nikolai Krambrock Maßnahmen analysiert, die bei der Entwicklung von Magento-Modulen eingesetzt werden können. Zu der Forschungsarbeit gibt es eine Übersicht und Erklärung. Ein Teil dieser Maßnahmen stammen aus problemzentrierten Interviews, deren Mitschrift heruntergeladen werden kann. Die Maßnahmen werden hier erklärt und in einen Kontext mit dem Problemen gesetzt.

MaßnahmeAdressiert folgende Probleme
M1 Schulung des Kunden / Product OwnersP1 Ungenaue oder widersprüchliche Anforderungen, P18 Viele Change Requests
M2 Einbeziehung des Kunden in den EntwicklungsprozessP1 Ungenaue oder widersprüchliche Anforderungen, P18 Viele Change Requests
M3 Abstrakte Schätzung mit Story Points und Team VelocityP3 Zeitliche Aufwandschätzung falsch
M4 Standards selber dokumentieren (basierend auf Reverse Engineering und Erfahrung)P2 Zusätzlicher Recherche-Schritt, P3 Zeitliche Aufwandschätzung falsch, P5 Know-How von erfahrenen Entwicklern wird nicht ausgeschöpft
M5 SchulungenP6 Anlernen dauert lange
M6 NegativbeispieleP6 Anlernen dauert lange
M7 Bei der Einstellung berücksichtigen: Erfahrung mit C#, Java u.ä. hilfreicher als mit PHPP6 Anlernen dauert lange, P15 Für Entwickler aufwändige Einarbeitung in Werkzeuge
M8 Vorhandene Werkzeuge verwendenP7 Debugger und/oder Versionskontrolle wird nicht verwendet, P8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung, P9 Unerwartete Seiteneffekte, P16 Fehleranfälliges Deployment
M9 Disziplin und Entwickler-AnspruchP8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung, P13 Geringe Code-Qualität von Fremd-Extensions
M10 Code ReviewsP8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M11 Automatisierte TestsP9 Unerwartete Seiteneffekte
M12 Selenium-Tests von Programmierern erstellen lassenP11 Automatisierte funktionale Tests sind aufwändig
M13 Review von Fremd-ExtensionsP13 Geringe Code-Qualität von Fremd-Extensions
M14 Eigenentwicklungen nach Möglichkeit vorziehenP13 Geringe Code-Qualität von Fremd-Extensions
M15 Abhängigkeiten zwischen Modulen und Templates vermeidenP14 Mehrere Schleifen zwischen Layoutern, Templatern und Entwicklern
M16 Alternative Entwürfe evaluierenP3 Zeitliche Aufwandschätzung falsch, P8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M17 Schätzungen hinterfragen
M18 Pair ProgrammingP5 Know-How von erfahrenen Entwicklern wird nicht ausgeschöpft, P6 Anlernen dauert lange, P8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung, P10 Viele Iterationen zwischen Codierung und Test
M19 Mehr Zeitdruck
M20 „aufpassen und nachschauen“P8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M21 Abrechnung nach AufwandP18 Viele Change Requests
M22 Kein vorgefertigtes finales Anforderungsdokument, transparent kontinuierliche Änderung der SpezifikationP11 Automatisierte funktionale Tests sind aufwändig, P18 Viele Change Requests
M23 Entwicklungs-, Test- und Live-Systeme synchronisierenP11 Automatisierte funktionale Tests sind aufwändig
M24 Manuelle Unit TestsP12 Unit Tests sind aufwändig und ineffektiv, P13 Geringe Code-Qualität von Fremd-Extensions, P16 Fehleranfälliges Deployment
M25 Konfigurations-Änderungen der Anwendung nur über Update-ScriptsP2 Zusätzlicher Recherche-Schritt, P9 Unerwartete Seiteneffekte
M26 Informiert bleiben über aktuelle Entwicklungen, auch in der CommunityP16 Fehleranfälliges Deployment
M27 Ein Team aus Templatern (Frontend) und Entwicklern (Backend), an Blockern wird gemeinsam gearbeitet (Scrum-Sirene)P14 Mehrere Schleifen zwischen Layoutern, Templatern und Entwicklern
M28 „Technical Debt“-Philosophie: Refactoring, Clean CodeP8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M29 Inkrementeller EntwurfP4 Formaler Entwurf ist erschwert
M30 Framework-DokumentationP2 Zusätzlicher Recherche-Schritt, P4 Formaler Entwurf ist erschwert, P5 Know-How von erfahrenen Entwicklern wird nicht ausgeschöpft
M31 Reverse EngineeringP2 Zusätzlicher Recherche-Schritt, P4 Formaler Entwurf ist erschwert, P5 Know-How von erfahrenen Entwicklern wird nicht ausgeschöpft
M32 Pattern Detection
M33 Visuelle Modellierung mit UML
M34 Visuelle Modellierung mit Magento-UMLP2 Zusätzlicher Recherche-Schritt, P4 Formaler Entwurf ist erschwert, P5 Know-How von erfahrenen Entwicklern wird nicht ausgeschöpft
M35 FDD-Prozess
M36 Testgetriebene Entwicklung (TDD)P8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung, P10 Viele Iterationen zwischen Codierung und Test
M37 Einfacher EntwurfP8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M38 Programming by ContractP4 Formaler Entwurf ist erschwert, P8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M39 Coding GuidelinesP8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M40 SOLID PrinzipienP8 Geringe Code-Qualität (insb. Wartbarkeit und Zuverlässigkeit) Codierung
M41 Testfall-GeneratorenP11 Automatisierte funktionale Tests sind aufwändig
M42 Built-in TestsP12 Unit Tests sind aufwändig und ineffektiv
M43 Assertion-basierte Tests
M44 Integrierte White-box Tests
M45 Test-Automatisierung systematisch entscheiden
M46 Smoke Test SuiteP11 Automatisierte funktionale Tests sind aufwändig
M47 Mutation TestingP11 Automatisierte funktionale Tests sind aufwändig, P12 Unit Tests sind aufwändig und ineffektiv
M48 Modellbasiertes TestenP11 Automatisierte funktionale Tests sind aufwändig
M49 Abstraktion von funktionalen Tests, automatisierte AkzeptanztestsP11 Automatisierte funktionale Tests sind aufwändig
M50 Kompatibilitätsanalyse mit FDMM

M1 Schulung des Kunden / Product Owners

Die Schulung des Product Owners bezieht sich auf seine Rolle und Verantwortung im Entwicklungsprozess und soll unter anderem zu präziseren und Ablauf-orientierteren Anforderungen führen. Diese Maßnahme bezieht sich auf Scrum, das Ziel ist aber unabhängig vom Prozessmodell erstrebenswert. Weiterhin würde Schulung in der Software helfen, dem Kunden den Funktionsumfang des Frameworks besser bekannt zu machen. Dies sollte die Änderungswünsche reduzieren, da der große Funktionsumfang als eine Ursache dafür identiziert wurde.

M2 Einbeziehung des Kunden in den Entwicklungsprozess

Die Einbeziehung des Kunden im gesamten Prozess ist ein Aspekt der agilen Softwareentwicklung, die die Kommunikation in den Mittelpunkt stellt. Sie führt dazu, dass das Produkt den Kundenwünschen besser entspricht und Change Requests kein Problem mehr sind, da sie frühzeitig erfolgen.

M3 Abstrakte Schätzung mit Story Points und Team Velocity

Scrum löst das Problem der zeitlichen Aufwandschätzung, indem einzelne Aufgaben (User Stories) nicht mehr nach Dauer sondern nach Größe (Story Points) geschätzt werden. Die zeitliche Schätzung ergibt sich dann automatisch durch die Team Velocity, die sich im Laufe des Projekts ergibt und von Sprint zu Sprint genauer wird. Das diese Art der Schätzung funktioniert, bedingt allerdings, dass der Kunde sich darauf einlässt, ohne Deadline und fixes Budget zu arbeiten.

M4 Standards selber dokumentieren

Undokumentierte Standards des Frameworks auf Architektur-Ebene müssen selbst dokumentiert werden, basierend auf Reverse Engineering und Erfahrung, damit das Know-How erfahrener Entwickler besser ausgenutzt wird — auch indirekt das Know-how der Entwickler des Frameworks, bzw. des Magento Enterprise Packages. Hier gibt es aus den Interviews noch keine Erfahrungswerte. Es ist also erforderlich, diese Maßnahme weiter auszuarbeiten.

M5 Schulungen

Schulungen sind ein empfohlener Einstieg. Eine intensive Schulung kann die die Zeit des Anlernens deutlich verkürzen.

M6 Negativbeispiele

Negativbeispiele für unsauberen Code sind ein erprobtes Mittel als Unterstützung beim Lernen.

M7 Bei der Einstellung zu berücksichtigen: Erfahrung mit C#, Java u.ä. hilfreicher als mit PHP

Für die Arbeit mit Frameworks, wie Magento, ist Erfahrung mit echten objektorientierten Programmiersprachen hilfreicher als mit PHP. Der Einstieg fällt so leichter und das Problem schlecht ausgebildeter PHP-Entwickler wird umgangen, wenn dies bei der Einstellung von Entwicklern berücksichtigt wird. Dazu gehört auch, dass die Entwickler mit dem Umgang mit verschiedenen Werkzeugen besser vertraut sind.

M8 Vorhandene Werkzeuge verwenden

Das Verwenden von Versionskontrolle und Debugger löst trivialerweise P7 und stellt auch keine Herausforderung dar. Ein Debugger hilft dabei, die Ursache für unerwartete Seiteneffekte zu finden. Tools zur Konflikt-Erkennung können dabei helfen, dass solche Seiteneffekte gar nicht erst auftreten, insbesondere beim Einsatz von Fremd-Extensions. Sie helfen also beim Umgang mit unzuverlässigem und schlecht wartbarem Code. Deployment-Hilfsmittel lösen Teilprobleme beim Deployment. Als Beispiel wird modman genannt, ein Werkzeug, dass die Trennung von Komponenten ermöglicht, auch wenn das Framework diese Trennung nicht praktiziert.

M9 Disziplin und Entwickler-Anspruch

Der Anspruch, sauber zu arbeiten ist ein notwendiges Kriterium für Softwarequalität. Gerade mit PHP, einer Sprache, die zu unsauberem Code geradezu ermutigt, ist bei den Entwicklern Disziplin erforderlich.

M10 Code Reviews

Code Reviews sind ein erprobtes Mittel zur Verbesserung und Sicherstellung der Code-Qualität. Shull et al untersuchen in [Shull 02] empirisch die Effektivität von Reviews und kommen zu dem Ergebnis, dass 60-90 % der gefundenen Defekte durch Reviews entdeckt werden, sofern Reviews durchgeführt werden.

M11 Automatisierte Tests

Automatisierte Tests verringern das Risiko unerwarteter Seiteneffekte und können sie umgehend erkennen. Automatisierte funktionale Tests sind dazu effizienter, als manuelle Tests.

M12 Selenium-Tests von Programmierern erstellen lassen

Ein Problem bei der Nutzung des Test-Tools Selenium ist, dass es zwar Record & Playback Tests ermöglicht, diese aber nicht immer auf Anhieb funktionieren, ohne sie programmatisch anzupassen. Werden die Tests direkt von Programmierern erstellt, stellt dies kein Problem mehr dar.

M13 Review von Fremd-Extensions

Wenn man Fremd-Extension nutzt, ist es notwendig, diese zunächst zu untersuchen, um Fehler und mögliche Konikte zu entdecken. Das Problem der oft niedrigqualitativen Extensions wird damit nicht gelöst aber es hilft, sie zu erkennen und Konflikte zu vermeiden.

M14 Eigenentwicklungen nach Möglichkeit vorziehen

Da Fremd-Extensions häufig von sehr geringer Qualität sind, sind Eigenentwicklungen in der Regel wirtschaftlicher. Es wird empfohlen, Fremd-Extensions nur sehr sparsam einzusetzen (A.1.3 S. 156, A.2.3 S. 194, A.3.3 S. 223).

M15 Abhängigkeiten zwischen Modulen und Templates vermeiden

Bei der Entwicklung von Modulen sollte die Unabhängigkeit zu Templates gewahrt bleiben. Damit werden unnötige Iterationen zwischen Templatern und Entwicklern vermieden.

M16 Alternative Entwürfe evaluieren

Beim Entwurf verschiedene Umsetzungs-Möglichkeiten in Betracht zu ziehen und gegeneinander abzuwägen kann helfen, die beste Lösung zu nden und Entwürfe bereits im Vorfeld auszusortieren, die nur unsauber oder gar nicht umsetzbar sind. Das damit einhergehende intensivere Befassen mit der Aufgabe kann auch zu akkuraterer Schätzung führen.

M17 Schätzungen hinterfragen

Werden die Aufwandschätzungen bei Abgabe hinterfragt und die Entwickler somit gezwungen, sie noch einmal zu reflektieren, kann das zu unmittelbarer Korrektur der Schätzungen führen. Eine langfristige Verbesserung der Schätzungen wird dadurch jedoch nicht erreicht, es wird lediglich das Problem verdeutlicht.

M18 Pair Programming

Pair Programming kann als Weitergabe von Know-how und Unterstützung des Lernprozesses dienen und funktioniert auch gut, wenn zwei Entwickler auf vergleichbarem Niveau zusammen arbeiten. Das Vier-Augen-Prinzip kann dabei die Iterationen zwischen Codierung und Test reduzieren.

M19 Mehr Zeitdruck

Unter Zeitdruck arbeiten Entwickler möglicherweise kurzfristig effektiver, langfristig hilft diese Maßnahme allerdings nicht.

M20 Aufpassen und nachschauen

Diese Maßnahme bezieht sich auf den Umgang mit dem dynamischen und inkonsistenten Typsystem von PHP. Gemeint ist, man muss es hinnehmen und bei der Entwicklung darauf achten.

M21 Abrechnung nach Aufwand

Die Abrechnung nach Aufwand ist, im Gegensatz zur Arbeit mit festem Budget und Deadlines, angenehmer für die Entwickler und aber oft günstiger für den Kunden und in jedem Fall für die Software-Qualität. Außerdem entfällt der von außen auferlegte Zeitdruck und es ist wirtschaftlich sicherer.

M22 Kein vorgefertigtes finales Anforderungsdokument

Eine kontinuierliche Änderung der Spezikation statt einem im Voraus erstellten finalen Anforderungsdokuments hilft, kombiniert mit der Abrechnung nach Aufwand, auf Change Requests entspannter zu reagieren, was das Problem P18 umgeht. Beide Maßnahmen werden in der Regel gemeinsam angewendet und funktionieren Hand in Hand. Änderungen gehören zur Software-Entwicklung dazu, durch den Verzicht auf ein finales Anforderungsdokument, wird diese Änderung transparent gemacht und der Kunde mehr in die Entwicklung einbezogen.

M23 Entwicklungs-, Test- und Live-Systeme synchronisieren

Die meisten Fehler beim Deployment können vermieden werden, indem die Entwicklungs- und Test-Systeme möglichst genaue Spiegelungen des Live-Systems sind, insbesondere Betriebssystem, Bibliotheken und Systemkonguration. Ein genanntes Problem bei automatisierten funktionalen Tests wird damit auch gelöst: Dass sie eigentlich ungestört auf dem Live-System laufen müssten, um aussagekräftig zu sein.

M24 Manuelle Unit Tests

Eine Alternative zu aufwändigen Unit Tests ist das manuelle Testen von isolierten Units über CLI-Skripte. Für auf diese Weise testbare Komponenten ist allerdings der Weg zum automatisierten Unit Test nicht mehr weit.

M25 Konfigurations-Änderungen der Anwendung nur über Update-Scripts

Bei einer Anwendung, in der unterschiedliche Konfigurationen große Auswirkungen auf die Funktion haben können, ist es hilfreich, die Konfiguration auf den verschiedenen Systemen synchronisiert und wiederherstellbar zu machen. Dies erreicht man dadurch, Konfigurationsänderungen während der Entwicklung nur über Skripte durchzuführen und nicht händisch in der Anwendungsinstanz.

M26 Informiert bleiben über aktuelle Entwicklungen, auch in der Community

Für bessere Übersicht über die Möglichkeiten des Frameworks ist es hilfreich, sich aktiv über aktuelle Entwicklungen auf dem Laufenden zu halten.

M27 Ein Team aus Templatern (Frontend) und Entwicklern (Backend)

Ein Team, das an Blockern gemeinsam arbeitet, löst das Problem von Schleifen zwischen Templatern und Entwicklern. Diese Maßnahme setzt allerdings voraus, dass beide Gruppen in einer Firma sitzen.

M28 Technical Dept-Philosophie: Refactoring, Clean Code

Das Prinzip der technischen Schuld führt zu erhöhter Software-Qualität, indem Refaktorisierung ermutigt wird und sauberer Code hohe Priorität hat.

M29 Inkrementeller Entwurf

Inkrementeller Entwurf ist eine Methode der agilen Entwicklung, bei der sich das Design imVerlauf der Entwicklung ergibt. Hier ist es also erwünscht, dass kein Entwurf vorab erstellt wird. P4 (Formaler Entwurf ist erschwert) wäre somit umgangen. Die Methode setzt allerdings testgetriebene Entwicklung voraus, die nur eingeschränkt anwendbar ist. Daraus folgt: Die Methode ist teilweise anwendbar auf P4.

M30 Framework-Dokumentation

Richard Lajoje und Rudolf Keller bestätigen die Schwierigkeit des Entwurfs Framework-basierter Anwendungen und identizieren die Framework-Dokumentation als wichtiges Hilfsmittel: Sie beschreiben die gemeinsame Verwendung von Design Patterns, Contracts und Motifs zur Framework-Dokumentation. Dabei wird der Begriff der Motifs neu eingeführt. Motifs dienen dazu, den Zweck des Frameworks zu beschreiben, sowie Anleitung zur Verwendung zu geben, unabhängig vom Framework-Design. Letzteres wird durch Design Patterns und Contracts beschrieben.

M31 Reverse Engineering

Techniken zur Framework-Dokumentation helfen nicht bei der Entwicklung von Anwendungen mit Frameworks, die nicht auf diese Weise dokumentiert sind. Mit Reverse Engineering könnte aufgrund des Framework-Quellcodes eine Dokumentation erstellt werden, die insbesondere auch die Framework-Patterns erklärt. Das ist allerdings ein nahezu beliebig aufwändiger Prozess. Um Standards zu dokumentieren, werden die mitgelieferten Module des Frameworks untersucht. Dies funktioniert nur bei Frameworks, deren Kern-Module ebenso aufgebaut sind, wie Erweiterungen. Dies ist bei Magento der Fall, gilt jedoch nicht im allgemeinen für Anwendungsframeworks. Für Magento ist insbesondere das Enterprise Paket, als Vorbild für Standards, nützlich. Aufgrund des hohen Aufwands wird Reverse Engineering als teilweise anwendbar auf die Probleme des Entwurfs eingestuft. Eine so erstellte Dokumentation würde die Recherche für Problemlösungen vereinfachen (P2) und Know-how verfügbar machen (P5). In Kombination mit den oben genannten Dokumentations-Techniken ermöglicht es auch einen formalen Entwurf der Anwendung (P4).

M32 Pattern Detection

Für C++ und Java wurden Werkzeuge entwickelt, die mittels Reverse Engineering Entwurfsmuster erkennen, und so automatisch dokumentieren können. Lee et al. stellen ein XMI-basiertes Tool vor, allerdings speziell für Java. Bergenti et al. eines, das ebenfalls XMI-basiert ist, aber sprachunabhängig funktioniert: Automatisches Reverse Engineering mit Pattern Detection ist bei PHP-Frameworks in der Regel nicht anwendbar, aufgrund vieler dynamischer und indirekter Relationen. Dies trifft insbesondere auf Magento zu. Für PHP existiert dementsprechend auch kein solches Werkzeug. Diese Technik ist daher nicht anwendbar.

M33 Visuelle Modellierung mit UML

Visuelle Modellierung umfasst den Entwurf mit visuellen Hilfsmitteln, insbesondere der Modellierungssprache UML. Sie vereinfacht Dokumentation, Diskussion und Prüfung des Entwurfs und hilft so auch dabei, Know-how besser zu nutzen und weiterzugeben. Die Verwendung von UML ist im vorliegenden Kontext problematisch, dies lässt sich auch auf ähnliche visuelle Hilfsmittel wie CRC-Cards übertragen. Es gibt jedoch Ansätze, UML für die Entwicklung mit Frameworks zu erweitern. Diese werden im folgenden Abschnitt behandelt.

M34 Visuelle Modellierung mit Magento-UML

Es gibt mehrere UML-Profile bzw. Erweiterungen speziell für Framework-Design: UML-F, F-UML und UML-FD. Diese Techniken sind prinzipiell anwendbar, falls man sich für Reverse Engineering entscheidet. Solche indirekten Beziehungen über globale Zugriffe sind mit UML nicht sinnvoll darstellbarund dieses Problem wird auch von UML-F, F-UML und UML-FD nicht gelöst. Man könnte das Framework-Design mit den Abstraktionen in UML-F (variable Methoden und erweiterbare Klassen) annähernd beschreiben, der design-implementation gap wäre hier allerdings so groß dass, diese Dokumentation wenig hilfreich wäre. Das Prinzip, Rollen im Framework mit UML-Tags zu notieren, ist durchaus brauchbar, müsste aber — um im konkreten Fall nützlich zu sein — adaptiert und spezialisiert werden. Die Idee Framework-spezifischer UML-Profile ist nicht neu, wie das UML-Profil für Enterprise JavaBeans (EJB) zeigt. Ein UML-Magento-Prol könnte eine zu diesem Thema weiterführende Arbeit sein. Dazu sollten unter anderem Notationen gehören für:

  • Klassen-Aliase
  • Observer
  • Rewrites
  • Controller
  • Abhängigkeiten über globale Akzessoren
  • Dynamische Beziehungen der Block-Klassen im Layout

Die Abbildung zeigt, wie eine solche Notation für Magento-Observer und Rewrites in Klassendiagrammen, in der Praxis, aussehen könnte. Mit den Tags {triggers}, {observes} und {event} werden die Event/Observer-Beziehungen dargestellt. Mit {dynamic} markierte Attribute, Methoden und Assoziationen, werden zur Laufzeit hinzugefügt, bzw. mit PHPs magischen Methoden simuliert, eine Technik, von der Magento umfassend Gebrauch macht. Klassen über ihre Aliase zu notieren (‚my/foo‘) vermeidet ein Aufblähen der Diagramme durch lange Klassennamen der Form <Namespace>_<Module>_Model_<Name> und bildet den Zugriff über Factory-Methoden wie Mage::getModel() ab. Zusammen mit dem Stereotypmodel (oder: block, helper, controller) ist die Klasse durch den Alias eindeutig bestimmt. Mittels {rewrite}-Tag wird deutlich gemacht, dass die Klasse den entsprechenden Alias einer Kern-Klasse übernimmt. Das Ziel dieser Tags und Stereotypen ist, Implementierungs-Details des Frameworks auszublenden, ohne dass Information verloren geht und auf der anderen Seite auch dynamische Beziehungen darzustellen, die zum Beispiel mittels XML-Konfigurationen konstruiert werden. UML-FD ist die vielseitigste und praxisnächste der drei Notationen und könnte als Werkzeug zur Framework-Dokumentation verwendet werden. Sie ist somit teilweise anwendbar auf P5 (Know-how), allerdings nicht im Fall von Magento, aufgrund der oben genannten Inkompatibilität. Abgesehen davon sind die Notationen UML-F, F-UML und UML-FD nicht anwendbar auf die Probleme des Entwurfs. Sie richten sich mehr an Framework-Entwickler, als an Anwendungsentwickler. Ein hypothetisches UML-Magento Profil nach obigem Beispiel wäre dagegen sowohl für den Anwendungsentwurf anwendbar (P4, P5), als auch für die Dokumentation von Problemlösungen zur Wiederverwendung (P2).

M35 FDD-Prozess

Der vom Feature Driven Development (FDD) definierte Prozess sieht die Erstellung von Klassenmodellen und Sequenzdiagrammen vor, im Wechselspiel von Entwicklerteams und Chefprogrammierern. So könnte das Know-how erfahrener Entwickler in der Rolle der Chefprogrammierer gut genutzt und weitergegeben werden (P5), aber diese Art von Entwurf funktioniert nicht, so lange keine brauchbare Notation dafür gefunden wurde. P4 muss also anderweitig gelöst werden, ebenso P2 (Zusätzlicher Recherche-Schritt). Bevor das gelöst wird, ist der FDD-Prozess nicht anwendbar, da die Phase „Plan“ je nach Feature, inklusive Fertigstellungstermine, sonst nicht strikt von der Phase „Entwurf“ je Feature getrennt werden kann. Die Probleme P2 und P4 werden mit FDD also nicht direkt adressiert. Für P5 sieht FDD eine Lösung vor, die Anwendbarkeit hängt allerdings von der Lösung der anderen Probleme ab, daher wird sie als teilweise anwendbar bewertet.

M36 Testgetriebene Entwicklung (TDD)

Testgetriebene Entwicklung (auch: test-first coding) hilft, die eigene Code-Qualität (Änderbarkeit, Testbarkeit, Lesbarkeit) zu verbessern. Weiterhin werden die Entwickler befähigt, unterstützt durch die automatisiert laufenden Tests, Bugs und Probleme bereits während der Entwicklung erkennen zu können. Die Überprüfung auf Korrektheit, und das Testen während der Entwicklung, reduziert also die Iterationen zwischen Codierung und Test. Es ist anzumerken, dass TDD keine Test-Methode, sondern eine Methode für Entwurf und Codierung ist, wobei sich das Design im Zusammenspiel mit Implementierung und Test ergibt. Dieser Vorteil lässt sich allerdings nicht ausschöpfen, sobald man durch das Design des Frameworks eingeschränkt ist und in diesem Rahmen keine Änderungen vornehmen kann. Das macht sich besonders bei der Arbeit mit Frameworks bemerkbar, die selber nicht Unit-tested sind und dadurch nicht zu weniger Komplexität, loserer Koppelung etc. gezwungen wurden Eigenschaften eines guten Designs, die die Testbarkeit fördern. In diesem Fall sind Unit Tests, und somit auch TDD, aufwändig. Teilweise lässt sich TDD dennoch anwenden, nämlich für Code-Einheiten, die in sich geschlossen sind und wenig mit dem Framework interagieren. Diese sind einfacher zu Unit-testen und das Design ist weniger vom Framework abhängig. Insgesamt wird TDD somit als teilweise anwendbar auf P8 (Geringe Code-Qualität) und P10 (Viele Iterationen zwischen Codierung und Test) bewertet, es kann allerdings aufgrund derEinschränkung durch das Framework keinen formalen Entwurf ersetzen (nicht anwendbar auf P4).

M37 Einfacher Entwurf (XP)

Die XP-Methode des einfachen Entwurfs adressiert keines der genannten Probleme mit dem Entwurf selbst, hilft allerdings gemeinsam mit Refaktorisierung (M28) dabei, die eigene Code-Qualität zu verbessern. Martin Fowler fasst das Prinzip des einfachen Entwurfs so zusammen: You don’t want to spend effort adding new capability that won’t be needed until a future iteration. And even if the cost is zero, you still don’t want to add it because it increases the cost of modication even if it costs nothing to put in. However you can only sensibly behave this way when you are using XP, or a similar technique that lowers the cost of change. Aus dieser Einschränkung folgt: Die Methode ist teilweise anwendbar auf P8 (geringe Code-Qualität).

M38 Programming by Contract

Bertrand Meyer führte ein Vertragsmodell (Programming by Contract oder Design by Contract) für Klassen und Methoden ein, das auf dem Hoare-Tripel mit Vorbedingung, Nachbedingung und Invariante basiert. Die Zusicherungen (Assertions) definieren genau, was die Programmeinheit leistet, erleichtern die Generierung von Testfällen und führen zu besserer Code-Qualität. Bei der Verwendung von Framework Hotspots sind Invarianten, sowie Vor- und Nachbedingungen jedoch möglicherweise gar nicht vollständig bekannt und müssen dies auch nicht sein,um den Hotspot zu nutzen (Blackbox Hotspot). Das macht eine sinnvolle Anwendung des Vertragsmodells unmöglich oder unverhältnismäßig aufwändig. Es kann also, analog zur testgetriebenen Entwicklung, nur in einzelnen Code-Einheiten verwendet werden, die wenig mit dem Framework interagieren. Die Methode ist teilweise anwendbar auf Entwurf (P4) und Code-Qualität (P8).

M39 Coding Guidelines

Vom Framework vorgegebene Coding Guidelines sollten selbstverständlich eingehalten werden. Diese sind jedoch oft nicht vollständig, es gibt zum Beispiel im Zend Framework keine Konventionen zur Benennung von Methoden, lediglich zur Schreibweise. So ist es der Code-Qualität dienlich, eigene Richtlinien als Ergänzung aufzustellen. Diese Methode ist ohne weiteres anwendbar.

M40 SOLID Prinzipien

Prinzipien objektorientierten Designs, wie SOLID (vgl.), sind eine gute Richtlinie, aber so lange das Framework selbst sich nicht daran hält, kann man sie nicht immer sinnvoll anwenden. Bei der Magento-Programmierung wird das Single Responsibility Prinzip verwendet. Dieses Prinzip wird in Magento häufig verletzt, was zu Kollisionsproblemen durch Klassen-Rewrites führt. Hätte jede Klasse nur einen Grund sich zu ändern, müssten nicht verschiedene Extensions dieselbe Klasse überschreiben.

Open-Closed Prinzip (OCP)

Magento ist zwar grundsätzlich an jeder Stelle erweiterbar, ohne den Kern zu verändern, teilweise werden dazu aber Source-Dateien vollständig ersetzt. Bei konsequenter Beachtung des OCP wäre dies nicht notwendig.

Liskovsches Substitutionsprinzip (LSP)

Das LSP wird nicht verletzt.

Interface Segregation Prinzip (ISP)

Magento nutzt überhaupt keine Interfaces, sondern verlässt sich für lose Koppelung auf das dynamische Typsystem von PHP. Dadurch leidet die Robustheit gegenüber Änderungen.

Dependency Inversion Prinzip (DIP)

Das DIP ist bei der Arbeit mit Frameworks dann kein Problem, solange Details vollständig in der Anwendung und Abstraktionen vollständig im Framework liegen. Die Abhängigkeit von Details zu Abstraktionen, und nicht umgekehrt, ist in dem Fall automatisch gegeben. Magento als Anwendungsframework enthält nicht nur Abstraktionen, verletzt das DIP aber technisch gesehen dennoch nicht, da explizite Abhängigkeiten durch Einsatz des Service Locator Patterns und dem dynamischen Typsystem von PHP nahezu vollständig vermieden werden. Dabei wird allerdings auch auf explizite Abstraktionen in Form von Interfaces verzichtet, was die Stabilität und Wartbarkeit wiederum beeinträchtigt. Problematisch sind also SRP, OCP, ISP und in Teilen DIP, was sich auch im Anwendungsentwurf niederschlägt. Die Prinzipien werden als teilweise anwendbar, bezüglich der Code-Qualität (P8), bewertet.

M41 Testfall-Generatoren

Eine Technik für die Erstellung von automatisierten Tests ist die Verwendung von Testfall-Generatoren. Diese benötigen eine Quelle für das Test-Orakel, dazu gibt es verschiedene Ansätze:

Software als Orakel

Das Verhalten der Software selbst wird analysiert und als Orakel verwendet. Dieser Ansatz ist nur für Regressions-Tests brauchbar, er kann keine Defekte finden. Eine kommerzielle Lösung für Java hierzu ist der AgitarOne JUnit Generator (ehemals JUnitFactory) zu finden.

Benutzerdefinierter Vertrag als Orakel

Eine Variante stellen Sai Zhang et al. vor: Ihr Generator Palus setzt JUnit Theories zur Definition von Annahmen ein, die für jede Eingabe gelten sollen. Aufgrund dieser werden mit statischer und dynamischer Code-Analyse, zufällige aber sinnvolle, Testfälle generiert.

Benutzer-Feedback als Orakel

Es werden zufällige Eingabedaten generiert und anhand von Benutzer-Feedback verfeinert. Carlos Pacheco und Michael Ernst führen diese Variante ein und haben sie unter dem Namen Randoop für Java und .NET implementiert. Die Software wurde erfolgreich bei Microsoft eingesetzt, um Fehler in Bibliotheken aufzudecken, die bereits jahrelang mit anderen Techniken getestet wurden.

Heuristik als Orakel

Dieser Ansatz ist bei Robustheit-Tests zu finden. Es werden Sonder- und Grenzfälle für Eingabedaten generiert, um Laufzeit-Fehler zu provozieren. Die Art der Fehler wird heuristisch als erwarteter Fehler oder Bug eingestuft. Beispiel: JCrasher für JavaAlberto Bacchelli et al. analysieren die Effektivität dieser automatisch generierten Tests im Vergleich zu manuell erstellten Tests und kommen zu dem Schluss, dass sie eine sinnvolle Ergänzung darstellen, handgeschriebene Tests aber nicht ersetzen können. Entsprechende Generatoren existieren allerdings bislang nicht für PHP und die Generatoren, die auf Code-Analyse basieren sind aufgrund der Dynamik von PHP nicht unmittelbar portierbar. Für Unit Tests mit PHP-Frameworks (P12) kann daher angenommen werden, dass die Technik nicht anwendbar ist. Funktionale Tests (P11) von Web-Anwendungen können unabhängig von der verwendeten Sprache durchgeführt werden, hier sind Code-unabhängige Testfall-Generatoren anwendbar. Der Ansatz „Benutzerdefinierter Vertrag als Orakel“ überschneidet sich mit der Methode „Modellbasierte Tests“. Ein Beispiel dazu (TestOptimal) wird unten, im entsprechenden Abschnitt, aufgeführt.

M42 Built-in Tests

Taewoong Jeon et al. stellen eine Technik vor, mit der das Testen von Anwendungen erleichtert werden soll, die auf Hotspot-basierten Frameworks aufbauen. Die Lösung sind sogenannte Built-in Tests, Test-Komponenten, die in die Hotspots des Frameworks eingebettet werden, ohne dass Änderungen am Framework nötig sind. Für den Test wird der Monitor anstelle des CUT als Observer registriert. Die BIT-Komponenten implementieren das gleiche Interface, wie der Observer, und der Aufruf wird durchgereicht. Vor und nach dem eigentlichen Aufruf prüft der Monitor Invarianten, Vorbedingungen und Nachbedingungen.

M43 Assertion-basierte Tests

Je Voas und Lora Kassab geben vor, untestbare Software testbarer zu machen mit Hilfe von Assertions im Programm-Code. Ist die untestbare Software allerdings ein Framework, bedeutet dies, dass Framework-Code geändert werden müsste, das kommt aus Gründen der Wartbarkeit nicht in Frage. Weiterhin schlagen Voas und Kassab statische Code-Analyse vor, um Stellen zu finden, an denen Fehlerverdeckung wahrscheinlich ist. Sie räumen allerdings ein, dass dieser Ansatz dynamisch erzeugte Programm-Zustände nicht erfassen kann, was ihn für PHP-Frameworks im Allgemeinen ungeeignet macht. Der Ansatz wird aus den genannten Gründen als nicht-anwendbar bewertet.

M44 Integrierte White-box Tests

Alexander Schmitz stellt eine Technik des Testens von Framework-basierten Anwendungen vor, die er Integrierte White-box Tests nennt, eine dynamische Kontrollfluss-Analyse mit Testdaten-Generierung. Dazu sind allerdings Änderungen im Framework-Code notwendig, es wird eine Abhängigkeit vom Framework zu einem Test-Controller geschaffen und die Framework-Klassen müssen ein Testable Interface implementieren. Die Komponenten des Frameworks informieren den Test-Controller dann über den Programmfluss, Tests werden über das Testable Interface ausgeführt. Test-Daten werden anhand der Kontrollfluss-Informationen automatisch generiert. Der Ansatz ist vielversprechend, aber aus dem genanntem Grund (Test-Code im Framework) nicht für bestehende Frameworks adaptierbar (nicht anwendbar).

M45 Test-Automatisierung systematisch entscheiden

Brian Marick untersucht die Wirtschaftlichkeit von automatisierten Tests anhand deren Lebensdauer und Kosten, im Vergleich zu manuellen Tests, und ihrer Wahrscheinlichkeit, Bugs zu finden. Er zeigt auf, dass es nicht grundsätzlich sinnvoll ist, jeden Test zu automatisieren und stellt einen systematischen Ansatz vor, die Entscheidung zur Automatisierung zu treffen.Dieser Ansatz zur Entscheidung über Test-Automatisierung von Black-Box Tests ist für alle Tests anwendbar, die sowohl manuell, als auch automatisch ausgeführt werden können, insbesondere also funktionale Tests mit Selenium. Die Kern-Frage lautet: Wie viel mehr kostet es den Test zu automatisieren, als ihn manuell auszuführen und wie wahrscheinlich ist es, dass der Test zusätzliche Bugs findet, zu den beim ersten Durchlauf gefundenen? Für die Anwendung gibt es allerdings eine entscheidende Hürde: Features, die ohne Änderungen am Support Code implementiert werden können, benötigen keine zusätzlichen automatisierten Tests. Das ist ein interessanter Aspekt für die Entwicklung mit Anwendungsframeworks, da ein Großteil des Support-Codes im Framework liegt. Allerdings beruht diese Regel auf der Annahme, dass bestehender Support-Code bereits von Tests abgedeckt wird. Bei ungetesteten Frameworks ist sie also nur dann anwendbar, wenn eine eigene Smoke Test Suite den betreffenden Support-Code bereits testet. Die übrigen Fragen zielen direkt oder indirekt auf die Lebensdauer des Tests und die Wahrscheinlichkeit, Bugs zu finden, ab. Doch auch die Wahrscheinlichkeit, Bugs zu finden, ist im Kontext von unstabilen Frameworks grundsätzlich höher, was die Entscheidung zugunsten der Test-Automatisierung verschiebt. Den Fall dass es bereits genügend Tests gibt oder es unwahrscheinlich ist dass anderer Code Bugs einführt, gibt es praktisch nicht. Daher ist die systematische Entscheidung über Automatisierung nicht anwendbar.

M46 Smoke Test Suite

Marick unterscheidet zwischen Task-getriebenen Tests und Feature-getriebenen Tests. Taskgetriebene Tests (auch: Use-Case-basierte Tests) tendieren dazu, mehr Support Code zu durchlaufen und sind daher wertvoller: sie haben eine größere Chance, Bugs zu finden, die auch ein manueller Tester finden würde. Als wichtiges Werkzeug zum Testen von Support Code werden automatisierte Smoke Tests genannt. Smoke Tests (auch: Build Verification Tests) sind Tests, die vor den eigentlichen Tests durchlaufen werden, um das Gesamtsystem zu prüfen. Eine hohe Abdeckung des Feature Codes spielt an dieser Stelle keine Rolle, Smoke Tests sollten von Änderungen im Feature Code möglichst gar nicht betroffen sein. Die Tests in der SmokeTest Suite werden allerdings darauf ausgelegt, eine hohe Pfadabdeckung im Support Code und eine große Varietät zu haben (z.B. verschiedene Reihenfolge, verschiedene Umgebungen) auf der anderen Seite können Tests weggelassen werden, die den Support Code nicht aufeine neue Weise ausführen oder eine kurze Lebensdauer haben.Die Smoke Test Suite wird im Laufe des Projekts erweitert, wenn bekannt wird, welche Stellenanfällig für Defect Clustering sind und welche scheinbar irrelevanten Faktoren zu Bugs führen.Bei Anwendungsframeworks kann idealerweise ein Großteil dieser Tests projektübergreifendwiederverwendet werden. Das Problem, fehlender funktionaler Tests für die Basis-Anwendungwürde so kompensiert.Die Methode ist also anwendbar auf P11 (Automatisierte funktionale Tests sind aufwändig).

M47 Mutation Testing

Um die Erstellung von besseren Unit Tests zu unterstützen, gibt es die Technik des Mutation Testing, mit der die Testfälle selbst getestet werden. Im Google Summer of Code gab es bereits ein Projekt, Mutation Testing in PHPUnit zu integrieren, das wurde allerdings nicht vollendet. Aktuell gibt es das Standalone Open Source Tool Mutagenesis, das für die Tests wiederum PHPUnit verwendet. Ob Mutation Tests die Effektivität von Unit Tests für Framework-basierte Anwendungen erhöhen, ist unklar. Demzufolge ist die Robustheit der Anwendung gegenüber Änderungen im Support-Code ein entscheidendes Merkmal, das Tests prüfen sollten. Mutationen des Support-Codes könnten also zur Überprüfung der Smoke Test Suite genutzt werden und sofern der CUT Support Code enthält auch zur Überprüfung von Unit Tests (beispielsweise Built-in Tests). Es fehlt dazu allerdings noch die Möglichkeit, zu spezifizieren, welche Teile des Codes mutiert werden. Mutagenesis mutiert grundsätzlich alle PHP-Dateien im Quellverzeichnis, eine Unterscheidung zwischen Support Code und Feature Code oder Framework-Code und Anwendungs-Code ist also derzeit nicht möglich. Die Technik wird als teilweise anwendbar für P11 (Automatisierte funktionale Tests sindaufwändig) bewertet, als Ergänzung zur Smoke Test Suite, allerdings nicht zum Testen von Konfigurationen, da eine Mutation von Konfigurationen nicht vorgesehen ist. Die Anwendbarkeit bezüglich P12 (Unit Tests sind aufwändig und ineffektiv) ist noch zu untersuchen.

M48 Modellbasiertes Testen

Unter Modellbasiertem Testen (MBT) fallen verschiedene Ansätze:

  1. Generierung von Testdaten aus Domain Model
  2. Generierung von Testfällen aus Environment Model
  3. Generierung von Testfällen mit Orakeln aus Behavior Model
  4. Generierung von Test-Skripten aus abstrakten Tests

Die ersten beiden Ansätze sind prinzipiell einfach umzusetzen, adressieren aber nicht den Test an sich sondern nur Testeingabe bzw. Testtreiber. Der dritte Ansatz ist der einzige, der das gesamte Problem des Test-Designs adressiert, von Eingabedaten über ausführbare Testfälle, bis zum Test-Orakel. Behavior Models sind Modelle für das System-Verhalten, beispielsweise in Form von State Charts. Der vierte Ansatz erstellt ausführbare Tests aus abstrakten Beschreibungen des Tests, beispielsweise UML-Diagrammen. Für die Tests müssen eigene Modelle erstellt werden, da Modelle aus der Entwicklung in der Regel nur vollständig genug vorhanden sind, wenn sie ihrerseits für Code-Generierung verwendet werden. In dem Fall wären Tests und Implementierung nicht hinreichend unabhängig. Es kann allerdings nützlich sein, die Test Models auf High Level Models aus der Entwicklung aufzubauen und auf Basis der informellen Anforderungen für die Tests anzupassen. Abbildung 5.8 zeigt, wie bei der Modellbasierten Softwareentwicklung UML-Modelle auf Code und Test-Code abgebildet werden können. Relevant für Tests sind Statecharts, Objektdiagramme und Ablaufdiagramme, ergänzt durch OCL Constraints und Code-Fragmente (hier: Java), und weniger wichtig, Klassendiagramme.

M49 Abstraktion von funktionalen Tests, automatisierte Akzeptanztests

Mugridge et al stellen eine Werkzeug-Kombination vor, mit der Web-basierte funktionale Tests abstrahiert werden können, so dass sie einfacher zu warten und effektiver in agiler Entwicklung einsetzbar sind. Ihre Erkenntnisse decken sich mit denen aus P11 (Automatisierte funktionale Tests sind aufwändig):

  • Tests sind empfindlich gegenüber Änderungen im User Interface
  • Tests müssen angepasst werden, was Kenntnisse auf Geschäfts- und Implementierungs-Ebene erfordert
  • Tests für neue Funktionalität können erst im Nachhinein geschrieben werden, da sie von Design-Details und Implementierungs-Entscheidungen abhängen

Dieses Problem soll mit abstrahierten Tests gelöst werden, die gleichzeitig als Spezikation auf Geschäftsebene dienen. Dazu wird das Open Source Tool ZiBreve eingesetzt. FIT (Framework for Integrated Tests) erlaubt es, Tests in Form von Tabellen zu schreiben (datengetriebene Tests), FitNesse ist einWiki-basiertes Frontend für FIT, FitLibrary erweitert FIT um verschiedene Test Runner und Fixtures, insbesondere die Anbindung an Selenium, und ZiBreve schließlich dient der Test-Abstraktion mit Beispiel-basierten Spezifikationen auf Ebene der Geschäftslogik. Alle Tests werden in Form von Wiki-Tabellen mit FitNesse und ZiBreve erstellt, es ist keine zusätzliche Programmierung notwendig. Es gibt zusätzlich noch Möglichkeiten, Tests automatisch zu generieren. ZiBreve unterstützt die Erstellung, Evolution und Organisation von business-level, example-based specifications, so dass diese über den gesamten Entwicklungsprozess hin effektiv sind.

M50 Kompatibilitätsanalyse mit FDMM

Fabian Christ und Jan-Christopher Bals stellen eine Methode zur Framework-Dokumentation vor, aufgrund dieser automatische Kompatibilitätsanalysen bei der Evolution von Framework-basierten Anwendungen möglich wären. Dies wäre eine weitere Maßnahmefür P9 (Unerwartete Seiteneffekte) im Zusammenhang mit Framework-Updates und somit eine Ergänzung zu funktionalen Tests. Ohne dass jede Version des Frameworks (und ggf. der verwendeten Drittanbieter-Module) auf diese Weise dokumentiert wurde, ist diese Analyse jedoch nicht anwendbar.