Monkey Patching состоит из динамических модификаций класса или модуля во время выполнения, мотивированных намерением исправить существующий сторонний код в качестве обходного пути к ошибке или функции, которая не работает должным образом, следовательно, исправление monkey будет изменять не само программное обеспечение, а только локальную копию во время ее работы.

Говоря обыденным языком, исправление обезьяны изменяет поведение методов класса (встроенных или созданных пользователем) во время выполнения. Для кого-то, кто только начинает изучать программирование, может показаться, что это сложно переварить, но это не так (обещаю)!

Каждый класс в Ruby имеет собственный список встроенных методов. Например, строка имеет целый список методов: в том числе #reverse, который меняет порядок строки, #count, который подсчитывает, сколько символов в строке, #empty? который скажет вам, пуста строка или нет, вернув истину или ложь, и так далее ...

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

Довольно простые вещи, правда? Теперь вызовем функцию #clear…

Как и ожидалось, строка очищена, и теперь test содержит пустую строку. Но что, если бы мы могли изменить способ работы метода String # clear? Вместо того, чтобы очищать массив, пусть он напечатает новую строку, которая повторяется.

Теперь, как предоставить классу строковых доступ к этому новому методу String # clear? Вы можете подумать, что нам, вероятно, придется потратить кучу времени на сортировку библиотек Ruby в вашей системе и изменить этот метод, верно? Неправильный!

Нам просто нужно создать новый класс String и вставить в него наш метод.

Этот новый метод String # clear перезапишет существующий метод String # clear, встроенный в Ruby в нашей системе, пока он включен в проект, над которым мы сейчас работаем.

Это означает, что это не постоянное изменение, которое повлияет на другие наши проекты - оно будет доступно только в том случае, если файл включен в проект Ruby, явно написав следующее:

Теперь у нас есть готовый к работе новый метод String # clear, давайте попробуем.

Метод #clear больше не выполняет своего поведения по умолчанию. Довольно потрясающе, да? Вы можете не только изменить поведение существующего метода, но и создать свой собственный, который будет выполняться в классе.

Например, в Rails есть метод массива, который расширяет класс массива для преобразования массива в предложение (Array # to_sentence). Что, если вы действительно хотели использовать этот метод, но вам не обязательно было нуждаться в остальном, что предоставляет Rails?

Просто скопируйте исходный код метода из документации Rails, поместите его в класс массива, как мы сделали с классом String выше, и вуаля!

При всем вышесказанном, исправление обезьяны - это то, что нам редко придется использовать или реализовывать вручную (методы обезьяны Rails исправляют для нас библиотеку Ruby по умолчанию). В некоторых языках, а именно в Python, установка патчей обезьяны категорически не рекомендуется. Ruby, похоже, принимает его больше, чем другие, но вы должны знать, что у него есть свои подводные камни.

Изменение поведения методов по умолчанию может привести к очень неожиданным и трудным для решения ошибкам. Изменение поведения встроенного метода Ruby (даже незначительное) может привести к катастрофическим результатам, особенно при совместной разработке.

Только представьте, с какими ошибками столкнулись бы другие разработчики, если бы у вас было перечисление Array # count в системе с единицей, а не с нулевым значением по умолчанию. Нелепый пример, но идею вы поняли.

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

Процитирую Филиппа Брауна, сообщение в блоге которого помогло мне лучше понять эту концепцию: Рубин подобен острому ножу, он может быть чрезвычайно эффективным, но обычно ты сам виноват, если порезался.