Facebook
Twitter
Google+
Kommentare
4

Assert Null

Ich hatte ja gestern angekündigt, dass es um Asserts geht. Im google Testing Blog wurde ein Artikel darüber verfasst, ob man bei Methoden, die Objekte erwarten prüfen sollte, ob das, was tatsächlich rein gegeben wird, nicht null ist. Jetzt ist das Handling bei C++ ein wenig anders als bei PHP, aber einen Transfer kann man ohne Probleme schaffen.

Miško Hevery, sagt in seinem Beitrag, dass er im Konstruktor nicht auf null prüfen würde, da dies das Testen erschwert. So ist es einfacher nur einen Teil der Parameter zu übergeben, was einem klar macht, welcher Part denn nun in diesem Test untersucht wird. Klingt übersichtlicher.

Versuchen wir das mal auf PHP zu übertragen. Ich habe einen Konstruktor, der verlangt Objekte in seiner Signatur. Laut Hevery sollte man nun die Objkte als optional deklarieren ($object = null). Da ich eh zu jeder Äquivalenzklasse genau einen Test schreibe, ist die Chance groß, dass ich die Parameter separat abhandeln werde und somit einen der Objekte sinnvoll instanzieren werde und die anderen eben nicht.

Jetzt kommt das Problem. Was beim Testen noch recht angenehm ist, wird bei der Handhabung zu einem Defizit. Ein Objekt sollte jeder Zeit einen gültigen Zustand haben, aus diesem Grund sollte muss man auch alle „lebenswichtigen“ Parameter mit in den Konstruktor packen. Wenn diese nur optional sind, dann ist das Objekt nicht vollständig. Hevery geht auf diesen Punkt auch ein, meiner Meinung nach aber nicht konkret genug. Was ist schon ein Haus ohne Dach?

Die Lösung der google Jungs ist ganz einfach. Wir machen eine Factory, über die ich meine Klassen instanziere und schon habe ich immer gültige Objekte, ausser halt in den Test, wo ich sie auch gar nicht brauche. Wenn man so drüber nachdenkt, dann hat er recht und alle sind glücklich. Das Problem bei PHP ist aber die Sichtbarkeit des Konstruktors. Definiere ich ihn als public, so kann die factory Objekte instanzieren, jeder andere aber auch. Ich habe also wieder die Chance, unvollständige Objekte zu erstellen. Packt man die factory in die Klasse selbst mit rein, sieht es schon ganz anders aus, jetzt kann nur noch die Fabrikmethode Instanzen erstellen und diese sind auch immer gültig. Aber wie komme ich jetzt mit meinem Test an ein „Teilobjekt“? Geht nicht. Ist also doch nicht so einfach. Was fehlt, wäre eine Package/Komponenten weite Sichtbarkeit. Einige Programmiersprache, wie zum Beispiel Java bieten so etwas an. Soviel ich wei0 gehört c++ aber nicht dazu. Vielleicht könnte man hier mit „friend“ arbeiten, aber hier bin ich wieder nur am raten und  das sollte ich lieber sein lassen.

Fazit: So lange es keine zusätzliche Sichtbarkeit gibt, solltet ihr versuchen eure Objekte zu jedem Zeitpunkt gültig zu halten. Die Handhabung wird so einfach sauberer und besser verständlich. Optionale Parameter sollten wirklich nur existieren, wenn sie wirklich optional sind, also wenn sie nicht unbedingt benötigt werden.

Über den Autor

Nils Langner

Nils Langner ist der Gründer von "the web hates me" und auch der Hauptautor. Im wahren Leben leitet er das Qualitätsmanagementteam im Gruner+Jahr-Digitalbereich und ist somit für Seiten wie stern.de, eltern.de und gala.de aus Qualitätssicht verantwortlich. Nils schreibt seit den Anfängen von phphatesme, welches er ebenfalls gegründet hat, nicht nur für diverse Blogs, sondern auch für Fachmagazine, wie das PHP Magazin, die t3n, die c't oder die iX. Nebenbei ist er noch ein gern gesehener Sprecher auf Konferenzen. Herr Langner schreibt die Texte über sich gerne in der dritten Form.
Kommentare

