Pregunta

Me estoy moviendo lentamente de PHP5 a Python en algunos proyectos personales, y actualmente me encanta la experiencia. Antes de elegir ir por la ruta de Python, miré a Ruby. Lo que sí noté de la comunidad de rubíes fue que los parches de mono eran comunes y muy respetados. También me encontré con un lote de historias de horror con respecto a los ensayos de depuración de ruby ??s / w porque alguien incluía una biblioteca relativamente inofensiva para hacer un pequeño trabajo, pero que parcheaba un objeto central muy usado sin decírselo a nadie.

Elegí Python por (entre otras razones) su sintaxis más limpia y el hecho de que podía hacer todo lo que Ruby podía hacer. Python está haciendo que el clic OO sea mucho mejor que PHP, y estoy leyendo más y más sobre los principios OO para mejorar esta mejor comprensión.

Esta noche he estado leyendo sobre principios SOLID de Robert Martin:

  • S principio de responsabilidad individual,
  • O lápiz / principio cerrado,
  • L principio de sustitución de iskov,
  • I principio de segregación de interfaz, y
  • D principio de inversión de dependencia

Actualmente estoy hasta O : LAS ENTIDADES DE SOFTWARE (CLASES, MÓDULOS, FUNCIONES, ETC.) DEBEN ESTAR ABIERTOS PARA EXTENSIÓN, PERO CERRADOS PARA MODIFICACIÓN .

Me da vueltas la cabeza por el conflicto entre garantizar la coherencia en el diseño OO y todo el parche de mono. Entiendo que es posible hacer parches de mono en Python. También entiendo que ser '' pitón '' es seguir las mejores prácticas comunes y bien probadas, y amp; principios.

Lo que me gustaría saber es la opinión de la comunidad sobre los dos temas opuestos; cómo interactúan, cuando es mejor usar uno sobre el otro, si el parche de mono debe hacerse en todos ... espero que puedan proporcionarme una resolución al asunto.

¿Fue útil?

Solución

Hay una diferencia entre parchear mono (sobrescribir o modificar métodos preexistentes) y la simple adición de nuevos métodos. Creo que lo último está perfectamente bien, y lo primero debería ser considerado sospechosamente, pero todavía estoy a favor de mantenerlo.

He encontrado bastantes problemas en los que una extensión de terceros parchea las bibliotecas centrales y rompe cosas, y realmente apestan. Desafortunadamente, todos parecen invariablemente que los desarrolladores de extensiones de terceros toman el camino de menor resistencia, en lugar de pensar en cómo construir sus soluciones correctamente.
Esto apesta, pero no es más culpa del parche de los monos que de los fabricantes de cuchillos que las personas a veces se cortan.

Las únicas veces que he visto la necesidad legítima de parches de monos es evitar errores en bibliotecas de terceros o centrales. Solo por esto, no tiene precio, y realmente me decepcionaría si eliminaran la capacidad de hacerlo.

Cronología de un error en un programa de C # que teníamos:

  1. Lea informes de errores extraños y rastree el problema a un error menor en una biblioteca CLR.
  2. Invierta días para encontrar una solución alternativa que implique la captura de excepciones en lugares extraños y muchos hacks que comprometan mucho el código
  3. Dedique días a la difícil solución alternativa cuando Microsoft lance un paquete de servicio

Cronología de un error en un programa de rieles que teníamos:

  1. Leer informes de errores extraños y rastrear el problema a un error menor en una biblioteca estándar de ruby ??
  2. Pase 15 minutos realizando un parche de mono menor para eliminar el error de la biblioteca de ruby, y coloque guardias a su alrededor para disparar si se ejecuta en la versión incorrecta de ruby.
  3. Continuar con la codificación normal.
  4. Simplemente elimine monkeypatch más tarde cuando se lance la próxima versión de ruby.

El proceso de corrección de errores es similar, excepto con el parche de mono, es una solución de 15 minutos y una 'extracción' de 5 segundos, mientras que sin él, se produce dolor y sufrimiento.

PD: El siguiente ejemplo es "técnicamente" parchado de mono, pero ¿es moralmente? parche de mono? No estoy cambiando ningún comportamiento, esto es más o menos solo hacer AOP en ruby ??...

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

Otros consejos

