Meistens sind wir zufrieden, dass unser Code die richtige Qualität hat, wenn wir es irgendwie schaffen, dass die Tools zur statischen Codeanalyse (SCA) wie Checkstyle, PMD usw. weniger schwere Verstöße melden. Wenn wir zum Beispiel feststellen, dass eine Klasse sehr groß ist, teilen wir sie einfach in zwei oder mehr Klassen auf, um den Verstoß zu beseitigen. Das Tool ist zufrieden und wir sind es auch, und meistens ist das das Ende der Geschichte.Häufig ist ein SCA-Verstoß jedoch erst der Anfang der Geschichte. Wenn Sie anfangen, die Frage "Warum" mit jedem gefundenen SCA-Verstoß zu verbinden, dann kommen die wahren Gründe zum Vorschein.Das ist ähnlich wie die Art und Weise, wie wir Hindernisse in einem Scrum-Projekt beseitigen. Die Hindernisse stellen selten isolierte Fälle von Ineffizienz dar. Meistens sind sie vielmehr Teil eines größeren Problems. Der Weg, ein Hindernis zu beseitigen, besteht darin, es zu beheben, damit das Team effektiv arbeiten kann, und dann die Ursache zu untersuchen, die das Hindernis verursacht hat, damit die Hauptursache behoben werden kann. Dies wird als "Bottom-up Process Re-Engineering" bezeichnet.
In ähnlicher Weise besteht die Lösung eines SCA-Verstoßes darin, ihn zu beseitigen, damit der Code sauber und gut aussieht, und dann nach der wahren Ursache zu suchen.
Ich habe dies aus erster Hand erfahren, als ich ein Audit für ein großes System durchführte, das online von Millionen von Menschen genutzt wird. Während der Analyse schlug mein Co-Auditor vor, dass wir nach Hotspots suchen sollten, die von den SCA-Tools hervorgehoben werden. Dann sollten wir an diesen Stellen in den Code eintauchen, um größere Probleme zu finden. Damals war ich skeptisch, ob dieser Ansatz funktionieren würde, aber jetzt glaube ich fest an seine Philosophie.Die SCA-Tools leisten hervorragende Arbeit, wenn es darum geht, auf die Hot Spots hinzuweisen. Sie können entweder die Hot Spots ausbessern, damit das SCA-Tool zufrieden ist, oder Sie können sich mit den größeren Problemen befassen, um die Grundursache des Problems zu beseitigen.Ich werde einige Beispiele aus meiner Prüfung anführen, um es deutlicher zu machen. Ich möchte Sie warnen, dass diese Probleme zu einfach für eine tiefere Analyse aussehen, aber glauben Sie mir, wenn Sie die Analyse durchführen, kommen Sie auf einige unerwartete, nachdenklich stimmende Erkenntnisse. Und natürlich sind dies nur ein paar Beispiele zur Veranschaulichung, Sie könnten dies auf idealerweise jeden Verstoß anwenden, den Sie erhalten.
1.Size violation: Wir haben festgestellt, dass die Anwendung Servlets enthielt, die mehr als 3000 Zeilen lang waren und deren Methoden jeweils mehr als 800 Zeilen umfassten. Eine schnelle Lösung für dieses Problem wäre gewesen, die Methodengröße zu reduzieren, indem man die Methoden aufteilt und einige Methoden aus der Klasse in eine Hilfsklasse verschiebt, so dass die Verstöße gegen die Klassengröße und die Methodengröße behoben sind.
Als wir jedoch tiefer schauten, um die Frage "Warum haben die Servlets so viele Zeilen und so große Methoden?" zu beantworten, stellten wir fest, dass die gesamte Geschäftslogik in den Servlets vorhanden war. Es gab einen größeren Verstoß gegen das Prinzip der einzigen Verantwortung, da die gesamte Logik in einer einzigen Klasse enthalten war. Die Präsentationslogik, die Geschäftslogik und die Datenzugriffslogik waren alle in einer Klasse untergebracht, was zu einem anfälligen Design führte, das sich nur schwer ändern lässt, ohne dass es kaputt geht. Es gab keine Schichtung und keine Trennung von Belangen.
Das Design des Systems war hier der Schuldige und wahrscheinlich hat keiner der Entwickler oder der Architekt des Projekts das so empfunden.
2.Methoden mit einer großen Anzahl von Parametern: Ein schneller Weg, dieses Problem zu lösen und das SCA-Tool glücklich zu machen, wäre die Einführung eines Objekts und die Befüllung des Objekts mit den erforderlichen Parametern.
Als wir jedoch tiefer in das System eintauchten, stellten wir fest, dass das System keine Abstraktion aufwies. Es gab auch keine Domänenobjekte in dem System. Wenn Daten zwischen Methodenaufrufen übergeben werden mussten, wurden sie alle als primitive Daten, meist Strings, übergeben. Der Schwerpunkt lag nicht auf einem domänenorientierten Design. Die Methoden waren mit jedem zusätzlichen Parameter überladen, der in einer anderen Situation benötigt wurde, was darauf hindeutete, dass das System offen für Änderungen und geschlossen für Erweiterungen war. Für jede kleine Änderung musste eine neue Methode geschrieben werden. Dies verstieß gegen das Open-Close-Prinzip.
Auch hier war das Design der Schuldige.
3.Große zyklomatische Komplexität und NPath: Wir waren verblüfft, als wir für einige Methoden CC-Zahlen > 50 und NPath-Zahlen von > 1,7 Millionen sahen.
Als wir tiefer eintauchten, stellten wir fest, dass die fraglichen Methoden eine Menge verschachtelter if..else-Logik enthielten. So weit so gut, aber was ist der Grund für diese verschachtelte Logik? Wir fanden heraus, dass die Methode die gesamte Versandlogik für die Anfrage enthielt. Wenn die Anfrage diese Attribute hat, tun Sie dies, sonst tun Sie das und so weiter. Dies erklärte auch, warum das System eine geringe Codeabdeckung durch Unit-Tests aufwies. Die Erstellung eines Unit-Tests zum Testen von 1,7 Millionen möglichen Pfaden würde Wochen, wenn nicht Monate dauern. Offensichtlich hatte niemand daran gedacht, eines der vielen leicht verfügbaren MVC-Frameworks einzuführen. Als wir das Team befragten, warum sie kein MVC-Framework einsetzten, wurde uns gesagt, dass sie es anfangs nicht für nötig hielten, weil das System zu klein war. Als es zu wachsen begann, hatten sie nie die Zeit, ein Refactoring durchzuführen und ein Framework einzuführen.
Dies kann verschiedene Ursachen haben, wie z.B. mangelnde Kommunikation zwischen Kunde und Anbieter über realistische Zeitpläne, Refactoring als Teil des Standardentwicklungsprozesses, mangelndes Interesse des Teams am Projekt, mangelndes Interesse am Erreichen der richtigen Qualität und Konzentration auf die Erledigung der Arbeit.
4.Fehlende geschweifte Klammern und falsche Benennung von Variablen: Dies ist wahrscheinlich einer der Verstöße, der von einem SCA-Tool sofort gemeldet wird und leicht zu korrigieren ist.
Bei näherer Betrachtung stellten wir jedoch fest, dass bestimmte Module der Anwendung im Vergleich zu anderen große Verstöße meldeten. Als wir zwei Module mit der höchsten Anzahl von Verstößen verglichen, stellten wir fest, dass beide sehr unterschiedliche Benennungsstrategien verwendeten. Weitere Untersuchungen ergaben, dass bei dem Projekt keine Kodierungsstandards verwendet wurden. Jedes Modul und jeder Entwickler war frei, eine Nomenklatur zu verwenden, die seinem Geschmack entsprach. Es gab keine konzeptionelle Integrität und keine Einheitlichkeit, nach der die gesamte Software aufgebaut war.Ungeeignete Softwareentwicklungsprozesse und ein Mangel an koordinierter Kommunikation zwischen den Teams waren die offensichtlichen Schuldigen in diesem Fall.5. Eine große Anzahl von nicht verwendeten Importen, Variablen und Methoden: Auch hier handelt es sich um ein Problem, das leicht zu beheben ist.Als wir die Entwickler jedoch nach dem Grund für den ungenutzten Code befragten, wurde uns gesagt, dass sie den ungenutzten Code nie entfernen, um ihn nicht eines Tages zu benötigen. Das würde ihnen in Zukunft Zeit sparen.Offensichtlich hat niemand an die Zeit gedacht, die verloren geht, wenn wir uns durch tonnenweise unbenutzten Code scrollen müssen, und wahrscheinlich wurden sie auch nie über das Prinzip von YAGNI aufgeklärt.Auch hier waren ein unsachgemäßer Entwicklungsprozess und mangelnde Aufklärung der Entwickler die Schuldigen.Sie werden mir zustimmen, dass all diese Verstöße sehr geringfügig waren und leicht hätten behoben werden können, ohne dass eine tiefere Analyse erforderlich gewesen wäre. Wenn Sie jedoch versuchen, tiefer zu graben, dann deuten die meisten von ihnen auf größere Probleme hin, die einen gezielteren Ansatz zur Behebung erfordern. Wir haben gesehen, dass relativ kleine Probleme, die von den SCA-Tools gemeldet wurden, auf größere Probleme zurückzuführen waren, wie z.B. unsachgemäßes Design, substandardisierte Entwicklungsprozesse, mangelnde Kommunikation und fehlende Schulung des Entwicklungsteams im Hinblick auf eine effektive Softwareentwicklung.
Eine Ursachenanalyse für kleine Verstöße mag daher übertrieben erscheinen, aber oft ist der kleine Verstoß nur die Spitze des Eisbergs!
Wenn Sie das nächste Mal einen gemeldeten SCA-Tool-Verstoß lösen, halten Sie einen Moment inne und fragen Sie sich: "Warum habe ich diesen Verstoß überhaupt?"