Считается ли обезьян-патчинг хорошей практикой программирования?


15

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

Тем не менее, я видел, как этот метод использовался как «обычный путь» в основных проектах, например, в gevent.monkeyмодуле Gevent .

Стало ли использование обезьяньей патчи основной, нормальной и приемлемой практикой программирования?

Смотрите также: «Обезьяна для людей» Джеффа Этвуда


13
Я бы сказал, что то, что называется « исправление обезьян», НЕ считается хорошей практикой программирования. Даже не зная, что это такое, просто по имени.
littleadv

Что делать, если сторонняя организация не хочет делать нужное вам исправление?

1
@ Thorbjørn: хороший вопрос, с одной стороны, я не люблю monkeypatching, с другой - мне не очень нравится идея клонирования проекта и сохранения локальных патчей, если это всего лишь небольшая проблема.
vartec

1
@littleadv: ... тогда назовите это «оперативное исправление» / «исправление на лету» или «исправление во время выполнения», и это звучит хорошо, верно? ;) Все то же самое.
dagnelies

3
Javascript в значительной степени построен на концепции
ZJR

Ответы:


19

Нет, но иногда monkeypatch - меньшее зло (чем сломанный код :)). Мои общие правила для monkeypatches в ruby:

  • есть действительно веская причина для monkey-patch (временное критическое исправление - хорошая причина. Хорошее форматирование метода to_s - нет, если только вы не работаете с ActiveSupport)

  • сделайте их максимально прозрачными: поместите их в определенное место в кодовой базе и в отдельных файлах, напишите документацию, описывающую причину monkeypatch (вот пример ).

  • легко удалить - документация должна содержать информацию об удалении и о том, что нужно искать. Многие обезьяны являются временными, поэтому их легко удалить.


11

Да, monkeypatching очень полезен!

Почему-то имена очень сильно влияют на восприятие людей. Назовите это «monkeypatch», и это звучит плохо, назовите это «оперативное исправление» или «исправление на лету», и это звучит хорошо.

Независимо от этого, я думаю, что возможность изменять методы / атрибуты / функции во время выполнения - очень полезная вещь. Даже люди, использующие javascript, используют его весь день, не зная об этом.

Например:

button.onclick = function(e) { ...}

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

Теперь по вопросу доставки исправлений таким образом ... ну ... почему бы и нет. Вам просто нужно скачать маленький патч вместо большого релиза. Черт, вы могли бы даже исправить сервер, не останавливая его, отлично! И затем, однажды, вы также можете получить последний выпуск для большего обновления. Справедливо. Так что да, я голосую за «исправления во время выполнения» как за хорошую вещь.

Интересно, что некоторые языки, такие как Erlang, были даже построены вокруг этой концепции. Возможность обновления сервера на лету.

Конечно, в конце концов, как и во всем остальном, все зависит от того, как вы это используете. Вы можете сделать замечательные ОО вещи и дерьмовый, это все то же самое.

РЕДАКТИРОВАТЬ:

Позвольте мне добавить несколько различий в регистре, будь то исправление вашей собственной библиотеки или сторонней библиотеки .

... в основном то, что вы делаете с таким патчем, это исправление ошибки вашей собственной или сторонней библиотеки. В любом случае это полезно. Для вас, это позволяет вам доставить исправление на лету. Что касается стороннего, либо вы ждете (несколько месяцев?), Пока они не исправят это самостоятельно, либо вы делаете это сейчас самостоятельно. (вы все равно можете отправить им патч, чтобы они исправили его на своей стороне). Когда они выпустят свою следующую версию lib с исправленной проблемой, вы все равно можете, если хотите, обновить библиотеку и удалить патч на вашей стороне.

Теперь, конечно, если вы используете патч, чтобы изменить поведение библиотеки и оттолкнуть ее цель / способ работы, то, очевидно, это и есть путь к катастрофе. Даже обезьяна увидит это ... ну, я надеюсь. ;)


1
Никто не говорит, что это бесполезно. Тем не менее, это не очень хорошая практика в целом. И «исправление» и «исправление на лету» звучат не лучше для меня.
Лукас Стейскал

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

Я согласен, что это мощная и полезная функция. Но также очень опасен (особенно в Ruby), поэтому его следует использовать с особой осторожностью (особенно для модификации стандартных и сторонних библиотек). Вы когда-нибудь пытались поддерживать приложение в зависимости от нескольких непатентованных сторонних библиотек? Рецепт катастрофы, когда вы пытаетесь обновить библиотеку.
Лукас Стейскал

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

... Я добавил несколько комментариев о последнем случае.
августа

8

Я считаю, что все патчи по своей природе рискованны из-за их характера во время выполнения и неспособности быть обнаруженными во время разработки.

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

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

Мои два цента


4

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

Давным-давно к моему ядру Linux было применено 3 отдельных патча, необходимых для моего драйвера видеокарты, и двух проприетарных приложений, которые у меня были. У двух из них были противоречивые изменения, что означало, что мне нужен 4-й патч, чтобы устранить различия между ними. Теперь, когда проблема безопасности была исправлена ​​в исходном ядре, мне приходилось либо ждать, пока поставщики этих трех патчей выпустят обновление для новой версии ядра, что занимало от одного до шести месяцев, либо мне приходилось вручную поддерживать восходящий выпуск. патчи безопасности, пока другие производители патчей не догонят.

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


3

Нет. Это не стандартная методика разработки программного обеспечения. Это остается обходным путем для решения острой проблемы и имеет явные недостатки. Нарушение принципа подстановки Лискова приходит на ум. Исправления из-за обезьян серьезно затрудняют анализ программ. Для ваших собственных программ вы должны разместить код там, где он принадлежит. Для сторонних библиотек вы всегда будете в опасности, что ваш патч не будет работать со следующей версией библиотеки.

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

Кстати, ты когда-нибудь писал юнит-тест для патча обезьяны?


Я не думаю, что вы можете применить LSP здесь. У этого есть очень определенное определение относительно подтипов.
Конрад Рудольф

@KonradRudolph Обезьяна, исправляющая объект, меняет его тип. В динамически типизированных языках каждый тип t с тем же интерфейсом, что и тип u, является подтипом u. Если он ходит как утка ...
Скарфридж

«… Меняет свой тип» - достаточно справедливо. Имеет смысл.
Конрад Рудольф

RE «Это не стандартная методика для разработки программного обеспечения.», Кажется, это делается * постоянно и в основных библиотеках »в Python для тестирования.
Томми
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.