En mi opinión, es útil tener monkeypatching pero algo de lo que se puede abusar. Las personas tienden a descubrirlo y sienten que debería usarse en todas las situaciones, donde tal vez un mixin u otro constructo sea más apropiado.

No creo que sea algo que debas prohibir, es algo que a los chicos de Ruby les gusta usar. Puede hacer cosas similares con Python, pero la comunidad ha tomado la postura de que las cosas deberían ser más simples y más obvias.

El parcheado de mono no es explícito en rubí, también se realiza en todo JavaScript, con efectos negativos (IMO).

Mi opinión personal es que los parches de mono solo deben hacerse para

a) Agregue funcionalidad a una versión anterior de un idioma que esté disponible en la nueva versión del idioma que necesita.

b) Cuando no hay otro "lógico" lugar para ello.

Hay muchas maneras fáciles de hacer que los parches de mono sean realmente horribles, como la capacidad de cambiar el funcionamiento de funciones básicas como ADICION .

Mi postura es, si puedes evitarlo, hazlo.

Si puedes evitarlo de una manera agradable, te felicito.

Si no puede evitarlo, obtenga la opinión de 200 personas porque probablemente no lo haya pensado lo suficiente.

Mi odio a las mascotas son herramientas móviles que extienden el objeto función . Sí, usted puede hacer esto. En lugar de que las personas simplemente aprendan cómo funciona JavaScript:

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

Se agregó un nuevo método a cada objeto de función (sí, no estoy bromeando) para que las funciones ahora tengan sus propias funciones.

foo.delay( 5000 , args );

Que tuvo el efecto adicional de que este tipo de basura es válida:

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

Y sigue así hasta el infinito.

¿El resultado? Ya no tiene una biblioteca y un idioma, su idioma se inclina ante la biblioteca y si la biblioteca está dentro del alcance, ya no tiene un idioma y no puede hacer las cosas de la forma en que se hicieron cuando aprende el idioma, y ??en su lugar tiene que aprender un nuevo subconjunto de comandos solo para que no se caiga de bruces (¡a costa de ralentizaciones excesivas!)

¿puedo notar que foo.delay también devolvió un objeto, con sus propios métodos, por lo que podría hacer

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

e incluso

 x.clear.delay(10); 

que puede sonar demasiado útil, ... pero debe tener en cuenta la sobrecarga masiva utilizada para hacer esto viable.

 clearTimeout(x); 

¡TAN DURO!

(Descargo de responsabilidad: ha pasado un tiempo desde que usé moo, y he tratado de olvidarlo, y los nombres / estructura de la función pueden ser incorrectos. Esto no es una referencia de API. Por favor, consulte su sitio para obtener más detalles (lo siento, su referencia API es una mierda!))

Mokeypatching es generalmente incorrecto. Cree una subclase adecuada y agregue los métodos.

He usado monkeypatching una vez en el código de producción.

El problema es que REST usa GET, POST, PUT y DELETE. Pero el cliente de prueba de Django solo ofrece GET y POST. He aplicado métodos parcheados para PUT (como POST) y DELETE (como GET).

Debido a la estrecha vinculación entre el cliente de Django y el controlador de prueba de Django, me pareció más fácil parchearlo para admitir la prueba REST completa.

Puede encontrar esta discusión sobre las clases abiertas de Ruby y el Principio Abierto-Cerrado.

Aunque me gusta Ruby, siento que los parches de mono son una herramienta de último recurso para hacer las cosas. En igualdad de condiciones, prefiero usar las técnicas tradicionales de OO con una pizca de bondad de programación funcional.

En mis ojos, los parches de mono son una forma de AOP. El artículo Principios de diseño orientado a aspectos: lecciones del diseño orientado a objetos (PDF) ofrece algunas ideas sobre cómo SOLID y otros principios de OOP pueden aplicarse a AOP.

Mi primer pensamiento es que los parches de mono violan OCP, ya que los clientes de una clase deberían poder esperar que esa clase funcione de manera consistente.

Los parches de mono son simplemente incorrectos , en mi humilde opinión. No he encontrado el principio abierto / cerrado que mencionas antes, pero es un principio que he sostenido durante mucho tiempo, estoy de acuerdo con él al 100%. Pienso en el parche de mono como un olor a código a mayor escala, un olor a filosofía de codificación, por así decirlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top