Anti-Muster, die Sie in Ihrem Code vermeiden sollten

Jeder Entwickler möchte strukturierten, einfach geplanten und gut kommentierten Code schreiben. Es gibt sogar eine Vielzahl von Designmustern, die uns klare Regeln geben und einen Rahmen, den wir berücksichtigen sollten.

Aber wir können immer noch Anti-Patterns in Software finden, die einige Zeit später oder zu schnell geschrieben wurde.

Ein harmloser grundlegender Hack zur schnellen Behebung eines Problems kann einen Präzedenzfall in Ihrer Codebasis schaffen. Es kann an mehreren Stellen kopiert werden und sich in ein Anti-Pattern verwandeln, das Sie ansprechen müssen.

Was ist ein Anti-Muster?

In der Software ist Anti-Pattern ein Begriff, der beschreibt, wie Sie wiederkehrende Probleme in Ihrem Code NICHT lösen können. Anti-Patterns gelten als schlechtes Software-Design und sind normalerweise ineffektive oder undurchsichtige Korrekturen.  

Sie fügen hinzu , im Allgemeinen auch als „technische Schulden“ - welcher Code ist Sie kommen müssen zurück und beheben richtig später.

Die sechs Anti-Muster, die ich in diesem Artikel diskutieren werde, sind Spaghetti-Code , Goldener Hammer , Bootsanker , Toter Code , Verbreitung des Codes und das Gott-Objekt .

Spaghetti-Code

Spaghetti Code ist das bekannteste Anti-Pattern. Es ist Code mit wenig bis null Struktur.

Nichts ist modularisiert. Es gibt zufällige Dateien in zufälligen Verzeichnissen. Der gesamte Fluss ist schwer zu verfolgen und ist völlig miteinander verwickelt (wie Spaghetti).

Normalerweise ist dies ein Problem, bei dem jemand den Ablauf seines Programms nicht sorgfältig durchdacht hat und gerade mit dem Codieren begonnen hat.

Was tut es?! Ich kann dem nicht folgen

image.png

Dies ist nicht nur ein Alptraum für die Wartung, sondern macht es nahezu unmöglich, neue Funktionen hinzuzufügen.

Sie werden ständig Dinge kaputt machen, den Umfang Ihrer Änderungen nicht verstehen oder genaue Schätzungen für Ihre Arbeit abgeben, da es unmöglich ist, die unzähligen Probleme vorherzusehen, die bei solchen Archäologien / Vermutungen auftreten.

Lesen Sie hier mehr über das Spaghetti Code Anti-Pattern.

Goldener Hammer

"Ich nehme an, es ist verlockend, wenn das einzige Werkzeug, das Sie haben, ein Hammer ist, alles so zu behandeln, als wäre es ein Nagel." Abraham Maslow

Stellen Sie sich ein Szenario mit mir vor: Ihr Entwicklerteam ist sehr, sehr kompetent in der brandneuen Hammer-Architektur. Es hat fantastisch für alle Ihre früheren Probleme funktioniert. Sie sind das weltweit führende Hammer-Architektur-Team.

Aber jetzt nutzt irgendwie immer alles diese Architektur. Eine Flachkopfschraube? Hammer. Kreuzschlitzschraube? Hammer. Benötigen Sie einen Inbusschlüssel? Nein, tust du nicht, hämmere es.

Sie beginnen mit einem architektonischen Ansatz, der nicht ganz Ihren Anforderungen entspricht, aber die Arbeit erledigt. Sie sind zu sehr auf ein Muster angewiesen und müssen das beste Werkzeug für den besten Job lernen.

Ihr gesamtes Programm könnte einen ernsthaften Leistungseinbruch erleiden, weil Sie versuchen, ein Quadrat in eine Kreisform zu rammen. Sie wissen, dass das Codieren und Ausführen eines Programms mit der Hammerarchitektur für dieses Problem doppelt so lange dauert, aber es ist einfacher und es ist das, womit Sie vertraut sind.

Es ist auch nicht sehr vorhersehbar. Verschiedene Sprachen haben gemeinsame Lösungen für die Probleme, mit denen sie konfrontiert sind, und ihre eigenen Standards. Sie können nicht jede einzelne Regel, die für Sie gut funktioniert hat, ohne Probleme in einer Sprache auf die nächste anwenden.

Vernachlässigen Sie nicht das konsequente Lernen in Ihrer Karriere. Wählen Sie die richtige Sprache für Ihr Problem. Denken Sie an die Architektur und verschieben Sie Ihre Komfortzone. Erforschen und untersuchen Sie neue Werkzeuge und neue Wege, um die Probleme anzugehen, mit denen Sie konfrontiert sind.

Hier können Sie mehr über das Golden Hammer Anti-Pattern lesen .

Bootsanker

Im Boat Anchor Anti-Pattern belassen Programmierer Code in der Codebasis, weil sie ihn möglicherweise später benötigen.

Sie haben etwas außerhalb der Spezifikation codiert und es wird noch nicht benötigt, aber sie sind sicher, dass sie es nächsten Monat tun werden. Sie wollen es also nicht löschen. Senden Sie es an die Produktion und später, wenn sie es brauchen, können sie es schnell zum Laufen bringen.

Dies führt jedoch zu Wartungs-Albträumen in der Codebasis, die den gesamten veralteten Code enthält. Das große Problem ist, dass es ihren Kollegen schwer fällt, herauszufinden, welcher Code veraltet ist und den Ablauf im Vergleich zum Code, der dies tut, nicht ändert.

