Facebook
Twitter
Google+
Kommentare
9
Willkommen bei "the web hates me". Mittlerweile hat unser Team ein tolles neues Monitoringtool für Agenturen gelauncht. Unter dem Namen koality.io haben wir einen Service geschaffen, der er Agenturen ermöglicht mit sehr geringen Kosten alle Ihre Webseiten zu überwachen.

protected vs. private

Unglaublich, es ist 9:30 Uhr (zumindest als ich angefangen habe mit schreiben) und ich bin wach. Wäre ja nichts besonderes, wenn es nicht der Neujahresmorgen wäre und das schlimme ist, ich kann schon seit 7 nicht mehr pennen. Ein guter Grund also hier was zu schreiben.

Wie bereits angekündigt wollte ich ja mal was dazu schreiben, wann man private und wann man protected als Sichtbarkeit auf Klassenebene verwenden sollte. Auch wenn es wahrscheinlich eh jeder weiß, hier noch einmal schnell die Bedeutung dieser zwei Schlüsselwörter:

  • private – Eine private Methode darf nur im Kontext der Klassen aufgerufen werden, in der sie definiert wurde. Das gleiche gilt für Attribute. Leitet man eine Klasse ab, so wird der Zugriff auf diese Methoden/Variablen verboten. Von „außen“ kann man natürlich auch nicht darauf zugreifen.
  • protected – Der Zugriff von „außen“ ist hier natürlich auch gespannt, nur können diesmal abgeleitete Klassen diese Methoden aufrufen.

Ich weiß, ein alter Hut. Ich wollte aber sicher sein, dass es jetzt wirklich jeder weiß. Und außerdem ist ein wenig Buzzword-  (aka. Bullshit-) Bingo ja auch eine feine Sache.

Ich kenne einige Projekte und auch Entwickler, die erst mal jede Methode als protected definieren, denn man könnte sie ja in einer Unterklasse überschreiben wollen. Klingt ja eigentlich gar nicht so dumm. Als zweites Argument hört man die Testbarkeit (hier Unit Tests). Protected Methoden kann man durch eine „Proxyklasse“, die man von der Superklasse ableitet und alle Methoden auf public setzt testen. Vielleicht schreibe ich da ja mal ein Beispiel, obwohl ich das gar nicht mal für eine saubere Sache halte.

Dabei vergisst man aber vielleicht, dass man nur öffentliche Methoden testet. Private und protected machen gar keinen Sinn, da man mit Unit Tests nur das Verhalten nach Außen testet. Eine Art Blackboxtest also. Das Argument, dass man die Methode vielleicht einmal überschreiben will, lasse ich auch nicht gelten. Denn wenn ich sie später überschreibe, dann kann ich sie da auch noch auf protected setzen. Nach dem Motto „You ain’t gonna need it“ sollte man auch hier sparsamer sein. Viele Methoden sollten auch per Definition nicht überschreibbar sein. Setter und Getter eines Attribute sollten auf jeden Fall public oder protected sein, das Attribut aber selbst „nur“ private. Vorteil hiervon ist eine aufgeräumtere Klasse. Man hat wirklich nur die Methoden zum Aufruf zur Auswahl, die auch Sinn machen.

In unserem aktuellen Projekt sind wir sogar noch einen Schritt weiter gegangen. Wir haben das komplette Model (MVC) „neu“ geschrieben, da wir viel zu viele public Methoden gehabt haben, die gar nicht öffentlich sein sollten. Ok das Ding war auch so ziemlich Kacke und in PHP4 geschrieben, was natürlich auch die hohe Anzahl der öffentlichen Methoden erklärt. Dabei haben wir das Model von ca. 50, auf 10 öffentliche Methoden reduziert, was die Handhabung auf jeden Fall vereinfacht. Da lohnt sich auch ein Refactoring.

Als Fazit kann man also sagen, dass man nicht pauschal protected verwenden sollte, sondern vorher darüber nachdenken sollte, ob es wirklich nötig ist. In vielen Fällen is es garantiert eine gute Idee, aber in einigen wohl eher nicht.

Da fällt mir gerade ein, ich habe ja total vergessen euch ein gutes neues Jahr zu wünschen, was ich hiermit machen will.

Ü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

