Document ID: /fineweb-2-swissfilter-quality_10-filterrobots/filtered/03471.jsonl.gz/1692

27. April 2017 von Horst Naujoks
Das geht dich nichts an. Doch das geht mich sehr wohl etwas an.
Wie Sichtbarkeitsregeln und eindeutige Klassifizierungen die Arbeit am Code erleichtern können
Die fachlichen Hintergründe des Projekts waren mir größtenteils bekannt, eine fachliche Spezifikation im eigentlichen Sinne lag allerdings nicht vor. Das Projekt wurde agil entwickelt und Vorlagen gab es in Form von User Stories und dazugehörigen Entwickleraufgaben, die allerdings meist nur aus ein paar Sätzen bestanden. Im Nachhinein stellte sich zudem heraus, dass diese Vorgaben teilweise überholt, nicht vollständig und nicht deckungsgleich mit dem vorliegenden Code waren. Als Entwickler habe ich allerdings gelernt, mit solchen Dingen umzugehen. Ihr solltet euch ebenfalls mit Arbeitssituationen dieser Art vertraut machen, denn es kommt immer wieder vor, dass ihr mit unvollständigen Vorgaben innerhalb eines Projekts konfrontiert werdet.
Wie ihr euch sicherlich vorstellen könnt, ist es nicht immer ganz einfach, sich in einem unbekannten Code zurechtzufinden. Häufig geht ihr als Entwickler von einem Bug aus, eruiert die Code-Stelle und versucht, das Softwaredesign zu verstehen. Letzteres ist wichtig, da das Design euch vorgibt, wie Klassen, beziehungsweise allgemeine Code-Teilbereiche zusammenspielen sollen. Bei der Navigation im Code oder besser gesagt beim Design solltet ihr vor allem auf zwei Dinge achten:
- Die Benennungen von Klassen und Methoden, die das Fundament des Modells bilden.
- Die Existenz einer „DIE“, unter anderem Browse References und Show-Hierarchie, die zuverlässig aufzeigt, welche Codes miteinander verknüpft sind.
Soweit so gut. Doch was ist zu tun, wenn ein Design zwar vorhanden ist, es aber an vielen Stellen nicht konsequent umgesetzt wurde? Etwa wenn eine XyzMapperKlasse nicht nur Dinge mappt, sondern auch Persistenzaufgaben wahrnimmt? Oder wenn DTOs den Postfix-Bean einmal tragen und einmal nicht. Und wenn diese DTOs dann noch an manchen Stellen für externe und an anderen für interne Verarbeitungen verwendet werden?
So umgeht ihr mögliche Stolpersteine
Existiert eine Vielzahl solcher Stolperstellen, ist es wenig hilfreich, wenn ihr euch an einem Design orientiert, um den Code zu verstehen. Eure einzige Möglichkeit besteht darin, die gesamte Code-Basis durchzugehen und eigentlich jede Methode und jeden Methodenaufruf zu untersuchen. So könnt ihr zumindest sicherstellen, nichts übersehen zu haben. Dieses Vorgehen ist aber nichts außergewöhnliches und in manchen Fällen eben notwendig. Im Folgenden möchte ich euch Schritt für Schritt beschreiben, wie ihr am besten vorgehen könnt. Zunächst solltet ihr euch die Outline einer Klasse ansehen, denn dort seht ihr auf einen Blick, wieviele Methoden vorhanden sind und welche als „private“ oder „public“ klassifiziert sind. Als „privat“ werden die Methoden bezeichnet, die nur in der Klasse selbst verwendet werden: Der Begriff „public“ meint hingegen die Methoden, die auch von außen verwendet werden können. Die Unterscheidung von „private“ und „public“ ist also von entscheidender Bedeutung, wenn ihr euch im Code zurechtfinden möchtet.
In der Code-Basis, die mir im oben genannten Projekt übertragen wurde, ist mit der Verwendung von „public“, „private“; „protected“ und „default" recht nachlässig umgegangen worden. Häufig waren in hier zu viele Parameter in der Rubrik „public“ verzeichnet. Das ist leider oft der Fall, wenn in Eile gearbeitet wird. Aber viel erstaunlicher fand ich, dass die Verwendung von „protected“ und „default“ offenbar ohne wirkliche Kenntnis von deren Funktionsweise gemacht wurde. Ich möchte dies im Rahmen des Beitrags allerdings nicht ausführlicher beschreiben. Denjenigen, die sich das genannte Problem nochmals vor Augen führen möchten, empfehle ich das folgende Tutorial: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Richtig kommunizieren durch Klassifizieren
Sichtbarkeitsregeln und Information Hiding gibt es in vielen Programmiersprachen und sind Teile der objektorientierten Programmierung. Klassifiziert ihr eine Methode als „privat“, signalisiert ihr dem Compiler, dass diese Funktion niemanden etwas angeht, sprich dass sie nur von “eurer” Klasse verwendet werden darf. Das ist auch richtig und gut so. Der Compiler ist zwar kein Mensch, dafür aber meist sehr streng, denn er setzt Sichtbarkeitsregeln ohne Wenn und Aber um. Nur in Java − das weiß ich, da ich es bereits mehrfach eingesetzt habe − kann diese Striktheit per „Reflection“ umgangen werden. Aber was bedeutet das eigentlich, wenn ihr diese Sichtbarkeitsregeln umgehen könnt? Die Antwort darauf ist einfach, denn es geht weniger darum, einem anderen Programmierer etwas vorzuenthalten oder zu verbieten, sondern um einen Austausch. Liegt eine „public-Klassifizierung“ vor, signalisiert ihr einem anderen Entwickler „Hier musst du dich nicht um den Inhalt kümmern“ oder „Das ist dir möglicherweise eine Hilfe.“. Es geht also schlicht und einfach darum, Design zu kommunizieren. Aus diesem Grund finde ich auch die Sichtbarkeitsregeln, die TypeScript in der Browser-Programmierung neu einbringt, sehr hilfreich. Sie verbessern nämlich unmittelbar euer Code-Verständnis. Auch wenn der TypeScript Compiler am Schluss kommunes JavaScript generiert und die Sichtbarkeitsregeln, beziehungsweise Sichtbarkeitshinweise spurlos verschwunden sind, findet die Kommunikation zwischen denjenigen, die Code schreiben und lesen vorher statt. In dem Projekt, das ich anfangs erwähnt habe, wäre ich froh gewesen, wenn diese Art der Kommunikation ernsthaft Berücksichtigung gefunden hätte.
Fazit
Eine kleine Überschlagsrechnung zum Schluss: Bei beispielsweise zehn Klassen mit je zehn Methoden, die alle „public“ sind, müssten 100 mal 100 potenzieller gegenseitiger Aufrufe angenommen werden, damit 10.000 vom einen zum anderen Ort navigieren. Sind hingegen nur eine oder zwei Methoden „public“ und die anderen „private“, so reduziert sich die Navigation auf 100 oder 400 Beziehungen. Wie ihr an diesem Beispiel seht, kann euch die richtige Kommunikation zwischen den Entwicklern erheblich Zeit sparen. Pflegt ihr zudem die Verwendung von „default“ und „protected“ wie sie eigentlich gedacht sind − nicht nur auf Methoden, sondern auch auf Klassenebene − steigert das zudem die Ausdrucksstärke der Architektur, vermittelt euch ein gewisses Maß an Sicherheit beim Zurechtfinden und spart weitere Zeit. Sichtbarkeitsregeln – so meine Erkenntnis – dienen nicht dem Vermitteln von “Das geht dich nichts an”, sondern der Kommunikation von Softwaredesign. So gesehen, geht es mich doch sehr wohl etwas an.
Anmerkung 1: Der Einfachheit habe ich Verweise auf Modifier in Interfaces oder Inner Classes bewusst außer Acht gelassen. Aber selbstverständlich gilt hier das gleiche Prinzip. Je bewusster gewählt, helfen sie der Kommunikation des Designs.
Anmerkung 2: Mit Java 9 bietet sich in Kombination mit dem Module System − bekannt unter dem Namen Jigsaw − eine gute Möglichkeit, Software-Architektur explizit auszudrücken. Die Java VM prüft nämlich während der gesamten Laufzeit die Kontrolle über die Sichtbarkeit des Codes über Modulgrenzen. Dies sollte dann in Zukunft auch nicht mehr ohne weiteres überwindbar sein, obwohl Oracle sich für die Einführungsphase von Java 9 darüber noch andere Gedanken macht. (https://jaxenter.de/java-9-kill-switch-interview-55850)