Gibt es ein Antimuster zur Beschreibung dieser Codierungsmethode? [geschlossen]

26

Ich habe eine Codebasis, in der der Programmierer dazu neigte, Dinge in Bereichen zusammenzufassen, die keinen Sinn ergeben. Angenommen, Sie haben ein Fehlerprotokoll, über das Sie sich anmelden können

ErrorLog.Log(ex, "friendly message");

Er fügte verschiedene andere Mittel hinzu, um genau dieselbe Aufgabe zu erfüllen. Z.B

SomeClass.Log(ex, "friendly message");

Was sich einfach umdreht und die erste Methode aufruft. Dies erhöht die Komplexität ohne zusätzlichen Nutzen. Gibt es ein Anti-Pattern, um dies zu beschreiben?

P. Brian Mackey
quelle
36
"Bad Coding" deckt es ab;)
Oded
12
Hängt davon ab. Handelt es sich um einen Wrapper für eine Protokollbibliothek? Wenn es jemals die Chance gab, dass es getauscht werden könnte, ist dies tatsächlich eine gute Übung ...
Rig
3
@lortabac: Das Problem mit "Baklava Code" ist, dass es sich gut und lecker anhört und daher wünschenswert ist.
FrustratedWithFormsDesigner
10
Was sagt dieser Programmierer, wenn Sie sie hinzufügen? Warum fügen sie diese Methoden hinzu? Das Verstehen ihrer Argumentation sollte es einfacher machen, sie zu erziehen.
Keith
3
Klingt nach einer Indirektionsebene , die gut sein kann, wenn Sie die Kopplung zwischen zwei Klassen vermeiden möchten, wie @Rig hervorhob. Vielleicht war es nur ein Programmierer leidet patternitis - einfach einige Muster versuchen , ein Problem zu lösen , das nicht da ist, zu verletzen KISS.
Fuhrmanator

Antworten:

54

Es lohnt sich nur, eine schlechte Codierungsgewohnheit als Antipattern zu bezeichnen, wenn sie einigermaßen verbreitet ist.

Den Rest nennen wir einfach "Müllcode" ...


Wenn ich einen Namen für diese schlechte Angewohnheit vorschlagen würde, wäre es "Obsessive Abstraktionsstörung" :-)

Stephen C
quelle
9
Ich habe immer "Indirection Hell" verwendet.
Dan Neely
27

Nein, es ist kein Anti-Pattern, aber ich würde die folgenden Probleme ansprechen.

Verstoß gegen das Prinzip der Einzelverantwortung

SRP sagt, dass eine Klasse einen Grund haben sollte, sich zu ändern. Das Hinzufügen einer Protokollierungsmethode bedeutet, dass sich auch die Klasse ändern muss, wenn die Protokollierungslogik geändert werden soll.

Verletzung einer is-aBeziehung

Basisklassen sind keine Toolboxes, in denen Sie verschiedene Komfortmethoden hinzufügen können.

Auf diese Weise werden alle geerbten Klassen effektiv mit den Implementierungen der Basisklasse gekoppelt.

Vergleichen Sie das mit der Zusammensetzung.

jgauffin
quelle
1
"Single Responsibility Problem"? SRP? Vielleicht wollten Sie Single Responsibility Principle schreiben? Verbinden Sie einfach die beiden hier. :)
zxcdw
8

Nicht, dass dies akzeptabel wäre, aber dies könnte nur eine unvollendete Umgestaltung sein. Vielleicht hatte SomeClass.log () eine eigene Logik und wurde zuerst implementiert. Und später wurde ihnen klar, dass sie ErrorLog.Log () verwenden sollten. Anstatt also 100 Stellen zu ändern, an denen SomeClass.Log () aufgerufen wird, haben sie nur an ErrorLog.Log () delegiert. Persönlich würde ich alle Verweise auf ErrorLog.Log () ändern oder zumindest SomeClass.log () kommentieren, um zu sagen, warum es so delegiert, wie es tut.

Nur etwas zu beachten.

Heath Lilley
quelle
7

Der Begriff "Lasagne Code" kommt mir in den Sinn, obwohl er anscheinend verschiedene Dinge für verschiedene Menschen bedeutet . Meine Interpretation war immer "geschichtet, um geschichtet zu werden".

dasblinkenlight
quelle
3
Ich habe auch "Onion Code" gehört, um dasselbe zu beschreiben.
Justin Niessner
4

Ich bin mir nicht sicher, ob dies als Verstoß gegen das Prinzip der Einzelverantwortung zu bezeichnen ist, da bei einer Änderung der ErrorLog-Methodensignatur (der von SomeClass aufgerufenen Methode) jeder Clientcode, der diese Methode aufruft, fehlschlägt.

Es gibt offensichtlich eine Möglichkeit, die Vererbung zu verwenden (oder Klassen zu erstellen, die protokolliert werden müssen, indem eine Protokollierungsschnittstelle implementiert wird).


quelle
Immer noch schlechte Praxis, weil: 1) es unwahrscheinlich ist, dass sich etwas ändert, 2) wenn es sich ändert, sie einfach eine Wrapper-Klasse mit demselben Namen erstellen und die Importe ändern können.
Kevin Cline
2
+1. Und hier ist "Onkel Bob" (Robert Martin) , der dafür plädiert, Abhängigkeiten in einer begrenzten Anzahl von Modulen zu zentralisieren, anstatt sie durch den Code zu streuen.
MarkJ
3

