Каков формальный шаблон проектирования, лежащий в основе «monkeypatching»?
-
11-09-2019 - |
Вопрос
Основной вопрос CS здесь:из шаблонов проектирования, перечисленных в разделе «Гамма» и т. д., которые (если таковые имеются) охватывают патчи для обезьян?Кроме того, для какого класса проблем подходит Monkeypatching, а не для какого класса?подклассы?Исправление ошибок в основных классах библиотеки — это одно, а есть ли другие?Я слышал много шума и споров по поводу обезьяньего исправления в stackoverflow, у большинства из вас, похоже, есть сильные опасения по этому поводу, но как программисту мне очень нравится возможность инкапсулировать общие фрагменты функциональности и включать их в мои объектные модели в рельсах.
Возьмем, к примеру, скрепку-мыслитель: зачем мне когда-либо хотеть создавать подкласс этого подхода по сравнению с существующим сегодня подходом Monkeypatch?
Спасибо, -Рич
Решение
Я не думаю, что обезьянье исправление - это шаблон проектирования - расширение основного класса - это особенность языка, которую они, кажется, игнорируют.
Что касается остального, взгляните на взгляды Джеффа Этвуда на эта статья в его блоге.
По его (и моему) мнению, самая большая проблема с обезьяньим исправлением заключается в том, что оно может очень затруднить отладку, если оно модифицирует существующие методы - мы, люди, не можем отслеживать все «маленькие фрагменты здесь и там», как это делают машины.Подклассы обеспечивают более четкое разделение.
Итак, мои личные правила по патчению обезьян таковы:
- Если вы можете сделать это без Monkeypatching и все будет работать нормально, не используйте Monkeypatching.
- Вы можете добавлять в классы новые методы, но не можете изменять существующие.
- Сделайте это очень видимым и очевидным образом, т.е.файл с именем string_extensions.rb в вашем /lib, а не в скрытом /myvendor/submodule/se.rb .
- Должно быть локальным;классы, которые не используют библиотеку, не должны быть затронуты.
Теперь к вашему примеру:Скрепка для бумаг.
- Насколько мне известно, он добавляет методы в ваши классы ActiveRecord, но не изменяет существующие.
- Вам нужно добавить
has_attachment
директива для классов, использующих скрепку, в противном случае они не затрагиваются.
Таким образом, изменения локализованы и очевидны (я вообще-то думаю, что это удается). улучшать отладка:нам, людям, легче читать has_attachment
вместо class MyModel < Paperclip::ActiveRecordWithAttachment
).
Создание подклассов также является плохой идеей в этом случае, потому что вы не сможете использовать скрепку в дополнение к другому плагину, который использует подклассы - рельсы наследуются по одному.
А в случае со Скрепкой это явно has_a
отношения с его привязанностью, а не is_a
один.Можно возразить, что такое использование подклассов было бы неправильным.
Наконец, я хотел бы отметить, что Paperclip в некоторых случаях требует создания подклассов (вы должны использовать подклассы, чтобы создать процессор скрепок).