it-swarm.com.de

Was bedeutet "Monkey Patching" in Ruby genau?

Laut Wikipedia ist ein Affenpflaster :

eine Möglichkeit, den Laufzeitcode dynamischer Sprachen zu erweitern [...] oder zu ändern, ohne den ursprünglichen Quellcode zu ändern.

Die folgende Aussage aus demselben Eintrag hat mich verwirrt:

In Ruby wurde der Begriff "Affen-Patch" missverstanden, um jede dynamische Änderung einer Klasse zu bezeichnen. Er wird häufig als Synonym für die dynamische Änderung einer Klasse zur Laufzeit verwendet.

Ich würde gerne die genaue Bedeutung des Patchens von Affen in Ruby erfahren. Macht es etwas wie das Folgende oder ist es etwas anderes?

class String
  def foo
    "foo"
  end
end
59
Yaser Sulaiman

Die kurze Antwort lautet, dass es keine "exakte" Bedeutung gibt, da es sich um einen neuartigen Begriff handelt, der von verschiedenen Leuten unterschiedlich verwendet wird. Das ist zumindest aus dem Wikipedia-Artikel zu erkennen. Es gibt einige, die darauf bestehen, dass es nur für "Laufzeitcode" gilt (eingebaute Klassen, nehme ich an), während einige es verwenden würden, um auf die Laufzeitänderung einer Klasse zu verweisen.

Ich persönlich bevorzuge die umfassendere Definition. Wenn wir den Begriff nur für die Modifikation eingebauter Klassen verwenden, wie würden wir uns auf die Laufzeitmodifikation aller anderen Klassen beziehen? Das Wichtigste für mich ist, dass es einen Unterschied zwischen dem Quellcode und der tatsächlich laufenden Klasse gibt.

In Ruby war der Begriff Affenpflaster falsch verstanden, um jede Dynamik zu bedeuten Änderung an einer Klasse und ist häufig wird als Synonym für dynamisch verwendet Ändern jeder Klasse zur Laufzeit.

Die obige Aussage behauptet, dass die Verwendung von Ruby nicht korrekt ist - aber die Bedingungen entwickeln sich und das ist nicht immer eine schlechte Sache.

43
Joshua Swink

Die beste Erklärung, die ich für Monkey Patching/Duck-Punching gehört habe, stammt von Patrick Ewing in RailsConf 2007

... wenn es wie eine Ente geht und wie eine Ente redet, ist es eine Ente, oder? So Wenn diese Ente Ihnen nicht das Geräusch gibt, das Sie möchten, müssen Sie einfach die Ente schlagen, bis sie das zurückgibt, was Sie erwarten.

61
RSK

Das Affen-Patching ist, wenn Sie replace Methoden einer Klasse zur Laufzeit (not neue Methoden hinzufügen, wie andere beschrieben haben). 

Abgesehen davon, dass es eine sehr unübersehbare und schwer zu debugierende Methode zum Ändern von Code ist, skaliert sie nicht. Da immer mehr Module mit Affen-Patch-Methoden beginnen, steigt die Wahrscheinlichkeit, dass sich die Änderungen gegenseitig stampfen.

18
Paul Betts

Einer der mächtigsten Aspekte von Ruby ist die Möglichkeit, jede Klasse wieder zu öffnen und ihre Methoden zu ändern.

Ja, das ist richtig, Sie können jede Klasse tatsächlich wieder öffnen und ihre Funktionsweise ändern. Dies beinhaltet die Standard-Ruby-Klassen wie 

String, Array or Hash!

Nun, das ist offensichtlich so gefährlich, wie es sich anhört. In der Lage zu sein, das erwartete Ergebnis einer Methode zu ändern, kann allerlei seltsames Verhalten verursachen und es schwierig machen, Fehler aufzuspüren.

Trotzdem ist die Fähigkeit, jede Klasse zu „Monkey Patch“ zu machen, extrem mächtig. Ruby ist wie ein scharfes Messer, es kann extrem effektiv sein, aber normalerweise sind Sie selbst schuld, wenn Sie sich schneiden.

Zunächst fügen wir eine praktische Methode hinzu, um Lorem Ipsum-Text zu generieren:

class String
  def self.lipsum
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
  end
end

In diesem Beispiel habe ich die String-Core-Klasse wieder geöffnet und eine Lipsum-Klassenmethode hinzugefügt.

String.lipsum
=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit."

Wir können jedoch nicht nur Methoden zur String-Klasse hinzufügen, sondern auch das Verhalten vorhandener Methoden ändern!

