Beiträge mit tag "Software Design

Webinale / IPC 2010 in Berlin

0

Eine PHP Konferenz in Berlin war für mich die ideale Kombination, endlich mal wieder meinen Koffer zu packen, in einen Zug zu sitzen und mich vier Tage in einem Hotel mit einer Menge Entwickler aufzuhalten.

Berlin fand ich spitze, aber da das hier kein Blog über Städtereisen ist, schreibe ich heute „nur” eine kurze Zusammenfassung dessen, was ich mit Nico und Frank auf der International PHP Conference Spring Edition 2010 und der Webinale 2010 erlebt und gelernt habe.

Die Workshops

Begonnen hat die Konferenz für mich mit einem Workshop am Sonntag nachmittag (morgens hatten wir eine Stadtrundfahrt, aber dazu wollte ich ja hier nichts schreiben). Der Workshop „Softwarearchitektur vs PHP” von Johann-Peter Hartmann war sehr unterhaltsam und mit der Vorstellung von ATAM (Architecture Tradeoff Analysis Method) habe ich auch etwas neues gelernt. Ich hatte zwar mit etwas mehr Inhalten zum Thema Architektur gerechnet und hätte auf den interaktiven Teil auch verzichten können, aber alles in allem war es ein interessanter Vortrag.

Montag

Der Montag startet mit zwei eher durchwachsenen Keynotes: Während der Vortrag „Die Mensch-Maschine-Beziehung und ihre Folgen” von Ibrahim Evsan unterhaltsam war, obwohl er nichts Neues erzählt hatte, war die Google-Keynote „Die Zukunft liegt in der Cloud” einfach nur langweilig. Der Gipfel war, dass Petra Sonnenberg zeigen wollte, wie in Zukunft alle unsere Applikationen in der Cloud laufen, gleichzeitig aber eine Präsentation mit Google Docs erstellt hatte, die aussah wie die ersten Gehversuche mit Power Point. Geendet hat die Keynote mit einem Werbevideo von Google. Nicht gerade das, was ich mir von einem Unternehmen wie Google versprochen hatte.

Danach kam das Highlight des Tages: Julian Koschwitz hat in seiner Session zu „Augmented Editorial Design” gezeigt, wie man klassische Printmedien mit dem Web verbinden kann und Magazine um dynamischen Content wie Videos oder Sound anreichern kann. Eine Webcam und ein Browser ist ausreichend. Ähnlich gut war die erste Session der IPC, die ich danach besucht habe. David Soria Parra hat sehr anschaulich dargestellt, wie „Git für Fortgeschrittene” Probleme beseitigt, die viele von uns mittlerweile mit Subversion haben.

Nachmittags ging es mit einem Vortrag zu „Continuous Integration und Continuous Deployment” von Manuel Pichler weiter, von dem ich mir auch mehr erhofft hatte. Manuel hat die zwar Bewegründe für CI und wie man es schrittweise einführt schön zusammengefasst, der Teil über Deployment ist leider sehr kurz ausgefallen und war für mich leider nicht hilfreich, da wir täglich und nicht nur wöchentlich deployen.

Abgeschlossen habe ich den Tag mit der für mich langweiligsten Session der Webinale: „Positive User Experience durch User Centered Web Design”. Meine Experience war in diesem Vortrag nicht sehr positiv, was zum Teil auch an der fortgeschrittenen Uhrzeit gelegen haben mag.

Dienstag

Der Dienstag morgen begann mit einem Vortrag zu „Frontend Performance mit PHP” von Frank und Nico, der sehr gut besucht war und mir auch noch ein paar neue Impulse gegeben hat, obwohl ich natürlich wußte, was auf mich zu kommt.

Da sich Jung von Matt für die aktuelle 1&1 Kampagne verantwortlich zeigt, habe ich mir danach die Session „Künftig entscheidend für den Erfolg (fast) jeder Marke: Produktinfo und -inszenierung” von Michael Behrens angeschaut. Die Beispiele, die er gezeigt hat, waren interessant, jedoch weit weg von dem, was JvM für 1&1 macht. Deutlich cooler waren auch die Beispiele, die Michael Chaize in seiner Session „Ten Innovative Projects for the Flash Platform” gezeigt hat. Von 3D-Grafiken über Gesichtserkennung bis hin zur Emulation von Spielekonsolen war da für jeden was dabei. Flash scheint (leider) trotz HTML5 immer noch nicht tot zu sein.

