Обезьяна-исправления Vs. S.O.L.I.D. принципы? - PullRequest
25 голосов
/ 16 ноября 2008

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

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

Этим вечером я читал о принципах SOLID Роберта Мартина:

  • S принцип единоличной ответственности,
  • O ручка / закрытый принцип,
  • L принцип замещения исков,
  • I принцип разграничения поверхности и
  • D принцип обращения зависимостей

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

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

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

Ответы [ 8 ]

29 голосов
/ 17 ноября 2008

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

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

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

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

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

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

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

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

PS: Следующий пример - «технически» обезьяноподготовка, но разве это «морально» обезьяноподготовка? Я не изменяю никакого поведения - это более или менее просто делает AOP в ruby ​​...

class SomeClass
  alias original_dostuff dostuff
  def dostuff
    # extra stuff, eg logging, opening a transaction, etc
    original_dostuff
  end
end
5 голосов
/ 16 ноября 2008

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

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

4 голосов
/ 16 ноября 2008

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

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

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

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

4 голосов
/ 16 ноября 2008

Исправление обезьян не является рубиновым явлением, оно также выполняется во всем javascript с отрицательными (IMO) эффектами.

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

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

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

Существует множество простых способов сделать патч обезьян действительно ужасным, например, возможность изменить работу основных функций, таких как ADDITION .

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

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

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

Ненависть моего питомца - это mootools, расширяющий объект function . Да, ты можешь это сделать. Вместо того, чтобы просто изучать, как работает 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 отстой!))

3 голосов
/ 16 ноября 2008

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

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

2 голосов
/ 11 марта 2009

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

1 голос
/ 16 ноября 2008

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

0 голосов
/ 16 ноября 2008

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

...