PHP SDK for Amazon Web Services

Wednesday, September 29. 2010
Comments

Yesterday, Jeff Barr announced Amazon's own PHP SDK for their web services — own, because AWS hired CloudFusion's lead developer earlier this year (in March) and I guess after a while they decided it was time to incorporate his open source efforts into the company. The full story is on getcloudfusion.com.

So what?

What's more than just pretty interesting about all of this, is that not only is the AWS PHP SDK hosted on Github (bonus points for sure), but since it implements almost the entire API of all infrastructural services and is backed by the API provider, this library currently presents the most feasible way for PHP developers to work with AWS. And to add to that, the library is fully documented as well.

Having worked myself on various small wrappers for the EC2 and SNS web services, I'm really somewhat glad that I can stop working on them now and continue implementing the web services.

PEAR

Amazon's move is also another victory for PEAR (and of course Pirum) because it brings more acceptance to the distribution of PHP libraries using a PEAR Channel.

The SDK's channel is the following: http://pear.amazonwebservices.com/

Setup

pear channel-discover pear.amazonwebservices.com
pear install aws/sdk

The flipside

There are absolutely no unit tests included anywhere. But since I'm assuming that they exist indeed, I hope they will be open sourced before not too long. Or in case they don't (What's up with that?), that pull requests will be accepted so the community will be able to contribute some.

Google Chrome: useful extensions for developers

Wednesday, September 22. 2010
Comments

While Chrome likes to emphasize how speedy it is, it is also sometimes a pretty bare-metal browser. But all the speed comes at an expensive — Chrome is doing less out of the box, which some people will say means, "Chrome is focusing on the essentials".

So because I'm thankful for said speedyness and overall painlessness, I also realize how I little extra bells and whistles I really need for a great browsing experience.

And in the end, being speedy and painless clearly wins.

I've been using Chrome for over a year now (or longer?) and aside from a couple custom extensions I wrote for my own pleasure, so far there only three other extensions I installed.

JsonView

JsonView formats JSON into a pretty structure which I can expand and contract. It also adds some color. This extension is incredibly helpful to those dealing with web services which exchange data using JSON. A must-have if you recognize yourself in that group.

Link: https://chrome.google.com/extensions/detail/chklaanhfefbnpoihckbnefhakgolnmc

XML Tree

XML Tree is just like JsonView, but for XML. Yes, it's dead simple, but I also highly recommend it.

Link: https://chrome.google.com/extensions/detail/gbammbheopgpmaagmckhpjbfgdfkpadb

SpeedTracer

SpeedTracer could be called the equivalent to Firebug. But since Chrome already ships with a pretty comprehensive developer console (which gets you about 80-90% of what Firebug does), SpeedTracer really is the icing on the cake. Not a must have, but a nice to have.

Link: https://chrome.google.com/extensions/detail/ognampngfcbddbfemdapefohjiobgbdl

Debugging Zend_Test

Monday, September 20. 2010
Comments

Sometimes, I have to debug unit tests and usually this is a situation I'm trying to avoid.

If I have to spend too much time debugging a test it's usually a bad test. Which usually means that it's too complex. However, with Zend_Test_PHPUnit_ControllerTestCase, it's often not the actual test, but the framework. This is not just tedious for myself, it's also not the most supportive fact when I ask my developers to write tests.

An example

The unit test fails with something like:

Failed asserting last module used <"error"> was "default".

Translated, this means the following:

  • The obvious: an error occurred.
  • The error was caught by our ErrorController.
  • Things I need to find out:
    • What error actually occurred?
    • Why did it occur?
    • Where did the error occur?

The last three questions are especially tricky and drive me nuts on a regular basis because a unit test should never withhold these things from you. After all, we use these tests to catch bugs to begin with. Why make it harder for the developer fix them?

In my example an error occurred, but debugging Zend_Test also kicks in when things supposedly go according to plan. Follow me to the real life example.

Real life example

I have an Api_IndexController where requests to my API are validated in its preDispatch().

Whenever a request is not validated, I will issue "HTTP/1.1 401 Unauthorized". For the sake of this example, this is exactly what happens.

class ApiController extends Zend_Controller_Action
{
    protected $authorized = false;

    public function preDispatch()
    {
        // authorize the request
        // ...
    }
    public function profileAction()
    {
        if ($this->authorized === false) {
            $this->getResponse()->setRawHeader('HTTP/1.1 401 Unauthorized');
        }
        // ...
    }
}

Here's the relevant test case:

class Api_IndexControllerTest ...

    public function testUnAuthorizedHeader()
    {
        $this->dispatch('/api/profile'); // unauthorized
        $this->assertResponseCode(401);
    }
}