Stellen Sie sich vor, Sie befinden sich in einem Hotfix und versuchen verzweifelt herauszufinden, was für das Senden der Kartendaten von Kunden an die API verantwortlich ist, um Geld von ihrer Bank abzuheben. Sie könnten Zeit damit verschwenden, veralteten Code zu lesen und zu debuggen, ohne zu bemerken, dass Sie nicht einmal an der richtigen Stelle in der Codebasis sind.

Das letzte Problem ist, dass veralteter Code Ihre Erstellungszeit verlängert und Sie möglicherweise funktionierenden und veralteten Code verwechseln. Sie könnten sogar versehentlich anfangen, es in der Produktion einzuschalten.

Jetzt können Sie wahrscheinlich sehen, warum es als Bootsanker-Anti-Pattern bezeichnet wird - es ist schwer zu tragen (fügt technische Schulden hinzu), tut aber nichts (im wahrsten Sinne des Wortes hat der Code keinen Zweck, er funktioniert nicht).

Hier können Sie mehr über das Anti-Pattern des Bootsankers lesen .

Toter Code

Mussten Sie sich jemals Code ansehen, der von jemandem geschrieben wurde, der nicht mehr in Ihrem Unternehmen arbeitet? Es gibt eine Funktion, die nicht so aussieht, als würde sie etwas tun. Aber es wird von überall gerufen! Sie fragen herum und niemand ist sich ganz sicher, was es tut, aber alle sind zu besorgt, um es zu löschen.

Manchmal kann man sehen, was es tut, aber der Kontext fehlt. Sie können den Fluss lesen und verstehen, aber warum? Es sieht nicht so aus, als müssten wir diesen Endpunkt mehr erreichen. Die Antwort ist für jeden Benutzer immer dieselbe Antwort.

This is commonly described as the Dead code anti-pattern. When you can't see what is "actual" code necessary to the flow and successful execution of your program, versus what was only needed 3 years ago, and not now.

This particular anti-pattern is more common in proof on concept or research code that ended up in production.

One time at a tech meet up I met a guy who had this exact problem. He had tons of dead code, which he knew was dead, and lots he suspected was dead. But he could not get permission from management to ever remove all the dead code.

He referred to his approach as Monkey testing, where he started to comment out and turn off things to see what blew up in production. Maybe a little too risky!

If you don't fancy Monkey testing your production app, try to frame technical debt to management as "technical risk" to better explain why you think it's so important to tidy up.

Or even write down everything your particular module/section does you want to re-write, and take an iterative approach to remove piece by piece the dead code. Checking every time you haven't broken anything.

You don't have to drop a huge rewrite with thousands of changes. But you will either understand why it's so crucial and document why it's needed, or delete the dead code as you desired.

You can read more here about the Dead code anti-pattern.

Proliferation of Code

Objects or modules regularly communicate with others. If you have a clean, modularised codebase you often will need to call into other separate modules and call new functions.

The Proliferation of Code anti-pattern is when you have objects in your codebase that only exist to invoke another more important object. Its purpose is only as a middleman.

This adds an unnecessary level of abstraction (adds something that you have to remember) and serves no purpose, other than to confuse people who need to understand the flow and execution of your codebase.

A simple fix here is to just remove it. Move the responsibility of invoking the object you really want to the calling object.

You can read more here about the Proliferation of Code anti-pattern.

God Object

If everywhere in your codebase needs access to one object, it might be a God object.

God objects do too much. They are responsible for the user id, the transaction id, the customer's first and last name, the total sum of the transaction, the item/s the user is purchasing...you get the picture.

It is sometimes called the Swiss Army Knife anti-pattern because you only really need it to cut some twine, but it also can be a nail file, saw, pair of tweezers, scissors, bottle opener and a cork screw too.

In this instance you need to separate out and modularise your code better.

Programmers often compare this problem to asking for a banana, but receiving a gorilla holding a banana. You got what you asked for, but more than what you need.

The SOLID principles explicitly discuss this in object orientated languages, to help us model our software better (if you don't know what the SOLID principles are, you can read this article).

The S in the acronym stands for Single Responsibility - every class/module/function should have responsibility over one part of the system, not multiple.

You can see this problem over and over again, how about the below interface?

interface Animal { numOfLegs: string; weight: number; engine: string; model: string; sound: string; claws: boolean; wingspan: string; customerId: string; } 

Can you see by even just briefly scanning this interface that the responsibility of this is far too broad, and needs refactoring? Whatever implements this has the potential to be a God object.

How about this?

 interface Animal { numOfLegs: string; weight: number; sound: string; claws: boolean; } interface Car { engine: string; model: string; } interface Bird { wingspan: string; } interface Transaction { customerId: string; } 

Interface segregation will keep your code clear about where the responsibilities lie, and stop forcing classes that only need wingspan to also implement the engine, customerId and model  and so on.

Sie können hier mehr über das Anti-Muster des Gott-Objekts lesen .

Fazit

In jeder großen Codebasis besteht ein konstantes Gleichgewicht zwischen der Verwaltung der technischen Schulden, dem Beginn der Neuentwicklung und der Verwaltung einer Reihe von Fehlern für Ihr Produkt.

Ich hoffe, dieser Artikel hat Ihnen ein Auge für das Erkennen gegeben, wenn Sie das Kaninchenloch eines Anti-Musters hinuntergehen, und einige Werkzeuge, um es sauber zu lösen.

Ich teile mein Schreiben auf Twitter, wenn Ihnen dieser Artikel gefallen hat und Sie mehr sehen möchten.