{"id":67,"date":"2015-01-09T21:06:17","date_gmt":"2015-01-09T21:06:17","guid":{"rendered":"http:\/\/techblog.auchmonoabspielbar.de\/?p=67"},"modified":"2015-01-09T21:06:17","modified_gmt":"2015-01-09T21:06:17","slug":"programmier-un-tugenden-die-man-vermeiden-sollte","status":"publish","type":"post","link":"http:\/\/techblog.auchmonoabspielbar.de\/?p=67","title":{"rendered":"Programmier-Un-tugenden, die man vermeiden sollte"},"content":{"rendered":"<p>Gestern ist mir mal wieder unsch\u00f6ner Programm-Code \u00fcber den Weg gelaufen. Das hat mich dazu animiert, mal die h\u00e4ufigsten Fehler aufzulisten, die ich immer mal wieder sehe und \u00fcber die ich mich dauerhaft \u00e4rgern kann.<\/p>\n<p>Dabei geht es mir noch nicht mal um irgendwelche abstrakten Programmiermodelle oder best practices im Architekturbereich. Es geht um kurze, allt\u00e4glich Codest\u00fccke, die man eigentlich nicht falsch machen kann. Und doch wird es gerne falsch gemacht. Es geht auch nicht um Syntaxfehler, die filtert der Compiler raus. Sondern einfach nur um schlechten Code, der irgendwie funktioniert.<\/p>\n<p><strong>1. Unklare Vorstellungen \u00fcber boolsche Werte<\/strong><\/p>\n<p>Wenn ich solche Abschnitte sehe, stellen sich mir die Nackenhaare auf:<\/p>\n<pre>boolean isEnabled = myButton.getEnabled();\r\n\r\nif (isEnabled == true) { ...<\/pre>\n<p>Die Variable isEnabled enth\u00e4lt einen boolschen Wert, die IF-Entscheidung erwartet einen. Warum dann noch diesen zus\u00e4tzlichen Vergleich dazu packen. Damit sich der Compiler auch wirklich sicher ist, dass der Wert true ist? Und dann k\u00f6nnte man konsequenterweise doch auch &#8222;if ((isEnabled == true) != false)&#8220; schreiben.<\/p>\n<p>Mir signalisiert so eine Vorgehensweise, dass der Entwickler nur eine vage Vorstellung von boolschen Werten und ihrer Verwendung besitzt.<\/p>\n<p><strong>2. \u00dcberfl\u00fcssige Kontrollstrukturen<\/strong><\/p>\n<p>Dieses Beispiel geht in die gleiche Richtung wie Beispiel 1.<\/p>\n<pre>boolean isEnabled = myButton.getEnabled();\r\n\r\nif (isEnabled) {\r\n\r\n  otherButton.setEnabled(true);\r\n\r\n} else {\r\n\r\n  otherButton.setEnabled(false);\r\n\r\n}<\/pre>\n<p>Hier wird ohne nachvollziehbaren Grund eine komplette Kontrollstruktur aufgebaut. Dabei kann ich mich gar nicht \u00fcber die verschenken Nanosekunden \u00e4rgern. Aber jeder andere Entwickler erwartet hier, dass etwas passiert, was schwergewichtiger ist als eine einfache Zuweisung: &#8222;otherButton.setEnabled(isEnabled)&#8220;.<\/p>\n<p>Leider kommt dieser Fehler in der Praxis immer wieder vor. Auch hier liegt vermutlich oft einfach ein Defizit im Bereich &#8222;mal dar\u00fcber nachdenken, was ich gerade mache&#8220; vor.<\/p>\n<p><strong>3. Verdrehte Ausdr\u00fccke<\/strong><\/p>\n<p>Eines meiner Lieblingsaufreger, besonders gern von alten C Programmierern gemacht:<\/p>\n<pre>if ( 7 == anzahlWochentage) ...<\/pre>\n<p>Das liest sich einfach schlecht &#8211; Obi-Wan Kenobi Grammatik. Wenn man den Ausdruck umgangssprachlich formulieren w\u00fcrde, w\u00fcrde man sagen &#8222;Wenn die Anzahl der Wochentage gleich 7 ist&#8220; und keinenfalls &#8222;Wenn 7 die Anzahl der Wochentage ist&#8220;. Auch wenn der Inhalt der gleiche ist, stolpert man \u00fcber die falsche Reihenfolge, der Gedankenfluss wird gest\u00f6rt, die Aufmerksamkeit ist beeintr\u00e4chtigt.<\/p>\n<p>Die Herkunft dieses Anti-Patterns ist klar. Uralte C Compiler (\u00e4lter als 30 Jahre), haben die Anwender leichtf\u00fc\u00dfig in Fehler der Art &#8222;if (anzahlWochentage = 7)&#8230;&#8220; laufen lassen. Durch das vergessene zweite Gleichheitszeichen wird aus dem Vergleich eine Zuweisung. In der umgedrehten Schreibweise f\u00fchrt das zu einem Compilerfehler, da ein konstanter Wert nicht als Left-Value verwendet werden kann. Aber auch vor 30 Jahren gab es schon &#8222;lint&#8220; f\u00fcr solche Probleme. Alle modernen Compiler werfen hier deutliche Warnings aus, so dass man diesen Fehler eigentlich nicht mehr machen kann.<\/p>\n<p>Ein Entwickler, der sich dieser Schreibweise bem\u00e4chtigt, l\u00f6st bei mir schnell den Verdacht aus, dass er sich nicht um seine Warnings k\u00fcmmert. Oder, dass er so viele Warnings hat, dass er sie gar nicht mehr kontrollieren kann. Beides ist schlecht, der Programmierer bewegt sich Haarscharf an der Grenze zum Chaos.<\/p>\n<p><strong>4. Magic Numbers<\/strong><\/p>\n<p>Die Verwendung von symbolischen Konstanten statt Zahlen im Quellcode ist mittlerweile fast \u00fcberall Standard. In vielen Firmen gibt es Style Guides, die die Verwendung von Magic Numbers ausdr\u00fccklich verbieten.<\/p>\n<p>Der Nutzen von Konstanten liegt auf der Hand. Wenn ich f\u00fcnf Produktgruppen habe und im Programmcode alle Schleifen mit der Ziffer 5 laufen lasse, habe ich bei einer Erweiterung auf 6 Gruppen massiven Aufwand. Man kann ja nicht einfach per Suchen und Ersetzen alle 5 gegen eine 6 austauschen. Statt dessen muss man sich jede Verwendung genau darauf hin ansehen, ob die Zahl der Gruppen gemeint ist. Zudem gibt es weitere Verwendungen, der Index der letzten Gruppe betr\u00e4gt 4 und nicht 5. Darauf muss man also auch achten.<\/p>\n<p>\u00dcbel wird es, wenn ein Programmierer zwar den Wortlaut der Regel befolgt aber den Sinn nicht verstanden hat (oder nicht verstehen will). Dann kommen solche Konstruktionen vor:<\/p>\n<pre>const FIVE = 5;\r\n\r\n...\r\n\r\nfor (var group = 0; group &lt; FIVE; group++) ...<\/pre>\n<p>Der Wortlaut der Regel wurde befolgt, im Programmcode selber gibt es keine Magic Numbers. Aber das Ziel wurde verfehlt. Ich sehe der FIVE in der for Schleife nicht an, was f\u00fcr einen Zweck sie hat. Besonders \u00fcbel wird es, wenn sich die Zahl der Gruppen auf 6 erh\u00f6ht:<\/p>\n<pre>const FIVE = 6;<\/pre>\n<p>So eine Vorgehensweise kann man nur begrenzt mit Unf\u00e4higkeit begr\u00fcnden. Das grenzt schon an Sabotage.<\/p>\n<p><strong>5. Unsinnige Kommentare<\/strong><\/p>\n<p>Vern\u00fcnftige Kommentare zu erstellen, ist nicht unbedingt einfach. In manchen Betrieben gibt es eine Festlegung, was kommentiert werden muss. Bei uns ist es z.B. so, dass alle public Methoden mit einem JavaDoc Header versehen werden m\u00fcssen. Kommentare innerhalb einer Funktion sind aber kaum \u00fcber einen Style Guide definierbar. Wenn man dann einfach einen bestimmten Prozentsatz von Kommentarzeilen fordert, entstehen solche Konstruktionen:<\/p>\n<pre>customers++;\u00a0 \/\/ customer wird eins hochgez\u00e4hlt<\/pre>\n<p>Ein unglaublich bl\u00f6der Kommentar, der genau das wiederholt, was der Programmcode ganz offensichtlich ausf\u00fchrt. Solche Kommentare sind nicht nur nutzlos. Sie sind sogar sch\u00e4dlich. Sp\u00e4testens dann, wenn sich der Programmcode mal \u00e4ndert und der nutzlose Kommentar nicht angepasst wird. Dann habe ich einen Widerspruch im Quellcode der schwere Irrt\u00fcmer ausl\u00f6sen kann.<\/p>\n<p>Kommentare sollten im Normalfall NICHT beschreiben, was passiert. Das wird durch den Programmcode am Besten beschrieben. Und wenn der schwer verst\u00e4ndlich ist, dann sollte man sich lieber Gedanken \u00fcber eine bessere Schreibweise statt \u00fcber einen Kommentar machen.<\/p>\n<p>Kommentare sollten beschreiben WARUM etwas passiert. Denn dieser Teil ist nicht aus dem Code abzuleiten. Vielleicht aus dem Kontext. Oder aus dem Pflichtenheft (liegt das f\u00fcnf Jahre sp\u00e4ter noch in einer aktualisierten Form vor?).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gestern ist mir mal wieder unsch\u00f6ner Programm-Code \u00fcber den Weg gelaufen. Das hat mich dazu animiert, mal die h\u00e4ufigsten Fehler aufzulisten, die ich immer mal wieder sehe und \u00fcber die ich mich dauerhaft \u00e4rgern kann. Dabei geht es mir noch nicht mal um irgendwelche abstrakten Programmiermodelle oder best practices im Architekturbereich. Es geht um kurze, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,2],"tags":[],"class_list":["post-67","post","type-post","status-publish","format-standard","hentry","category-menschen","category-software"],"_links":{"self":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=67"}],"version-history":[{"count":1,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":68,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=\/wp\/v2\/posts\/67\/revisions\/68"}],"wp:attachment":[{"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/techblog.auchmonoabspielbar.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}