Вопрос

Я медленно перехожу с PHP5 на Python в некоторых личных проектах, и сейчас мне нравится этот опыт.Прежде чем выбрать путь Python, я посмотрел на Ruby.Что я действительно заметил в сообществе Ruby, так это то, что исправление обезьян было обычным явлением и высоко ценилось.Я также наткнулся на много ужасных историй об испытаниях отладки программного обеспечения Ruby, потому что кто-то включил относительно безобидную библиотеку для выполнения небольшой работы, но которая исправила какой-то активно используемый основной объект, не сказав никому.

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

Сегодня вечером я читал о SOLID Роберта Мартина принципы:

  • Спринцип единой ответственности,
  • Оручка/закрытый принцип,
  • лпринцип замены исков,
  • япринцип разделения интерфейсов и
  • Дпринцип инверсии подчиненности

в настоящее время я готов О: ПРОГРАММНЫЕ ОБЪЕКТЫ (КЛАССЫ, МОДУЛИ, ФУНКЦИИ И Т.Д.) ДОЛЖНЫ БЫТЬ ОТКРЫТЫ ДЛЯ РАСШИРЕНИЯ, НО ЗАКРЫТЫ ДЛЯ МОДИФИКАЦИИ..

Моя голова кружится из-за конфликта между обеспечением согласованности объектно-ориентированного дизайна и всей этой штукой с исправлениями обезьян.Я понимаю, что в Python можно выполнить исправление обезьян.Я также понимаю, что быть «питоническим» — значит следовать общим, хорошо проверенным передовым практикам и принципам.

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

Это было полезно?

Решение

Существует разница между исправлением обезьян (перезаписью или изменением ранее существовавших методов) и простым добавлением новых методов.Я думаю, что последнее вполне нормально, а к первому следует относиться с подозрением, но я по-прежнему за его сохранение.

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

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

Хронология ошибки в программе на C#, которая у нас была:

  1. Прочитайте отчеты о странных ошибках и найдите причину проблемы в незначительной ошибке в библиотеке CLR.
  2. Потратьте несколько дней на поиск обходного пути, включающего перехват исключений в странных местах и ​​множество хаков, которые сильно компрометируют код.
  3. Потратьте несколько дней на поиск обходного пути, когда Microsoft выпустит пакет обновлений.

Хронология ошибки в программе Rails, которая у нас была:

  1. Прочитайте странные отчеты об ошибках и отследите проблему до незначительной ошибки в стандартной библиотеке Ruby.
  2. Потратьте 15 минут на выполнение небольшого исправления обезьяны, чтобы удалить ошибку из библиотеки Ruby, и разместите вокруг нее защиту, чтобы она отключилась, если она будет запущена в неправильной версии Ruby.
  3. Продолжайте нормально кодировать.
  4. Просто удалите Monkeypatch позже, когда будет выпущена следующая версия Ruby.

Процесс исправления ошибок выглядит аналогично, за исключением того, что исправление обезьян - это 15-минутное решение и 5-секундное «извлечение», тогда как без него возникают боль и страдания.

ПС:Следующий пример представляет собой «технически» исправление обезьян, но является ли оно «морально» исправлением обезьян?Я не меняю никакого поведения — это более или менее просто выполнение АОП в Ruby…

class SomeClass
  alias original_dostuff dostuff
  def dostuff
    # extra stuff, eg logging, opening a transaction, etc
    original_dostuff
  end
end

Другие советы

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

Я не думаю, что это следует объявить вне закона, это просто то, что ребята из Ruby любят использовать.Вы можете делать подобные вещи с помощью Python, но сообщество придерживается позиции, что все должно быть проще и очевиднее.

Исправление Monkey не является явным для Ruby, оно также выполняется по всему JavaScript, с отрицательными (IMO) эффектами.

Мое личное мнение: исправление обезьян следует делать только для

а) Добавьте функциональность к старой версии языка, которая доступна в новой версии нужного вам языка.

б) Когда для него нет другого «логического» места.

Есть много-много простых способов сделать обновление обезьян по-настоящему ужасным, например, возможность изменить работу основных функций, таких как ДОБАВЛЕНИЕ работа.

Моя позиция такова: если вы можете этого избежать, сделайте это.

Если вы можете избежать этого хорошим способом, слава вам.

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

Моя любимая ненависть Mootools расширяет функция объект.Да, ты можешь это сделать.Вместо того, чтобы люди просто изучали, как работает JavaScript:

setTimeout(function(){ 
    foo(args); 
}, 5000 ); 

К каждому функциональному объекту был добавлен новый метод (да, я не шучу), так что у функций теперь есть свои собственные функции.

foo.delay( 5000 , args );

Что имело дополнительный эффект от того, что такая чушь была действительной:

foo.delay.delay( 500,  [ 500, args ] ); 

И так до бесконечности.

Результат?У вас больше нет библиотеки и языка, ваш язык подчиняется библиотеке, и если библиотека оказывается в пределах видимости, у вас больше нет языка, и вы не можете просто делать вещи так, как они делались, когда вы изучаете язык, и вместо этого придется выучить новый подмножество команд только для того, чтобы оно не развалилось лицом к лицу (ценой чрезмерного замедления!)

Могу ли я отметить, что foo.delay также вернул объект со своими собственными методами, так что вы можете сделать

x = foo.delay( 500, args ); 
x.clear(); 

и даже

 x.clear.delay(10); 

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

 clearTimeout(x); 

ТАК ТРУДНО!

(Отказ от ответственности:Прошло много времени с тех пор, как я использовал moo, и пытался забыть об этом, и имена/структура функций могут быть неправильными.Это не ссылка на API.Пожалуйста, проверьте их сайт для получения подробной информации (извините, их ссылка на API отстой!))

Mokeypatching вообще неправильно.Создайте правильный подкласс и добавьте методы.

Я однажды использовал Monkeypatching в рабочем коде.

Проблема в том, что REST использует GET, POST, PUT и DELETE.Но тестовый клиент Django предлагает только GET и POST.У меня есть исправленные методы для PUT (например, POST) и DELETE (например, GET).

Из-за тесной привязки между клиентом Django и тест-драйвером Django, казалось, проще всего использовать обезьяний патч для поддержки полного тестирования REST.

Вы можете найти поучительное это обсуждение об открытых классах Ruby и принципе открытости-закрытости.

Несмотря на то, что мне нравится Ruby, я считаю, что исправление обезьян — это последнее средство, позволяющее добиться цели.При прочих равных условиях я предпочитаю использовать традиционные объектно-ориентированные методы с примесью функционального программирования.

На мой взгляд, исправление обезьян — это одна из форм АОП.Статья Принципы аспектно-ориентированного проектирования:Уроки объектно-ориентированного проектирования (PDF) дает некоторые идеи о том, как SOLID и другие принципы ООП могут быть применены к АОП.

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

Исправление обезьян - это просто неправильный, ИМХО.Я не сталкивался с принципом открытости/закрытости, о котором вы упоминали ранее, но я давно придерживаюсь этого принципа и согласен с ним на 100%.Я думаю об обезьяньем патче как о запахе кода в более широком масштабе, как о запахе философии кодирования.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top