class String
  def upcase
    self.reverse
  end
end

In diesem Beispiel übernehmen wir die upcase-Methode und rufen stattdessen die reverse-Methode auf!

"hello".upcase
=> "olleh"

Wie Sie sehen, ist es unglaublich einfach, Methoden zu einer vorhandenen Klasse hinzuzufügen oder zu ändern, selbst wenn Sie diese Klasse nicht besitzen oder zu Ruby gehören.

Wann sollten Sie Monkey Patching verwenden?

Selten.

Ruby bietet uns eine Fülle an leistungsstarken Tools, mit denen wir arbeiten können. Nur weil ein Werkzeug leistungsstark ist, ist es nicht das richtige Werkzeug für den Job.

Insbesondere das Affen-Patching ist ein äußerst leistungsfähiges Werkzeug. Ein starkes Werkzeug in den falschen Händen verursacht jedoch unendlich viele Schmerzen und Leiden.

Wann immer Sie eine Klasse mit einem Affen-Patch versehen haben, verursachen Sie möglicherweise in Zukunft möglicherweise Kopfschmerzen, wenn Probleme auftreten.

Klassen, die mit Monkey Patches versehen wurden, sind schwieriger zu verstehen und zu debuggen. Wenn Sie nicht vorsichtig sind, wird Ihnen die Fehlermeldung, die Sie erhalten, sehr wenig Aufschluss über das eigentliche Problem geben.

Wenn Sie eine Methode mit dem Affen-Patch aktualisieren, brechen Sie möglicherweise nachgelagerten Code, der auf dieses Verhalten angewiesen ist.

Wenn Sie einer vorhandenen Klasse mit Monkey Patching eine neue Methode hinzufügen, öffnen Sie möglicherweise seltsame Edge-Fälle, die Sie nicht vorhersehen können.

Wann ist der Monkey Patch in Ordnung?

Nachdem dies gesagt wurde, hat es keinen Sinn, über leistungsfähige Tools wie Monkey Patching zu verfügen, wenn Sie sie nicht wirklich nutzen.

Es gibt Fälle, in denen das erneute Öffnen einer Klasse sinnvoll ist.

Beispielsweise werden häufig Monkey-Patches angezeigt, die einfach eine bequeme Methode hinzufügen, die keine Nebeneffekte hat. Ruby hat eine sehr schöne Syntax und daher kann es eine Versuchung sein, eine Klasse mit dem Affen-Patch zu manipulieren, um einen hässlichen Methodenaufruf in etwas lesbarer zu machen.

Oder vielleicht müssen Sie eine Klasse, die Sie besitzen, mit einem Affen-Patch versehen.

Es gibt viele Fälle, in denen Monkey Patch in Ordnung ist, aber es sollte definitiv nicht Ihre erste Waffe sein.

Es ist oft der Fall, dass Monkey Patching nur die Vorliebe des faulen Entwicklers ist, wenn ein bekanntes Entwurfsmuster für ein bestimmtes Problem tatsächlich umgestaltet oder implementiert wird.

Nur weil Monkey Patching Ihnen eine einfache Lösung bietet, heißt das nicht, dass Sie diesen Weg immer gehen sollten.

http://culttt.com/2015/06/17/what-is-monkey-patching-in-Ruby/

6
Subhash Chandra

Du hast Recht; Es ist, wenn Sie eine vorhandene Klasse ändern oder erweitern, anstatt sie zu subklassieren.

4
davetron5000

Das ist Affen-Patching:

class Float
  def self.times(&block)
    self.to_i.times { |i| yield(i) }
    remainder = self - self.to_i
    yield(remainder) if remainder > 0.0
  end
end

Jetzt stelle ich mir vor, dass dies manchmal nützlich sein könnte, aber stellen Sie sich vor, Sie sahen Routine.

def my_method(my_special_number)
  sum = 0
  my_special_number.times { |num| sum << some_val ** num }
  sum
end

Und es bricht nur gelegentlich, wenn es aufgerufen wird. Für diejenigen, die aufpassen, wissen Sie bereits warum, aber stellen Sie sich vor, Sie wussten nicht, dass der Float-Typ eine .times-Klassenmethode hat, und Sie haben automatisch angenommen, dass my_special_number eine Ganzzahl ist. Jedes Mal, wenn der Parameter eine ganze Zahl, eine ganze Zahl oder ein Gleitkomma ist, funktioniert er einwandfrei (ganze Ints werden zurückgegeben, es sei denn, es gibt einen Gleitpunktrest). Aber geben Sie eine Zahl mit etwas im Dezimalbereich ein und es wird auf jeden Fall kaputt gehen!