The result:

1) Api_IndexControllerTest::testUnAuthorizedHeader
Failed asserting response code "401"

/project/library/Zend/Test/PHPUnit/Constraint/ResponseHeader.php:230
/project/library/Zend/Test/PHPUnit/ControllerTestCase.php:773
/project/tests/controllers/api/IndexControllerTest.php:58

Not very useful, eh?

Debugging

Before you step through your application with print, echo and an occasional var_dump, here's a much better way of see what went wrong.

I'm using a custom Listener for PHPUnit, which works sort of like an observer. This allows me to see where I made a mistake without hacking around in Zend_Test.

Here is how it works

Discover my PEAR channel:

sudo pear channel-discover till.pearfarm.org

Install:

[email protected]:~/ sudo pear install till.pearfarm.org/Lagged_Test_PHPUnit_ControllerTestCase_Listener-alpha
downloading Lagged_Test_PHPUnit_ControllerTestCase_Listener-0.1.0.tgz ...
Starting to download Lagged_Test_PHPUnit_ControllerTestCase_Listener-0.1.0.tgz (2,493 bytes)
....done: 2,493 bytes
install ok: channel://till.pearfarm.org/Lagged_Test_PHPUnit_ControllerTestCase_Listener-0.1.0

If you happen to not like PEAR (What's wrong with you? ;-)), the code is also on github.

Usage

This is my phpunit.xml:

<?xml version="1.0" encoding="utf-8"?>
<phpunit bootstrap="./TestInit.php" colors="true" syntaxCheck="true">
    <testsuites>
    ...
    </testsuites>
    <listeners>
        <listener class="Lagged_Test_PHPUnit_ControllerTestCase_Listener" file="Lagged/Test/PHPUnit/ControllerTestCase/Listener.php" />
    </listeners>
</phpunit>

Output

Whenever I run my test suite and a test fails, it will add something like this to the output of PHPUnit:

PHPUnit 3.4.15 by Sebastian Bergmann.

..Test 'testUnAuthorizedHeader' failed.
RESPONSE

Status Code: 200

Headers:

     Cache-Control - public, max-age=120 (replace: 1)
     Content-Type - application/json (replace: 1)
     X-Ohai - WADDAP (replace: false)

Body:

{"status":"error","msg":"Not authorized"}

F..

Time: 5 seconds, Memory: 20.50Mb

There was 1 failure:

1) Api_IndexControllerTest::testUnAuthorizedHeader
Failed asserting response code "401"

/project/library/Zend/Test/PHPUnit/Constraint/ResponseHeader.php:230
/project/library/Zend/Test/PHPUnit/ControllerTestCase.php:773
/project/tests/controllers/api/IndexControllerTest.php:58

FAILURES!
Tests: 5, Assertions: 12, Failures: 1.

Analyze

Analyzing the output, I realize that my status code was never set. Even though I used a setRawHeader() call to set it. Turns out setRawHeader() is not parsed so the status code in Zend_Controller_Response_Abstract is not updated.

IMHO this is also a bug and a limitation of the framework or Zend_Test.

The quickfix is to do the following in my action:

$this->getResponse()->setHttpResponseCode(401);

Fin

That's all. Quick, but not so dirty. If you noticed, I got away without hacking Zend_Test or PHPUnit.

The listener pattern provides us with very powerful methods to hook into our test suite. If you see the source code it also contains methods for skipped tests, errors, test suite start and end.

Monkey patching in PHP

Tuesday, June 22. 2010
Comments

