Frage

In ziemlich großer Ruby-Anwendung, haben wir eine Situation, in der ein bestimmtes Objekt durch ein paar Dinge identifiziert: Namen und id, sagt. Jeder dieses Werttypen dient einen etwas anderen Zweck und so ist nicht genau äquivalent (id und Namen bestehen in verschiedenen Orten). So Aufwicklung wir mit einer Vielzahl von Werten um die Anwendung übergeben werden (ids, Namen und Objekte). Diese Situation scheint ein Problem zu mindestens seit einem gewissen Grad haben wir bereits von Wanzen gebissen worden, die, welche Art beteiligten nicht klar sein sollte auf eine bestimmte Funktion übergeben werden. Ich erinnere mich tatsächlich ähnliches Problem Code in einer Reihe von Anwendungen im Laufe der Jahre zu sehen, obwohl ich nie wieder einen bestimmten Namen zu ihm gab.

Ruby als typenlos Sprache, erlaubt keine klassische Art-basierten polymorphe Funktionen in der Weise, dass C ++ tut. Als Arbeit um, hat ein Kollege oft Code dieser Art zurückgegriffen:

  def initialize starting_value
    if starting_post.kindof? Foo
      @starting_id = get_id_from_foo starting_value
    elsif starting_post.kindof? Bar
      @starting_id = get_id_from_bar starting_value
    else
      raise "illegal type"
    end
  end

Die Verbreitung dieses Codes um unsere Code-Basis (nicht nur initializers) ergibt, was ich nennen würde „chaotisch-Polymorphismus“. Es funktioniert oft, aber manchmal schafft sehr rätselhaft Situationen.

Ich habe drei Fragen zu diesem Thema.

  • Sie haben einen offiziellen Namen für diese als anti-Muster? "Messy Schnittstelle?", "Messy Polymorphismus?" oder etwas anderes?
  • Wie schlecht zu tun, Leute denken, das ist?
  • Gibt es eine systematische Art und Weise, zu Refactoring diese? Die Herausforderung, die wir haben mit gewöhnlicher Refactoring, die viele Tests, die wir verwenden diese erstellt sind loose-Typisierung und damit würden wir beide ändern müssen die Tests und die Implementierungen gleichzeitig und hätte so nicht das Gerüst Wirkung der gewöhnliche Testbasis Refactoring. Ich denke bin, dass man könnte tatsächlich „stärken“ dieser losen Polymorphismus, und abstrakt-out der Code in eine Funktion, anstatt sofort reißen sie aus. aber würde das eine gute Idee sein?
War es hilfreich?

Lösung

Können Sie nicht irgendeine Art von GET_ID Methode definieren, so dass eine id selbst zurückgibt, ein Objekt die ID zurückgibt, und der Name tut, was es eine ID zu erhalten tun muss? Dann können Sie immer etwas canonicalise, die Sie wissen, eine der drei sein wird. Ebenfalls mit get_name und get_object Methoden, wenn diejenigen, benötigt werden.

Das heißt, Sie haben eine implizite ThingWhatHasAnID Schnittstelle definiert, und machten, dass der Ente-Typ Ihrer Funktionsparameter.

Es sei denn, ich etwas fehle, würde ich nenne dieses anti-Muster „verpasste Gelegenheit, eine Abstraktion zu schaffen“.

Andere Tipps

Fast jede Zeit finden Sie selbst Einschalten eine Klasse des Objekts, es ist ein Hinweis darauf, dass das Verhalten selbst eine Methode des Objekts sein sollte. Botschaftsabsendung ist polymorphen basierend auf den Empfänger. In diesem Fall sollte es so etwas wie:

def initialize starting_value
  @starting_id = starting_value.id
end

definieren id unabhängig von den verschiedenen get_id_from_* Methoden zu tun zu tun pflegen. Der illegale Art Fall wird bereits erhöhen, weil Sie einen NoMethodError bekommen.

Als für das, was diese zu nennen, würde ich es nennen „prozeduralen Programmierung in einer OO-Sprache.“

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