Durch das ständige Vertauschen von Sessions habe ich leider mittags einige Sessions verpasst und die Zeit genutzt, was für’s Büro zu programmieren. Abgeschlossen habe ich den Tag mit einer spontanen Session zu YQL von Yahoo!, in der leider nur die Standard-Beispiele gezeigt wurden.

Mittwoch

Den Mittwoch habe ich nach dem Hotel-Checkout wieder mit zwei Keynotes auf der Webinale begonnen. David Carr hat in seiner Keynote „The Speed of Now” den Namen zum Programm gemacht und ist extrem schnell durch eine Masse an Slides gegangen, so dass man ihm kaum noch folgen konnte. Ossi Urchs Keynote „Social Web oder Die neue Macht der Nutzer” klang eher nach einer Keynote von 2008 als nach einer Keynote in der man Trends für 2011 erfahren hätte. Das allgegenwärtige „Twitter, Facebook und Smartphones beherrschen unser Leben!” wurde am dritten Tag der Webinale dann doch etwas alt.

Danach fand die Panel Diskussion „Holy Code, holy Shit! – Die Developer-Designer-Hölle” statt, an der ich auch beteiligt war. Leider war es organisatorisch nicht möglich, dass sich alle Teilnehmer vorher treffen, so dass hier keine wirkliche Diskussion entstand und es eher bei „Thema verfehlt” einzuordnen war. Sollte ich jemals wieder an einer Panel-Diskussion teilnehmen, dann nur, wenn es vorher auch möglich ist, sich mit den anderen Teilnehmern und vor allem dem Moderator abzustimmen.

Nach der Mittagspause war ich dann mit meinem Vortrag „23 Dinge, die Sie über Software-Entwicklung in Teams wissen sollten” dran.

Der Vortrag lief gut, ich habe mir auch meinen „Cowboy/Indianer”-Witz merken können und das Feedback war durchweg positiv. Abgeschlossen habe ich den Tag mit einem Vortrag von Frank zum Thema „A better Approach for File System dependent tests”, in dem Frank sein Projekt vfsStream vorgestellt hat.

Zusammenfassend hat sich der Besuch der Konferenzen für mich mehr gelohnt, als das in den letzten Jahren der Fall war. Tatsächlich habe ich während der Konferenz jedoch festgestellt, dass mich die Themen der Webinale mittlerweile mehr fesseln als die Sessions auf der PHP Conference.

Verwenden Sie keine Verneinung nicht!

3

Wenn ich es schaffe, eine if-Anweisung zu vermeiden, dann versüßt mir das immer meinen Tag. Aber leider kann man als Entwickler nicht darauf verzichten, Bedingungen in den Code einzubauen.

Was ich jedoch versuche, an allen Stellen zu vermeiden, ist der schreckliche „not”-Operator, der in den meisten Sprachen durch den Einsatz von „!” implementiert wird. Der Einsatz dieses Operators macht den Quellcode immer schwerer zu lesen. Ich möchte keine Bedingungen wie die folgende in meinem Code haben:

if (!$this->isUserAuthenticated()) {
    $this->requireLogin();
}

So ein kleines Ausrufezeichen übersieht man einfach viel zu leicht und da es die Logik des Ausdrucks komplett umdreht, ist es einfach viel zu wichtig, um übersehen zu werden. Noch schlimmer wird es, wenn Sie den Operator mehrfach in einer Bedingung einsetzen.

if (!$this->isUserAuthenticated() && !$this->isInternalIP()) {
    $this->requireLogin();
}

In solchen Code-Stellen kommt es gerne auch mal vor, dass man UND mit ODER verwechselt. Denn wenn man etwas negieren möchte, sollte man dran denken, auch die Verknüpfung zu negieren oder entsprechend zu klammern. Die obige Bedingung ist mit der folgenden identisch, statt einem logischen UND verwenden Sie jedoch ein logisches ODER:

if (!($this->isUserAuthenticated() || $this->isInternalIP())) {
    $this->requireLogin();
}

Auf den ersten Blick erschließt sich mir nie, was die Bedingung aussagt, sobald ein „not”-Operator im Spiel ist.