Oder wir könnten dies als einen "lehrbaren Moment" ansehen :)

Ihr Entwickler ist möglicherweise auf halbem Weg zu einer guten Idee. Angenommen, Sie möchten die Anforderung haben, dass alle Ihre Geschäftsobjekte in der Lage sind, intelligent zu protokollieren. Sie könnten definieren:

   public interface IBusinessObjectLogger
   {
       void Log(Exception ex, string logMessage)
   }

Jetzt können Sie innerhalb Ihrer Objekte das ErrorLog-Objekt verwenden, um die Protokollierung tatsächlich durchzuführen, während SomeClass-Code der Protokollnachricht einen objektspezifischen Wert hinzufügt. Anschließend können Sie Ihre Protokollierungs-APIs erweitern, um dateibasierte, datenbankbasierte oder nachrichtenbasierte Protokollierungsfunktionen zu implementieren, ohne Ihre Geschäftsobjekte zu berühren.

cdkMoose
quelle
3

Ich bin mir nicht sicher, ob das automatisch böse ist.

Wenn Sie SomeClass.Log aufrufen, ist es mit Sicherheit böse, aber wenn Log nur von WITHIN SomeClass verwendet wird, wird die Kopplung abgeschnitten, und ich würde es als akzeptabel bezeichnen.

Loren Pechtel
quelle
2

Dies ist in bestimmten Codierungsstilen tatsächlich ziemlich häufig, und die Grundlagen der Gedankenrichtung sind an sich kein Anti-Pattern.

Es ist sehr wahrscheinlich das Ergebnis von jemandem, der notwendigerweise ohne Kenntnis der breiteren Codebasis codiert: "OK, dieser Code muss einen Fehler protokollieren, aber diese Funktion ist nicht der primäre Zweck des Codes. Daher benötige ich eine Methode / Klasse, die dies erledigt für mich". Das ist eine gute Denkweise. Aber ohne zu wissen, dass ErrorLog existiert, haben sie SomeClass erstellt. Sie fanden dann zu einem späteren Zeitpunkt ErrorLog, und anstatt alle Verwendungen der von ihnen eingegebenen Methode zu ersetzen, führten sie ihren Methodenaufruf ErrorLog aus. Hier wird das zum Problem.

KeithS
quelle
2

Zufällige Komplexität ist Komplexität, die in Computerprogrammen oder deren Entwicklungsprozessen auftritt und für das zu lösende Problem nicht wesentlich ist. Während wesentliche Komplexität inhärent und unvermeidbar ist, wird zufällige Komplexität durch den Ansatz verursacht, der zur Lösung des Problems gewählt wurde.

http://en.wikipedia.org/wiki/Accidental_complexity

JoelFan
quelle
1

Dies kann ein Missbrauch / Missverständnis des Fassadenmusters sein . Ich habe ähnliche Dinge in einer Codebasis gesehen, mit der ich gearbeitet habe. Die Entwickler machten eine Phase durch, in der sie verrückt nach Designmustern waren, ohne die übergeordneten Prinzipien des OO-Designs zu verstehen.

Ein Missbrauch des Fassadenmusters führt zu einer Unschärfe der Abstraktionsebenen in den Anwendungsebenen.

Kazark
quelle
1

Dieser Programmierer verpackt Code so, dass er nicht direkt vom Protokollierungsmodul abhängt. Ohne spezifischere Informationen ist es nicht möglich, ein spezifischeres Muster anzugeben. (Dass diese Wrapper nicht nützlich sind, ist Ihrer Meinung nach unmöglich, ohne weitere Informationen zuzustimmen oder abzulehnen.)

Mögliche Muster hierfür sind Proxy , Delegate , Decorator , Composite oder andere, die mit dem Umbrechen, Ausblenden oder Verteilen von Anrufen zu tun haben. Es kann eines dieser Dinge in einem unvollständigen Entwicklungszustand sein.

Kaz
quelle
0

Ich könnte mir vorstellen, dass es ein kultureller Unterschied ist. Vielleicht gibt es einen guten Grund für doppelte Funktionalität in dieser speziellen Codebasis. Ich könnte mir die Leichtigkeit des Schreibens als einen solchen Grund vorstellen. Die Python - Programmierer in mir würde immer noch sagen , dass es schlecht ist, da „ Es one-- sein sollte und vorzugsweise nur eine --obvious Weg , es zu tun. “, Aber einige Perl Jungs vielleicht die Tatsache gewöhnt, dass " Es gibt mehr als eine Weg, es zu tun ".

Bengt
quelle
1
Einfache Initiale Schreiben ist nicht ein guter Grund für die Vervielfältigung. Fehlerhafter Code ist möglicherweise einfacher, wenn Sie ihn zum ersten Mal schreiben, aber das macht es auf lange Sicht nicht einfacher, Code zu schreiben. Was macht der Neue mit der duplizierten Funktionalität? Welche Methode nennt er? Er verschwendet Zeit damit, sie aufzusuchen und zu lesen, nur um herauszufinden, dass sie dasselbe tun.
Kazark
Vielleicht war dieser Code ursprünglich als Prototyp gedacht, der dann (ab) als Inkrement verwendet wurde. In diesem Fall wäre die Optimierung für das erste Schreiben meines Erachtens gültig gewesen.
Bengt