Stellen Sie sich vor, wie oft dies mit Ihren Edelsteinen, Rails-Plugins und sogar Ihren eigenen Mitarbeitern in Ihren Projekten passieren könnte. Wenn da eine oder zwei kleine Methoden vorhanden sind, kann es einige Zeit dauern, diese zu finden und zu korrigieren.


Wenn Sie sich fragen, warum es kaputt geht, beachten Sie, dass sum eine ganze Zahl ist und ein Gleitkomma-Rest zurückgegeben werden kann. Außerdem funktioniert das Exponentialzeichen nur, wenn die Typen gleich sind. Sie denken vielleicht, dass es behoben ist, weil Sie Störungszahlen in Floats konvertiert haben, nur um festzustellen, dass die Summe das Fließkomma-Ergebnis nicht verarbeiten kann.

3
Robert K

In Python wird Monkeypatching oft als ein Zeichen der Verlegenheit bezeichnet: "Ich musste diese Klasse monkeypatchen, weil ..." (Ich habe es zuerst beim Umgang mit Zope gesehen, was in dem Artikel erwähnt wird). Es wird verwendet, um zu sagen, dass es notwendig war, eine Upstream-Klasse zu ergreifen und sie zur Laufzeit zu reparieren, anstatt Lobbying durchzuführen, um die unerwünschten Verhaltensweisen in der tatsächlichen Klasse zu beheben oder sie in einer Unterklasse zu fixieren. Nach meiner Erfahrung sprechen Ruby-Leute nicht so viel über das Monkeypatching, weil es nicht besonders schlecht oder gar nicht als bemerkenswert angesehen wird (daher "Entenstanzen"). Natürlich müssen Sie vorsichtig sein, wenn Sie die Rückgabewerte einer Methode ändern, die in anderen Abhängigkeiten verwendet wird. Das Hinzufügen von Methoden zu einer Klasse auf die Art und Weise, wie es active_support und facets tun, ist jedoch absolut sicher. 

Update 10 Jahre später : Ich würde den letzten Satz dahingehend ändern, dass "relativ sicher" ist. Das Erweitern einer Kernbibliothekenklasse mit neuen Methoden kann zu Problemen führen, wenn ein anderer Benutzer dieselbe Idee erhält und dieselbe Methode mit einer anderen Implementierung oder Methodensignatur hinzufügt oder wenn erweiterte Methoden für Kernfunktionalität verwirrt werden. Beide Fälle treten häufig in Ruby auf (insbesondere in Bezug auf active_support-Methoden).

2
method

Normalerweise handelt es sich um Ad-hoc-Änderungen, die Verwendung von offenen Ruby-Klassen, häufig mit Code von geringer Qualität.

Gutes Follow-up zum Thema:

http://www.infoq.com/articles/Ruby-open-classes-monkeypatching

1
maurycy

Erläuterung des Konzepts ohne Code:

Die Diskussion des genauen Konzepts ist zu akademisch und nuanciert, als es sein muss. Lassen Sie uns es mit dem folgenden Beispiel einfach machen:

Der normale Betrieb eines Autos

Wie fangen Sie normalerweise ein Auto an? Es ist ganz einfach: Sie drehen die Zündung, das Auto startet und Sie sind zu den Rennen unterwegs!

Affe ein Auto patchen

Was aber, wenn jemand anderes das Auto hergestellt hat und was, wenn Sie die Funktionsweise ändern möchten? 

Sie müssen nicht in die Automobilfabrik gehen, um diese Änderungen vorzunehmen: Sie können ihn einfach "monkey-patch" machen, indem Sie unter die Motorhaube gehen und heimlich und hinterlistig Dinge neu verbinden und ein paar Zwischenfälle hier und dort hinzufügen. Sie müssen wirklich wissen, was Sie tun, wenn Sie dies tun, sonst könnten die Ergebnisse ziemlich explosiv sein - und vielleicht ist das genau das, was Sie wollen? 

"Fabrizzio, wohin gehst du?"

Boom!

 Monday, Tuesday, Wed-nes-day, Thursday, Friday, Sat-a-day. Image is free and open source from unsplash - https://unsplash.com/photos/dyrehVIidQk

"Behalte deinen Quellcode in der Nähe, aber dein Affe wird näher gepackt."

0
BKSpurgeon