Frage

Ich habe gerade über ein Muster komme ich vorher gesehen habe, und wollte Meinungen zu ihm bekommen. Der betreffende Code beinhaltet eine Schnittstelle wie folgt:

public interface MyCrazyAnalyzer {
    public void setOptions(AnalyzerOptions options);
    public void setText(String text);
    public void initialize();
    public int getOccurances(String query);
}

Und die erwartete Nutzung ist wie folgt:

MyCrazyAnalyzer crazy = AnalyzerFactory.getAnalyzer();
crazy.setOptions(true);
crazy.initialize();
Map<String, Integer> results = new HashMap<String, Integer>();
for(String item : items) {
    crazy.setText(item);
    results.put(item, crazy.getOccurances);
}

Es gibt Gründe für einige dieser. Die setText (...) und getOccurances (...) ist da, weil es mehrere Abfragen, die Sie nach tun die gleiche teure Analyse der Daten tun mögen, aber dies kann zu einem Ergebnis Klasse Refactoring werden.

Warum ich denke, das so schlecht ist: die Umsetzung Zustand in einer Art und Weise speichert, die nicht eindeutig durch die Schnittstelle angezeigt wird. Ich habe auch etwas ähnliche Beteiligung eine Schnittstelle zu sehen, die rufen erforderlich „prepareResult“, dann „getResult“. Jetzt kann ich gut gestalteter Code denken, dass einige dieser Funktionen beschäftigt. Hadoop Mapper-Schnittstelle erweitert JobConfigurable und Verschließbare, aber ich sehe einen großen Unterschied, weil es ein Rahmen ist, der diese Schnittstellen Implementierung im Vergleich zu einem Service-Benutzer-Code verwendet, die mehrere Implementierungen haben könnten. Ich nehme alles im Zusammenhang mit darunter eine „close“ Methode, die gerechtfertigt bezeichnet werden muß, da es keine andere vernünftige Art und Weise ist, es zu tun. In einigen Fällen wie JDBC, ist dies eine Folge einer undichten Abstraktion, aber in den beiden Teilen des Codes von Mir denke, es ist ziemlich eindeutig eine Folge von Programmierern in aller Eile eine Schnittstelle zu einer Spaghetti-Code Klasse Zugabe zu bereinigen.

Meine Fragen sind:

  1. Hat jeder einverstanden ist dies eine schlecht gestaltete Schnittstelle?
  2. Ist das ein beschriebenes anti-Muster?
  3. Ist diese Art der Initialisierung jemals in einer Schnittstelle gehört?
  4. Ist nur das für mich falsch erscheinen, weil ich eine Vorliebe für funktionalen Stil und die Unveränderlichkeit habe?

Wenn diese häufig genug ist, einen Namen zu verdienen, schlage ich vor, das „Secret Handshake“ anti-Muster für eine Schnittstelle, die Sie zwingt mehrere Methoden in einer bestimmten Reihenfolge zu nennen, wenn die Schnittstelle nicht von Natur aus Stateful ist (wie eine Collection) .

War es hilfreich?

Lösung

Ja, es ist ein Anti-Muster:. Sequential Kopplung

ich in Options Refactoring würde - in die Fabrik geführt und Results, kehrte von einer analyseText() Methode

.

Andere Tipps

  1. Ich würde erwarten, dass der AnalyzerFactory, um zu sehen, die notwendigen params erhält weitergegeben und macht den Bau selbst; sonst, was genau sie tun?
  2. Nicht sicher, ob es einen Namen hat, aber es scheint, wie es sollte:)
  3. Ja, occassionally bequem es ist (und das richtige Maß an Abstraktion) Setter in Ihrer Schnittstelle zu haben, und erwartet, dass Klassen, sie zu nennen. Ich würde vorschlagen, dass so zu tun erfordert eine umfangreiche Dokumentation dieser Tatsache.
  4. Nicht wirklich, nein. Eine Präferenz für Unveränderlichkeit ist sicherlich eine gute Sache, und Setter / bean-basiertes Design kann die „richtige“ Wahl manchmal sein, aber Ihr gegebenes Beispiel zu weit nimmt.

Ich bin nicht sicher, ob es ein beschriebenes anti-Muster, aber ich völlig einverstanden ist dies eine schlecht gestaltete Oberfläche. Es lässt zu viel Gelegenheit für Fehler und verletzt mindestens ein Schlüsselprinzip:. Ihre API schwer zu Missbrauch machen

Neben Missbrauch kann diese API auch zu schwer zu debuggen Fehler, wenn mehrere Threads Verwendung derselben Instanz machen.

Joshua Bloch hat tatsächlich einen ausgezeichneten Präsentation (36m16s und 40m30s) auf API-Design und er befasst sich dies als eines der Merkmale eines schlecht gestalteten API.

Ich kann nichts Schlechtes in hier sehen. setText() bereitet die Bühne; Danach müssen Sie eine oder mehrere Anrufe getOccurances(). Da setText() so teuer ist, kann ich mich keinen anderen Weg, dies zu tun.

getOccurances(text, query) würde die „geheimen Handschlag“ zu einem enorm günstigen Performance Kosten beheben. Sie könnten versuchen, Text in getOccurances() zwischenzuspeichern und nur Ihre internen Caches aktualisieren, wenn der Text ändert, aber das beginnt mehr zu sehen und mehr wie Opfer zu einem gewissen OO-Prinzip. Wenn eine Regel keinen Sinn macht, dann gelten Sie es nicht. Software-Entwickler haben ein Gehirn aus einem Grund.

Eine mögliche Lösung - Fluent chaning verwenden. Das vermeidet eine Klasse Methoden enthält, die in einer bestimmten Reihenfolge genannt müssen. Es ist eine Menge, wie die Erbauer, die Sie Objekte nicht lesen sorgt dafür, dass nach wie vor in der Mitte sind bevölkert wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top