Announcement

Collapse
No announcement yet.

Anmerkung zum Artikel "Code Clean", Teil 3. Ein Plädoyer für "protected"

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Anmerkung zum Artikel "Code Clean", Teil 3. Ein Plädoyer für "protected"

    Die Artikelreihe beschäftigt sich mit den seit etwa 10 Jahren bekannten OO-Design-Mustern Robert Martins. Das ist reichlich spät, aber auf jeden Fall der Mühe wert! Dafür ein großes Dankeschön.

    Im dritten Teil wird das Open-Close-Principle behandelt: Offen für Erweiterungen und geschlossen für Änderungen. Dieses für Framework- und Library-Entwicklung essentielle Prinzip wird, wie mir scheint, oft missachtet ... und leider auch manchmal missverstanden.

    Äußeres Zeichen ist der unsägliche Gebrauch von private und package protected (default visibility) Methoden. Derart deklarierte Methoden lassen sich in externen Packages nicht mehr überschreiben. Die Klasse ist damit funktional nicht erweiterbar, Wiederverwendbarkeit und das Method-Template-Pattern werden ad absurdum geführt.

    Ein Beispiel findet sich im Listing 3 des Artikels: Was, wenn in einer von LoginService abgeleiteten Klasse die Methode checkCredentials eine weitere Prüfung durchführen soll? In der vorliegenden Implementierung muss die Methode login neu implementiert werden. Dafür besteht fachlich kein Grund, außerdem sind Probleme für die Wartung absehbar, wenn die Methode login in der übergeordneten Klasse LoginService geändert werden sollte.

    Im nicht so seltenen Extremfall führt die exzessive Verwendung von private und package protected Methoden dazu, Wiederverwendung zu verhindern. Wer schon einmal versucht hat, Klassen aus dem Package java.swing.text zu erweitern, weiß, was gemeint ist. Das Package scheint die Sichtbarkeit "protected" nicht zu kennen. Wenn man nicht den Boot-Classpath anpassen will (wo man eigene Klassen im Package java.swing.text definiert, die die Sichtbarkeit von default auf protected erweitern), dann muss man praktisch die gesamte Funktionalität neu implementieren ... Copyright- und Wartungsprobleme bei jedem neuen JDK-Release eingeschlossen.

    Also: vertraut euren Kollegen und verwendet mehr "protected"!

  • #2
    Vielen Dank für Ihr Interesse und Ihr Feedback zu unserem Artikel. Ihr "großes Dankeschön" hat mich sehr gefreut. Vielleicht darf ich mir einige Anmerkungen zu Ihrem Plädoyer erlauben. Bei dieser entscheidenden Frage geht es, meines Erachtens, weniger ums Vertrauen, sondern letztendlich um Code-Design. Und das hängt stark davon ab, in welchem Kontext sich der Code befindet. Wenn der Code dazu gedacht ist, um wie bei javax.swing.text als Modul oder Framework zu dienen, dann sind Designentscheidungen absolut kritisch zu betrachten.

    Denn oft führen falsche Entscheidungen zu Problemen wie z.B. die Rückwertskompatibilität. Eine Methode, die als Protected deklariert wird, gehört quasi zum API und kann später in seiner ursprünglichen Klasse nicht mehr so einfach geändert werden, da der Framework-Entwickler nie wissen kann, wie und wo diese Methode erweitert wurde. Die Wahl der privaten Sichtbarkeit einer Methode hat somit seine Existenzberechtigung.

    Die Probleme, die Sie in javax.swing.text adressieren, haben wahrscheinlich mit solchen Designentscheidung zu tun. Ich kenne mich in javax.swing.text zugegebenermaßen nur wenig aus, um da mit reden zu können. Generell kann ich sagen, dass ein durchdachtes API für ein solches Framework absolut existentiell ist.

    Geht es nun darum Code für sich oder sein Team zur erstellen, dann ist es am allerwichtigsten, den code so lesbar und einfach wie möglich zu halten. "Keep It Simple, Stupid" führt eher zu Designentscheidungen, die den Code evolvierbar (wartbar) halten. Wenn ich eine Methode als privat deklariere, geht es mir dabei nicht darum meinen Kollegen, den ich übrigens immer vollkommen vertraue, die Hände fest zu binden, sondern ich möchte sie nicht unnötig mit Komplexität stören. Eine erhöhte Sichtbarkeit bringt zwar Flexibilität, aber auch Komplexität mit sich. Flexibilität kann auch anders erreicht werden (siehe Strategy- oder Template-Method-Pattern).

    Entdeckt einer der Kollegen dennoch, dass er eine Methode wie in diesem Fall, checkCredentials(), erweitern muss, um z.B. Code-Duplizierung zu vermeiden, kann er dies durch Refactoring und selbstverständlich durch Beachtung der Clean-Code-Prinzipien, als da wären "Favor Composition over Inheritance", "Test First", etc., tun.
    Durch "Test First" , haben wir einen Code, der lose gekoppelt ist und wir eigentlich Probleme solcher Art per definitionem nicht haben dürften. Zum Weiteren erreichen wir durch "Test First" bekanntlich eine sehr hohe Testabdeckung, so dass Refactoringmaßnahmen keine großen bis gar keinen Schaden anrichten können und somit sehr schnell und sicher durchzuführen sind.
    Mein Gegenplädoyer wäre somit sich bei Design-Entscheidungen von testgetriebener Softwareentwicklung mehr Unterstützung zu holen.
    viele Grüße,
    Mussawisade

    Comment


    • #3
      Vielen Dank für die Antwort!

      Die Gründe kann ich sehr gut nachvollziehen. Sie ändern allerdings nichts daran, dass die exzessive Verwendung von private und default Sichtbarkeit das Open-Close-Principle behindern. Die Klassen sind dann nicht offen für Erweiterungen, das Method-Template-Pattern lässt sich nicht anwenden. Nehmen Sie als Beispiel eine Klasse mit einer public Methode, während alle anderen Methoden private sind. Was kann man hier im Allgemeinen wiederverwenden, wenn die Funktionalität in der public Methode spezialisiert werden soll (Stichwort Liskov-Substitution-Principle) ... nichts!

      In der Praxis großer Teams und unter dem üblichen Zeitdruck führen diese Umstände nach meiner Erfahrung nicht zum Refactoring, sondern zur Code-Duplizierung.

      Viele Grüße

      Comment


      • #4
        Originally posted by mgruebsch View Post
        Also: vertraut euren Kollegen und verwendet mehr "protected"!
        Den Kollegen vertrauen: unbedingt JA

        Verwendet mehr "protected"! Vorsicht

        Es gehört mit zu den Design-Entscheidungen einer Klasse, ob diese für Ableitungen entworfen wurde. Nur weil es syntaktisch möglich ist, muss die Klasse nicht auch ableitungsfähig sein.

        Best Practices / Mindset:
        Deklarationen sind per Default zunächst immer "final" und "private" [1] ... erst bewusste Design-Entscheidungen "öffnen" diese bedarfsweise ...

        cu
        @Boeffi

        [1] kann z.B. durch IDE-Unterstützung als Default-Verhalten gesetzt werden
        [2] http://blog.boeffi.net/clean-code-developer-of-passion
        Zuletzt editiert von Boeffi; 06.10.2011, 10:19.
        cu [ääähhht] boeffi.net

        Comment


        • #5
          Ich denke auch dass protected wirklich bewusst gewählt werden muss. In diesem Fall wollte der Autor aus welchen Gründen auch immer vielleicht nicht, dass diese Methode seiner Klasse überschrieben werden. Die Komplexität der Entwicklung nimmt zu wenn ich Methoden als protected markiere. Ich muss mir wirklich überlegen ob diese Methode sich beim Überschreiben so wie verhält wie ich es erwarte. Mache ich die Methode private sehe nur ich diese und niemand kann etwas kaputt machen.

          Wie gesagt: Ich sehe das auch als Design Entscheidung und nicht zwingend als muss. Ich kenne den Artikel leider nicht, allerdings vermute ich dass der Artikel nicht direkt vom Open Closed Prinzip gehandelt hat. Irgendein existierendes Pattern wird man wahrscheinlich immer wieder verletzen. Solange das bewusst und aus einem bestimmten Grund passiert sehe ich überhaupt kein Problem. Patterns sind Guidelines, keine Gesetze. Zumal sich das oben beschriebene Probleme mit Sicherheit auch per Composition hätte lösen lassen. "Favor composition over inheritance"

          Comment

          Working...
          X