I haven't really had the chance or time to play with PHP 5.3 until recently when Ubuntu 10.04 upgraded my local installations and kind of forced me to dive into it a little. And I'm also probably the last person on the planet to notice, but namespaces in PHP 5.3 allow you to monkey-patch core PHP code.

What's monkey patching?

So monkey patching is a technique to replace functions at runtime. One of the more common applications is stubbing (or mocking) code in unit tests. So for example mocking the response from a server allows you to run a unit test in absence of another external service. Thus making your test suite both more robust and possible bugs easier to squash.

Up until 5.3 monkey patching was not available in PHP — unless you used the runkit extension.

Other use cases are changing the behavior of code without directly forking it and maintaining a local copy, e.g. to add a feature or so or even to apply bug fixes without modifying the original code.

Example

Here's some example code.

<?php
namespace monkeypatch;

$str = 'your mom';

echo "This should eight, but it's not: " . strlen($str) . "\n"; // 6
echo "Now this should be really eight: " . \strlen($str) . "\n";

function strlen($str) {
    return 6;
}

The difference between strlen() and \strlen() is, that the first call uses the function we defined in the current namespace. Since using the namespace operator requires it to be the first thing in a file, all consecutive functions and classes are part of this namespace. If an equivalent is not available in the current namespace, it'll fall back to the parent namespace or root.

Other applications that come to mind would be fixing the parameter order in strstr() and in_array(), and similar! But of course I'm kidding and wouldn't suggest that really. :-)

Fin

That's all kids!

Wieso zum Teufel benutzt DU keine Versionskontrolle?

Tuesday, January 5. 2010
Comments