Aber welche Möglichkeiten gibt es, um den ungeliebten Operator loszuwerden?

Verneinen Sie den Methodennamen

Statt einer Methode isUserAuthenticated() einen „not”-Operator voranzustellen, könnten Sie eine zweite Methode implementieren, die bereits auf das Gegenteil prüft und einen sprechenden Namen hat:

if ($this->isUserUnknown()) {
    $this->requireLogin();
}

So liest sich der gesamte Code viel flüssiger und es kann nicht dazu kommen, dass der Operator übersehen wird oder das Ergebis im Kopf evaluiert werden muss.

Prüfen Sie auf false

Statt den „not”-Operator zu verwenden, können Sie die Rückgabe der Methode auf false prüfen:

if (false === $this->isUserAuthenticated()) {
    $this->requireLogin();
}

Der Code ist zwar nicht so lesbar wie im vorherigen Beispiel, aber wenn Sie die Bedingung nur einmal prüfen müssen, kann es sinnvoll sein, auf die Implementierung einer Methode für diesen einen Fall zu verzichten. Achten Sie übrigens immer darauf, bei einer Bedingung den konstanten Wert auf der linken Seite der Klammer zu setzen. Sollten Sie zu wenige Gleichheitszeichen verwenden, so kann aus der Bedingung nicht aus Versehen eine Zuweisung werden.

Verwenden Sie unless

Sollten Sie Ruby verwenden, so haben Sie noch eine dritte, sehr elegante Möglichkeit. Ruby bietet Ihnen neben der if-Anweisung auch eine unless-Anweisung, die, wenn Sie sie als Modifier einsetzen, besonders elegant zu lesen ist.

require_authentication unless user_is_authenticated

In diesem Beispiel ist der Code kaum noch von einem englischen Satz zu unterscheiden. Unterstützt wird das natürlich noch dadurch, dass Sie in Ruby keine Klammern verwenden müssen, wenn Sie keine Parameter an eine Methode übergeben wollen.

Wenn Sie also das nächste Mal eine Bedingung negieren, dann denken Sie darüber nach, ob es keine bessere Lösung gibt. Und falls Sie in einer Bedingung zweimal negieren müssen, dann denken Sie nochmal über eine Alternative nach. Es gibt sie sicher.

Commercial Break: PHP Design Patterns

0

Die zweite Auflage meines Buches ist mittlerweile zwar fast schon ein Jahr alt, aber trotzdem darf natürlich ein bißchen Eigenwerbung in meinem Blog nicht fehlen.

PHP Design Patterns” ist das erste deutschsprachige Buch zu Entwurfmustern in PHP. Neben einer Einführung in objektorientierte Programmierung im Allgemeinen und mit PHP im besonderen (Kapitel 1) sowie einem kurzen Ausflug in die SPL (Kapitel 2), zeigt das Buch auf grundlegende Regeln für gutes Software Design wie z.B. „Vererbung sorgt für starre Stukturen. Verwenden Sie stattdessen Objektkomposition, um verschiedene Funktionen einfacher miteinander kombinieren zu können.” Kapitel 3 behandelt weiterhin auch Fluent Interfaces und Dependency Injection, samt der Verwendung des DI-Containers in Stubbles.

Kapitel 4,5 und 6 behandeln dann einige der Standard Gang of Four Entwurfsmuster, wie Abstract Factory, Prototype, Composite, Facade, Flyweight, Command, State oder auch Chain-of-Responsibility. Die letzten beiden Kapitel stellen das Schichtenmodell vor und zeigen, wie man dies mit Hilfe eines Model-View-Controllers und Patterns wie Active-Record, Template-View, Registry oder auch Event-Dispatcher implementiert.

Das PHP Magazin schreibt zur ersten Auflage (1/2007):

Ein rundes, das anvisierte Themengebiet hervorragend ausfüllendes Buch, das vom Leser nur eins verlangt: Zeit und Konzentration auf den Inhalt. Der Lohn dieser geringfügigen Investition sind verschiedenste Aha-Effekte und ein echter Schub an neuen Kenntnissen und Ideen. Und ein Nachschlagewerk, das man nach dem ersten Lesen nicht mehr vom Schreibtisch nehmen möchte.

Das Buch wurde für die zweite Auflage komplett überarbeitet und an PHP 5.3 angepasst. Dabei wurde ein Großteil der Kapitel erweitert:

Details zu Buch:

Frisch im RSS-Reader

0

Seit ich mich entschlossen habe, selbst aktiv zu bloggen, habe ich auch wieder angefangen, regelmäßig andere Blogs zu lesen. Neu in meinem RSS-Reader sind jetzt:

Frank Westphal

Mit seinem Buch „Testgetriebene Entwicklung mit JUnit und FIT” verfolge ich in unregelmäßigen Abständen, was Frank Westphal veröffentlicht. Auf seiner Website veröffentlich er interessante Artikel zum Extreme Programming, Agiler Entwicklung und Qualitätssicherung. Seinen Podcast „Tonabnehmer” habe ich mir bislang noch nicht angehört, wären aber sicher ein guter Grund, Podcasts endlich mal auszuprobieren.

Neal Ford

Neal Ford ist Meme Wrangler bei Thoughtworks. Auf ihn bin ich bei einer Keynote auf der Dynamic Languages World aufmerksam geworden. Am meisten beeindruckt hat mich damals (und auch heute noch) sein Satz

Simplify essential complexity; diminish accidental complexity.

Diesem Satz hatten Holger Rüprich und ich auch eine unserer neun Regeln in unserem Workshop „Die Kunst des Software Design” auf der PHP World 2009 gewidmet.

Ludwig Ostrowski

Auf das Blog von Ludwig Ostrowski bin ich nur per Zufall (aka Twitter) gestolpert. In meinen Reader hat er es aus zwei Gründen geschafft:

  1. Seine neusten Einträge befassen sich mit Dependency Injection (und sogar PHP und Google Guice, meine Lieblingsthemen bei DI), Continuous Integration und Sonar. Alles Themen, die mich auch schon seit einiger Zeit fesseln.
  2. In seinem Blog zitiert er Martin Fowler mit einem meiner Lieblingszitate.

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Ich werde das Blog auf jeden Fall mal im Auge behalten.

David Seah

Zum Abschluss noch ein Blog, das nichts mit Software-Entwicklung zu tun hat. David Seah schreibt über Design und Produktivität und kombiniert beides, in dem er wunderschöne Vordrucke für Tasklisten oder auch Ressourcenplanung zum kostenlosen Download anbietet. Zusammengefasst werden diese unter dem Namen „The Prinable CEO”, den David Seah wie folgt erklärt:

The Printable CEO name comes from the idea that a good CEO should focus primarily on those things that move the company forward; since I can’t afford to hire my own CEO, being able to print one out seemed like the next best thing!

Die Feeds

new-Operator in PHP überladen…

0

…oder besser nicht? Mit der Extension test_helpers, die Sebastian Bergmann in seinem PHPUnit Channel veröffentlicht hat, ist es möglich, einzugreifen, wenn ein Objekt mit Hilfe des new-Operators erzeugt wird und stattdessen eine andere Klasse zu instanziieren. Das kann vor allem bei Tests nötig werden, wenn es die Architektur einer Anwendung nicht erlaubt, einzelne Klassen auszutauschen:

class NewsFeedGenerator {
    public function generateFeed() {
        $newsTable = new NewsEntryTable();
        foreach ($newsTable->getEntries() as $entry) {
            // hier wird der Newsfeed generiert.
        }
    }
}

Wenn Sie für diese Klasse einen Unit-Test schreiben möchten, der prüft, ob die Klasse einen korrekten Newsfeed generiert, dann sind sie im Test immer davon abhängig, dass sie wissen, welche Einträge aktuell in der Datenbank stehen. Alternativ könnten Sie natürlich auch sicherstellen, dass die Datenbank im Voraus mit den entsprechend erwarteten Einträgen gefüllt wird.

Ein Unittest sollte allerdings eine einzelne Komponente (in diesem Fall den Newsfeed-Generator) isoliert testen, damit der Test nicht fehl schlägt, bloss weil die Datenbank im Moment nicht verfügbar ist. Aus diesem Grund werden in Unit-Tests Mock-Objekte eingesetzt, die das gewünschte Verhalten simulieren. Ein Mock für die Klasse NewsEntryTable könnte ganz einfach implementiert werden:

class NewsEntryTableMock {
    public function getEntries() {
        return array(
            array('id' => 1, 'title' => 'Title 1', 'desc' => 'Description 1'),
            array('id' => 2, 'title' => 'Title 2', 'desc' => 'Description 2')
            // etc.
        );
    }
}

Wenn Sie diese Klasse verwenden, um den Newsfeed zu erzeugen, können Sie sich sicher sein, dass Sie immer die selben Daten als Basis verwenden.

Doch wie bekommen Sie die Klasse NewsFeedGenerator dazu, diese Datenquelle zu nutzen?

Mit Hilfe der neuen Extension ist das ganz einfach, Sie ersetzen die Klasse NewsEntryTable durch NewsEntryTableMock:

function overload_callback($className) {
    if ($className === 'NewsEntryTable') {
        return 'NewsEntryTableMock';
    }
    return $className;
}
set_new_overload('overload_callback');

Wenn Sie nun eine Instanz von NewsEntryTable erzeugen möchten, dann erzeugt PHP stattdessen eine Instanz von NewsEntryTableMock und sie können Ihren Newsfeed-Generator isoliert testen. Problem gelöst, möchte man meinen.

Das Problem ist jedoch nicht, dass ihr Test nicht isoliert ablaufen kann, sondern dass Sie eine feste Kopplung zwischen NewsFeedGenerator und NewsEntryTable in Ihrer Applikation haben. Was passiert, wenn Sie die Datenquelle auch im Betrieb austauschen müssen, da die Newseinträge nicht mehr in einer Datenbank sondern einer XML- oder CSV-Datei gespeichert werden, oder sogar über einen Service von einer anderen Applikation abgefragt werden müssen? Mit der aktuellen Architektur haben Sie dazu keine Möglichkeiten. Mit dem Einsatz von Dependency Injection jedoch schon:

class NewsFeedGenerator {
    protected $dataSource;
    public function __construct(NewsDataSource $dataSource) {
        $this->dataSource = $dataSource
    }
    public function generateFeed() {
        foreach ($this->dataSource->getEntries() as $entry) {
            // hier wird der Newsfeed generiert.
        }
    }
}
interface NewsDataSource {
    public function getEntries();
}
class DBNewsDataSource implements NewsDataSource {
    public function getEntries() {
        // Aus der Datenbank lesen
    }
}

$ds = new DBNewsDataSource();
$generator = new NewsFeedGenerator($ds);

Die beiden Klassen sind nun nicht mehr voneinander abhängig, NewsFeedGenerator hat nur noch eine Abhängigkeit auf das entsprechende Interface, nicht mehr auf die Implementierung. Sie können die Implementierung für den Test oder auch im Live-Betrieb austauschen, ohne dazu die Extension verwenden zu müssen.

Sie mögen Sich nun fragen, wo das Problem liegt, wenn Sie die Klasse durch den Einsatz der test_helpers Extension austauschen, da Sie feste Abhängigkeiten haben. Ein Test für schlecht designten Code ist sicher besser als kein Test für schlecht designten Code. Das hängt jedoch davon ab, was man sich von Tests verspricht. Ich war noch nie ein großer Freund von Unit-Tests, es langweilt mich meistens, Tests zu schreiben. Was mich jedoch dazu gebracht hat, trotzdem Tests zu schreiben, ist, dass ich festgestellt habe, dass die Architektur der Applikation besser wird. Tests sind ein zweiter Client für die Applikation, der uns zwingt, die Applikation aus einem anderen Blickwinkel zu sehen. Durch Tests deckt man Abhängigkeiten auf und wird gezwungen, diese zu lösen. Die ganze Applikation wird loser gekoppelt und einzelne Komponenten leichtegwichtiger.

Das Risiko, das ich also beim Einsatz dieser Extension sehe, ist, dass man nicht mehr gezwungen wird, über die Kopplung nachzudenken. Damit geht ein großer Vorteil von Unit-Tests verloren. Sofern Sie sich sicher sind, dass eine Entkopplung zweier Klassen keine weiteren Vorteile (oder sogar Nachteile) bringt, sollte einem Einsatz der Extension nichts mehr im Wege stehen.

Wenn Sie also test-helpers einsetzen möchten, dann denken Sie jedes Mal darüber nach, ob Sie nicht ein grundlegendes Problem mit Abhängigkeiten haben und besser Ihre Applikation refaktorisieren sollten.

nach oben