9 Comments

  1. Bin gerade bzgl meiner Recherche auf diesen Blogeinträg gestoßen.
    Ich muss sagen, dass ich anderer Meinung bin.
    Definitiv protected immer private vorziehen – eben genau aus dem von dir genannten Grund, dass die Klasse ableitbar bleibt. Was bringt dir die tollste Klasse, wenn man sie nicht ordentlich benutzen kann?

    Private macht nur in einem einzigen Fall Sinn:
    Wenn eine (aus welchem grund auch immer) private Methode als einziges auf eine Variable zugreift. Diese wird sonst nirgendwo verwendet, ergo: private machen.

    Reply
  2. @Mark: Dann spinnen wir das doch mal weiter. Warum nicht alles public machen? Dann kann ich auch von außen alles nutzen und bin so flexibel wie es nur geht.

    Datenkapselung ist ein wichtiger Bestandteil von OOP und ich glaube wenn man was darüber liest, wird einem klar, dass private vielleicht doch nicht so böse ist.

    Reply
  3. das hat doch damit gar nix zu tun
    public = von AUSSEN drauf zugreifbar (bei attributen oftmals schlechter stil, setter und getter benutzen soweit möglich)

    protected = abgeleitete klassen (und die wirds immer geben!) können zumindest den code weiterbenutzen

    private = nix geht

    und coden wir für uns selbst? meistens eher für einen höheren zweck…
    niemand kann so egoistisch sein und alles private machen und meinen, da gibts nix mehr zu extenden! das is einfach kurzsichtig.

    Reply
  4. @Mark: Nein das ist OOP, wir definieren Schnittstellen, die dann verwendet werden müssen. „Information Hiding“ bedeutet, das man so wenig wie möglich nach Außen gibt.

    Wie sieht es denn aus, wenn du deine Klassen refaktorst? Hältst du alle Schnittstellen stabil? Also auch alle protected Methoden? Ich glaube nicht, dass du so sinnvoll deinen Code verbessern kannst.

    Natürlich Code ist für mich selbst, aber es gibt andere Mittel Tools/Funktionalitäten zu erweitern, als Ableitung. Dekorierung und Obeserver-Pattern nur mal als Buzzwords.

    Reply
  5. >> “Information Hiding” bedeutet, das man so wenig wie möglich nach Außen gibt

    Du sagst es bereits selbst. Nach „Außen“.
    Wenn jemand eine klasse ableitet, verwendet er sie immernoch intern. Er erweitert sie ja. Vielleicht bin ich im moment zu sehr im Framework-Denken (also in meinem Fall CakePHP). Aber selbst bei Standalone Klassen verbaut man sich mit dem ganzen private zeugs jegliche Modifikation.

    beispiel class Foo:

    private $value = 0;

    public function getFinalValue() {
    return $this->value * 0.4;
    }

    wenn ich in meiner MyFoo extends Foo class nun getFinalValue überschreiben möchte (weil ich 0.5 haben will), kann ich das aufgrund des egoistischen denkens des programmers nicht.

    korrekt wäre hier:

    //Foo
    protected $value = 0;

    //MyFoo
    /**
    * @override (0.4 is not enough!)
    */
    public function getFinalValue() {
    return $this->value * 0.5;
    }

    ok? 🙂
    verbauen wir uns doch nich sinnlos zeugs. dafür is private nicht gedacht gewesen. und dank protected kann trotzdem niemand in der tatsächlichen verwendung
    echo $MyFoo->value machen (was ja eben durch den getter getan werden soll)

    Reply
  6. Hallo,

    Ich bin gerade über diesen Artikel gestolpert. Meine Frage hierzu: Du schriebst, dass „man nur Verhalten nach Aussen testet“. Ich sehe Information Hiding selbstredend auch als essenziell an, würde aber die meisten nicht public deklarierten Methoden testen wollen. Anders würde sich dies doch auch nicht mit TDD vertragen (erst den Test, dann die Implementierung zu schreiben).

    Du magst nun sagen, dass private Methoden Implementierungsdetails sind, welche vor den Nutzers einer Klasse zu verbergen sind (womit Du Recht hättest). Aber sind Tests wirklich gleichzusetzen mit den regulären Nutzern einer Klasse (nämlich denen zur Laufzeit)?
    Es muss eine andere Lösung geben. Nur Verhalten nach Außen zu testen kann es irgendwie nicht sein. Wie siehst Du das heute?

    Reply
  7. Hallo,
    Du schriebst:
    „Setter und Getter eines Attribute sollten auf jeden Fall private oder protected sein…“
    Das ist natürlich falsch. Normalerweise Setters und Getters sind public.

    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