(This post is entirely in German, I'll see if I can translate this rant later.) Also, Prost und frohes Neujahr — ich starte das neue Jahr damit etwas emotionalen Ballast aus dem alten Jahr loszuwerden!

Ab und an treffe ich wieder auf Kunden und Kollegen mit denen ich vor relativ langer Zeit — fünf oder sechs Jahren oder länger — zusammengearbeitet habe.

Die Zeitspanne ist deshalb wichtig weil ich generell daran Interesse habe immer wieder oder zumindest des öfteren mit jemandem zusammenzuarbeiten, wenn die Zusammenarbeit erfolgreich war. Wenn es allerdings Zwangspausen zwischen Projekten gibt, dann kann sich der geneigte Leser vorstellen, dass das letzte Projekt nicht vollkommene Zufriedenheit auf beiden Seiten ausgelöst hat.

Nichts desto trotz gibt jeder dem anderen eine neue Chance, und die Bezahlung spielt dann nicht eine gerade untergeordnete Rolle. Einige nennen so etwas Schmerzensgeld, und so ähnlich ging es mir auch in diesem Fall. Bzw. waren meine Motivation Weihnachtsgeschenke für Familie und Freunde, eine PS3 Slim und diverse andere Annehmlichkeiten.

Zwischenmenschliche Beziehungen

Schlußendlich entwickeln Menschen sich immer weiter. Diese Entwicklung merke ich nicht nur an technischen Fähigkeiten und Details, sondern auch menschlich, oder wie heisst so schön — am Stil.

Wenn ich mir nicht sicher bin, dann stelle ich mir folgende Fragen:

  • Wie laufen die Projekte ab?
  • Wieviel Spass macht es allen beteiligten?

Ausnahmen bestätigen die Regel und ab und an dauert die Entwicklung länger und ich muss Überzeugungsarbeit leisten.

In solchen Situation höre ich Sätze wie zum Beispiel:

  • "Aber das mach ich schon immer so."
  • "Objekte, wozu soll das gut sein? Kannst mir auch nen Array geben?!"
  • "Tests. Sowas mach ich nicht."

… oder mein absoluter Lieblingssatz:

  • "Versionskontrolle — das brauch ICH nicht."

Und irgendwann geht's natürlich schief.

Die Versionskontrolle

Besonders der letzte Satz hat es mir angetan und mich tatsächlich nach zwei Wochen Urlaub, nach denen mich wirklich nichts erschüttern konnte, während der Feiertage etwas auf die Palme gebracht.

Denn natürlich lief das Projekt nicht ganz so zügig und wurde nicht pünktlich zu Weihnachten fertig. Und da im neuen Jahr alles funktionieren soll, wurde es etwas hektisch!

Auf meine Frage welche (nicht ob) Versionskontrolle er benutze, erklärte mir der Kollege am Anfang ganz stolz, dass er alle Daten in mehren Kopien vorhät. Beim Kunden ("Produktivsystem") und auf seinen beiden Rechnern. Natürlich fällt einem dabei auf, dass die Versionskontrolle etwas missverstanden wird — denn primär geht es nicht um Backup.

Aber wieso man diesen Stress macht und nicht an einen Dienstleister wie github oder unfuddle auslagert, das ist mir ein Rätsel. Denn natürlich sollte auch die Versionskontrolle gesichert werden.

In dieser Situation fragte ich mich nur wie ein Team zusammenarbeitet, wenn es ohne VCS auskommen muss. Inzwischen kann ich es mir eigentlich gar nicht mehr vorstellen.

Als Argumente für den Einsatz einer Versionskontrolle führte ich an, dass es (eigentlich auch allein Sinn macht — Dokumentationszwecke — und) ab zwei Arbeitern nicht nur viele Vorteile mitsichbringt sondern ein Muss ist, und eine Voraussetzung dafür, dass ich an diesem Spiel teilnehme.

Ich erinnere mich oft an Projekte in dem Mitglieder des Teams mehr als einmal den Stand des anderen überschrieben haben. Für mich reicht das, aber anscheinend ist so etwas nicht abschreckend genug. Zu oft müssen Entwickler mit Code umgehen und wissen nicht wieso ein Problem auf diese und nicht jene Art gelöst wurde — bei richtigem Einsatz der Versionskontrolle (und Dokumentation im Code) passiert so etwas nicht.

Am Ende einigten wir uns auf git und ich kaufte dafür bei Github ein — und es ging los.

Im Projekt

Rückschläge gab es.

Mein Kollege besitzt zum Beispiel noch das selbe Notebook wie vor sechs Jahren. Und das hatte er gerade mit Windows XP neu eingerichtet. Und Git unter Windows war ihm zu mächtig ("das schreibt sich sicherlich überall in die Registry rein") wodurch er auch nie die Versionskontrolle dabei hatte.

Obwohl ich ihn mehr als einmal gebeten habe zumindest während unserer Zusammenarbeit git auf seinem Laptop aufzusetzen, hat er es dann doch nicht geschafft.

Besonders zeitraubend ist es, wenn der aktuelle Stand per Email oder per USB-Stick ausgetauscht wird. Manuelles mergen gehört zu den Dingen die ich überhaupt nicht machen möchte und generell lehne ich es auch ab meine geänderten Dateien per Email wieder zurückschicken.

Wieso auch, wenn alles mit git commit, git push und git pull erledigt werden kann?

Aber natürlich haben wir genau diese Dinge zwischen Weihnachten und Neujahr getan.

Die Ironie und Absurdität dieser Situation ist bezeichnend.

Fazit

Liebe Kinder!

Bei der Arbeit könnt Ihr wirklich am meisten Zeit vergeuden und alle in den Wahnsinn treiben wenn Ihr keine Versionskontrolle einsetzt.

Denn bei konsequenter und halbwegs gescheiter Benutzung würden folgende Fragen entfallen:

  • "Wieso sieht das so aus?"
  • "Hatten wir das nicht schon mal?"
  • "Welche Dateien hast Du gerade bearbeitet?".
  • "Kannst Du mir das mal eben schicken?"
  • "Das hab ich doch gestern schon gemacht?"
  • "Hast Du eben die Datei x überschrieben?"

... und mir würden noch andere einfallen, aber irgendwann muss auch mal Schluß sein.

The End

Keine Versionskontrolle — das hab ich lange nicht erlebt aber vielleicht ist das bezeichnend für die PHP-Welt. Ich würde auch zu gern noch einen Absatz über's Testen schreiben, denn auch darauf haben wir konsequent verzichtet.

Und es gab zu viele gute Beispiele wo es sinnvoll gewesen wäre. Aber das hebe ich mir für einen anderen Tag auf! :-)