Что именно означает «исправление обезьян» в Ruby? - PullRequest
61 голосов
/ 26 декабря 2008

Согласно Википедии, патч обезьяны - это:

способ продлить или изменить время выполнения код динамических языков [...] без изменения исходного источника Код.

Следующее утверждение из той же записи смутило меня:

В Ruby термин «патч обезьяны» был неправильно понимать любую динамику модификация к классу и часто используется в качестве синонима для динамически изменение любого класса во время выполнения.

Я хотел бы знать точное значение исправления обезьяны в Ruby. Это что-то вроде следующего или это что-то еще?

class String
  def foo
    "foo"
  end
end

Ответы [ 8 ]

62 голосов
/ 18 августа 2011

Лучшее объяснение, которое я слышал для Исправление обезьян / Штамповка уток - это Патрик Юинг в RailsConf 2007

... если он ходит как утка и говорит как утка, то это утка, верно? Так если эта утка не дает вам шум, который вы хотите, вы должны просто ударите эту утку, пока она не вернет, что вы ожидаете.

44 голосов
/ 26 декабря 2008

Короткий ответ: нет точного значения, потому что это новый термин, и разные люди используют его по-разному. По крайней мере, это можно понять из статьи в Википедии. Некоторые настаивают на том, что он применяется только к коду «времени выполнения» (я полагаю, встроенные классы), в то время как некоторые используют его для ссылки на изменение времени выполнения любого класса.

Лично я предпочитаю более инклюзивное определение. В конце концов, если бы мы использовали термин «только для модификации встроенных классов», как бы мы относились к модификации во время выполнения всех других классов? Для меня важно то, что есть разница между исходным кодом и действующим классом.

В Ruby термин «патч обезьяны» был неправильно понимать любую динамику модификация к классу и часто используется в качестве синонима для динамически изменение любого класса во время выполнения.

Вышеприведенное утверждение утверждает, что использование Ruby некорректно, но термины меняются, и это не всегда плохо.

19 голосов
/ 26 декабря 2008

Исправление обезьян - это когда вы заменяете методы класса во время выполнения ( не добавляете новые методы, как описали другие).

В дополнение к очень неочевидному и трудному для отладки способу изменения кода, он не масштабируется; По мере того, как все больше и больше модулей запускают методы исправления обезьян, вероятность изменений, мешающих друг другу, растет.

4 голосов
/ 26 декабря 2008

Вы правы; это когда вы изменяете или расширяете существующий класс, а не делите его на подклассы.

3 голосов
/ 26 декабря 2008

Это исправление обезьяны:

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

Теперь я представляю, что иногда это может быть полезно, но представьте, если вы видели рутину.

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

И он ломается только , иногда , когда его вызывают. Тем, кто обращает внимание, вы уже знаете почему, но представьте, что вы не знали о типе с плавающей точкой, имеющем .times class-метод, и автоматически предположили, что my_special_number является целым числом. Каждый раз, когда параметр представляет собой целое число, целое число или число с плавающей запятой, он будет работать нормально (целые числа передаются обратно, кроме случаев, когда есть остаток с плавающей запятой). Но передайте число с чем-либо в десятичной области, и оно наверняка сломается!

Только представьте, как часто это может происходить с вашими гемами, плагинами Rails и даже вашими коллегами по проектам. Если есть один или два небольших метода, подобных этому, и может потребоваться некоторое время, чтобы найти и исправить.


Если вам интересно, почему он ломается, обратите внимание, что sum является целым числом, а остаток с плавающей запятой может быть передан обратно; Кроме того, экспоненциальный знак работает только при одинаковых типах. Таким образом, вы можете подумать, что это исправлено, потому что вы преобразовали надоедливые числа в числа с плавающей запятой ... только чтобы обнаружить, что сумма не может принять результат с плавающей запятой.

2 голосов
/ 27 декабря 2008

В Python monkeypatching часто упоминается как признак смущения: «Мне пришлось monkeypatch этот класс, потому что ...» (я впервые столкнулся с ним, когда имел дело с Zope, о котором упоминается в статье). Говорят, что необходимо было овладеть вышестоящим классом и исправить его во время выполнения, вместо того, чтобы лоббировать исправление нежелательных поведений в реальном классе или их исправление в подклассе. По моему опыту, люди в Ruby не слишком много говорят об обезьяньей ловушке, потому что она не считается особенно плохой или даже заслуживающей внимания (отсюда и «штамповка утки»). Очевидно, что вы должны быть осторожны с изменением возвращаемых значений метода, который будет использоваться в других зависимостях, но добавление методов в класс так, как это делают active_support и facets, совершенно безопасно.

Обновление 10 лет спустя : я бы изменил последнее предложение, чтобы сказать "относительно безопасно". Расширение класса базовой библиотеки новыми методами может привести к проблемам, если кто-то другой получит ту же идею и добавит тот же метод с другой реализацией или сигнатурой метода, или если люди перепутают расширенные методы для функциональности основного языка. Оба случая часто происходят в Ruby (особенно в отношении методов active_support).

1 голос
/ 26 декабря 2008

Обычно речь идет об особых изменениях с использованием открытых классов Ruby, часто с некачественным кодом.

Хорошее продолжение по теме:

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

0 голосов
/ 11 января 2019

Пояснение понятия без кода:

Обсуждение точной концепции слишком академично и детально, чем нужно. Давайте сделаем это просто на следующем примере:

Нормальная эксплуатация автомобиля

Как ты обычно заводишь машину? Все просто: вы включаете зажигание, машина запускается, и вуаля вы отправляетесь в гонки!

Обезьяна, ремонтирующая автомобиль

Но что, если кто-то еще сделал машину и что, если вы захотите изменить ее работу?

Вам не нужно идти на завод по производству автомобилей, чтобы внести эти изменения: вы можете просто «подлатать обезьяну», забравшись под капот и умышленно и украдкой перемонтировав вещи и добавив туда несколько мест. Вы должны действительно знать, что вы делаете, когда вы делаете это, иначе результаты могут быть довольно взрывоопасными - и, возможно, это именно то, что вы хотите?

« Фабрицио, куда ты идешь? »

Boom!

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

«Держите исходный код близко, но ваши обезьяны исправляются».

...