Geheimer Handshake Anti-Pattern

8

Ich bin gerade auf ein Muster gestoßen, das ich schon einmal gesehen habe, und wollte dazu Meinungen bekommen. Der betreffende Code beinhaltet eine Schnittstelle wie folgt:

%Vor%

Und die erwartete Verwendung ist wie folgt:

%Vor%

Dafür gibt es Gründe. Die setText (...) und getOccurances (...) sind da, weil es nach der gleichen teuren Analyse der Daten mehrere Abfragen geben kann, die aber zu einer Ergebnisklasse refaktoriert werden können.

Warum ich denke, das ist so schlecht: Die Implementierung speichert den Zustand in einer Weise, die von der Schnittstelle nicht klar angezeigt wird. Ich habe auch etwas Ähnliches gesehen, das eine Schnittstelle betrifft, die "prepareResult" und dann "getResult" aufrufen muss. Jetzt kann ich an gut entworfenen Code denken, der einige dieser Eigenschaften einsetzt. Die Hadoop Mapper-Oberfläche erweitert JobConfigurable und Closeable, aber ich sehe einen großen Unterschied, weil es ein Framework ist, das Benutzercode verwendet, der diese Schnittstellen implementiert, im Gegensatz zu einem Service, der mehrere Implementierungen haben kann. Ich nehme an, dass alles, was mit der Aufnahme einer "nahen" Methode zu tun hat, die aufgerufen werden muss, gerechtfertigt ist, da es keinen anderen vernünftigen Weg gibt, dies zu tun. In einigen Fällen, wie JDBC, ist dies eine Konsequenz einer undichten Abstraktion, aber in den beiden Code-Stücken, an die ich denke, ist es ziemlich klar, dass Programmierer hastig eine Schnittstelle zu einer Spaghetti-Code-Klasse hinzufügen, um sie zu bereinigen.

Meine Fragen sind:

  1. Stimmen alle zu, dass dies eine schlecht gestaltete Schnittstelle ist?
  2. Ist das ein beschriebenes Anti-Pattern?
  3. Gehört diese Art von Initialisierung jemals zu einer Schnittstelle?
  4. Scheint das nur falsch für mich, weil ich eine Präferenz für funktionalen Stil und Unveränderlichkeit habe?

Wenn das üblich genug ist, um einen Namen zu verdienen, empfehle ich das "Secret Handshake" Anti-Pattern für eine Schnittstelle, die Sie dazu zwingt, mehrere Methoden in einer bestimmten Reihenfolge aufzurufen, wenn die Schnittstelle nicht von Natur aus stateful ist (wie eine Collection) .

    
Kevin Peterson 27.04.2009, 08:21
quelle

5 Antworten

17

Ja, es ist ein Anti-Pattern: Sequentielle Kopplung .

Ich würde in Options umgestalten - an die Factory übergeben und Results von einer analyseText() Methode zurückgegeben.

    
Douglas Leeder 27.04.2009, 09:18
quelle
3
  1. Ich würde erwarten, dass die AnalyzerFactory die notwendigen Parameter erhält und die Konstruktion selbst durchführt; sonst, was genau macht es?
  2. Nicht sicher, ob es einen Namen hat, aber es scheint wie es sollte:)
  3. Ja, gelegentlich ist es bequem (und auf der richtigen Abstraktionsebene), dass Sie in Ihrer Oberfläche Einstellungen vornehmen und erwarten, dass Klassen sie aufrufen. Ich würde vorschlagen, dass eine ausführliche Dokumentation dieser Tatsache erfordert
  4. Nicht wirklich, nein. Eine Präferenz für Unveränderlichkeit ist sicherlich eine gute Sache, und Setter / Bean-basiertes Design kann manchmal die "richtige" Wahl sein, aber Ihr gegebenes Beispiel nimmt es zu weit.
GaryF 27.04.2009 08:35
quelle
3

Ich bin mir nicht sicher, ob es ein beschriebenes Anti-Pattern ist, aber ich stimme völlig zu, dass dies eine schlecht gestaltete Oberfläche ist. Es lässt zu viele Möglichkeiten für Fehler und verletzt mindestens ein Schlüsselprinzip: Machen Sie Ihre API schwer zu missbrauchen.

Neben Missbrauch kann diese API auch zu schwer zu debuggenden Fehlern führen, wenn mehrere Threads dieselbe Instanz verwenden.

Joshua Bloch hat tatsächlich eine ausgezeichnete Präsentation (36m16s und 40m30s) über API-Design und er spricht dies als eine der Eigenschaften einer schlecht gestalteten API.

    
Ronald Wildenberg 27.04.2009 08:36
quelle
0

Ich kann hier nichts Schlechtes sehen. setText() bereitet die Bühne vor; Danach haben Sie einen oder mehrere Aufrufe von getOccurances() . Da setText() so teuer ist, kann ich mir keinen anderen Weg vorstellen.

getOccurances(text, query) würde den "geheimen Handshake" zu enormen Performance-Kosten beheben. Sie könnten versuchen, Text in getOccurances() zwischenzuspeichern und nur Ihre internen Caches zu aktualisieren, wenn sich der Text ändert, aber das sieht mehr und mehr nach einem OO-Prinzip aus. Wenn eine Regel keinen Sinn ergibt, wenden Sie sie nicht an. Softwareentwickler haben ein Gehirn aus einem Grund.

    
Aaron Digulla 27.04.2009 09:11
quelle
0

Eine mögliche Lösung - Fluent chaning verwenden. Das vermeidet eine Klasse, die Methoden enthält, die in einer bestimmten Reihenfolge aufgerufen werden müssen. Es ähnelt stark dem Builder-Muster, das dafür sorgt, dass Sie keine Objekte lesen, die sich noch in der Mitte befinden.

    
Sridhar-Sarnobat 23.08.2017 23:44
quelle

Tags und Links