4 Comments

  1. Du lösst also dahingehend das in PHP auf, das es in PHP aus den genannten Gründen keine solche Factory geben kann und ergo die Klasse die Aufgaben der (potenziellen) Factory zu übernehmen hat bis es eine über Klassengrenze hinaus differenzierbare Sichtbarkeit gibt? Dabei schreibst Du selber, dass Du garnicht weisst, ob C++ die Sichtbarkeiten in Packages abbilden kann.

    Vielleicht ist es eher eine Frage der Abstraktion. Natürlich kann es ein Haus ohne Dach geben (ist eben ein Null-Dach und die sehen so aus während sie gebaut werden). Meine Objekte in der Anwendung müssen doch vornehmlich logisch funktionieren (Das Haus kann gebaut werden und auch abgerissen, vielleicht soll es auch bewohnbar sein), damit ich sie oft und gerne wiederverwenden kann. Wenn ich im Objekt schon eine konkrete Abbildung implementiere, dann hebt sich dieser Vorteil schon wieder sehr weit auf. Die penible Prüfung im Code-Beispiel auf Null/Nicht Null Geschichten könnte als sowas angesehen werden. Nicht das es einfach wäre da immer den goldenen Weg zu finden, aber vielleicht ist dies mehr die Problematik die sich hier ausdrückt.

    Wenn ich mich gerade fürs Testen entscheiden, so gibt mir das doch bei vollständigen Tests eben die Sicherheit. Da es sogar gar kein Assert-Objekt in PHP gibt, würde ich eher mal nahelegen, der Klasse eine Methode an die Hand zu geben, die Prüft und Rückgibt, ob das Haus komplett ist – falls dies die vordringliche Sorge bei diesem Objekt ist.

    Und hier ziehlt vielleicht auch die Erwähnung der Factory-Methode ab. In der selbst wird vielleicht im einen Teil sich ums Dach gekümmert und in einem anderen Teil um Tür und Fenster.

    Und wo zum Teufel finde ich das Assert-Objekt in PHP?

    Reply
  2. 1) In PHP findest du nur die Assert Funktion, die aber völlig ausreichen kann. Prüfen ob ein Objekt null ist kann ich hiermit auch.

    2) Wenn ich ein Haus habe, das auch ohne Dach ein Haus ist, dann hat das Dach nichts im Konstruktor zu suchen (ist zumindest meine Meinung). Hier kommen nur die minimal benötigten Parameter rein. Ein addRoof( ) könnte man sich basteln, um das Problem zu lösen. Testbar wäre es so auch noch.

    3) Den ersten Abschnitt verstehe ich leider nicht so ganz.

    4) Die Null Dach Lösung halte ich für eine sehr saubere. Ich will halt verhindern, dass man kein Dach hat, es aber die Methode getRoof( ) oder so etwas im Interface gibt.

    Reply
  3. Danke für dein ausführliches Feedback:

    3) Den ersten Abschnitt verstehe ich leider nicht so ganz.

    Der bezog sich auf die Herleitung deiner Lösung. Ich wollte damit nachfragen, ob dieser Gedankengang bei deiner eine Rolle gespielt hat.

    Wie dem auch sei, du referierst nun das Null Object als das bessere Null. Dies beantwortet ein Teil meiner Frage. Ist sicherlich kein schlechtes Konzept und wie Du schreibst macht dies auch Sinn.

    Wenn es mir allerdings um Herleitung beim Programmieren geht, dann ist es zwar löblich Null Objekte zu verwenden. Getreu dem Motto: Programmiere nicht gegen die konkrete Implementierung (hier von Null) sondern im gegen eine abstrakte Instanz davon (hier: das Null Objekt). Allerdings schränkt es die Entwicklung im Sinne einer späteren Implementierung wiederrum ein, kann sich also Kontraproduktiv auswirken. Da kann eine spätere Factory Klasse oder eine Fassade das mehr an Sicherheit für jede Anwendung bieten ohne, dass die Verwendung der eigenen Objekte zu stark eingeschränkt wurde.

    Um im Bespiel vom Testing Blog zu bleiben: Du wolltest doch beim Testen dich nicht von zu vielen Komponenten abhänig machen. Für jedes Unterobjekt auch nochmal ein Null Objekt zu schreiben erhöht den Grad von Abhänigkeiten zumal Du ja schon angemerkt hast, dass PHP kein besonders sicheres Packaging bietet.

    Reply

Leave a Comment.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen