ruby monkeypatching solid-principles

ruby - Monkey-patching vs. Principios sólidos?



monkeypatching solid-principles (8)

Poco a poco voy pasando de PHP5 a Python en algunos proyectos personales, y actualmente me encanta la experiencia. Antes de elegir bajar por la ruta de Python, miré a Ruby. Lo que sí noté de la comunidad de rubíes fue que el parche de monos era común y muy respetado. También encontré muchas historias de terror con respecto a las pruebas de depuración de ruby ​​s / w porque alguien incluyó una biblioteca relativamente inofensiva para hacer un pequeño trabajo pero que remendaba algún objeto central muy usado sin decirle a nadie.

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

Esta noche he estado leyendo acerca de los principios SÓLIDOS de Robert Martin :

  • Principio de responsabilidad de Sling,
  • O pluma / principio cerrado,
  • Principio de sustitución L iskov,
  • I nterface el principio de segregación, y
  • Principio de inversión de deuda

Actualmente estoy hasta O : las ENTIDADES DE SOFTWARE (CLASES, MÓDULOS, FUNCIONES, ETC.) DEBEN ABRIRSE PARA SU EXTENSIÓN, PERO CERRADAS PARA SU MODIFICACIÓN .

Mi cabeza está dando vueltas sobre el conflicto entre garantizar la coherencia en el diseño de OO y todo lo relacionado con el parche de los monos. Entiendo que es posible hacer parches de mono en Python. También entiendo que ser "pitónico" es seguir las mejores prácticas y principios comunes, bien probados y a prueba.

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 monos se debe hacer ... espero que puedan resolverlo por mí.


En mi opinión, es útil tener monkeypatching, pero se puede abusar de algo. La gente tiende a descubrirlo y siente que debería usarse en todas las situaciones, donde quizás una mixin u otra construcción sea más apropiada.

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


El parche de mono no es explícito en ruby, está hecho en todo javascript también, con efectos negativos (IMO).

Mi opinión personal es que el parche de mono solo debe 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 lugar "lógico" para ello.

Hay muchas maneras fáciles de hacer el parche de mono realmente horrible, como la capacidad de cambiar el funcionamiento de funciones básicas como ADDITION .

Mi postura es, si puedes evitarlo, hazlo.

Si puedes evitarlo de una manera agradable, felicitaciones para ti.

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

Mi mascota odio es mootools extendiendo el objeto de función . Sí, usted puede hacer esto. En lugar de que la gente simplemente aprenda 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) de modo que las funciones ahora tienen sus propias funciones.

foo.delay( 5000 , args );

Lo cual tiene el efecto adicional de que este tipo de basura es válida:

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

Y así ad infinitum.

¿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 manera en que lo hicieron cuando usted aprende el idioma. idioma, y ​​en su lugar tiene que aprender un nuevo subconjunto de comandos para que no se caiga de bruces (¡a costa de excesivas ralentizaciones!)

¿Puedo observar 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 debes tener en cuenta la sobrecarga masiva utilizada para que esto sea viable.

clearTimeout(x);

¡MUY DIFÍCIL!

(Descargo de responsabilidad: ha pasado un tiempo desde que usé moo, y he tratado de olvidarlo, y los nombres / estructura de funciones pueden ser incorrectos. Esto no es una referencia de API. Por favor revisen su sitio para detalles (lo siento, ¡su referencia API es una mierda!) )


Mi primer pensamiento es que el parche de monos viola OCP, ya que los clientes de una clase deberían poder esperar que la clase trabaje de manera consistente.


Mokeypatching es generalmente incorrecto. Crea una subclase adecuada y agrega los métodos.

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

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

Debido a la estrecha vinculación entre el cliente de Django y el controlador de prueba Django, parecía más fácil suspenderlo para respaldar la prueba REST completa.


Monkey-patching es simplemente malo , en mi humilde opinión. No me he encontrado con el principio abierto / cerrado que mencionas antes, pero es un principio que me he mantenido por mucho tiempo, estoy de acuerdo con él al 100%. Pienso en el parche de monos como un olor codificado a mayor escala, un olor a filosofía de codificación, por así decirlo.


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

Aunque me gusta Ruby, siento que el parche de monos es 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.


Hay una diferencia entre el parche de mono (sobreescritura o modificación de métodos preexistentes) y la simple adición de nuevos métodos. Creo que este último está perfectamente bien, y el primero debe ser visto sospechosamente, pero aún estoy a favor de mantenerlo.

Me he encontrado con algunos de esos problemas en los que una extensión de un tercero pone parches en las bibliotecas principales y rompe las cosas, y realmente son una mierda. Desafortunadamente, todos invariablemente parecen provenir de los desarrolladores de extensión de terceros que toman el camino de la menor resistencia, en lugar de pensar cómo construir sus soluciones correctamente.
Esto apesta, pero ya no es culpa de parches de monos, sino de culpa de los fabricantes de cuchillos que a veces la gente se corta a sí misma.

Las únicas veces que he visto una necesidad legítima de parche de mono es solucionar los 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 tuvimos:

  1. Lea informes de errores extraños y resuelva el problema en un error menor en una biblioteca CLR.
  2. Invertir días viene con una solución que implica la captura de excepciones en lugares extraños y muchos hacks que compromete el código mucho
  3. Pasar días sacando una solución hacky cuando Microsoft lanza un service pack

Cronología de un error en un programa de rieles que tuvimos:

  1. Lea informes de errores extraños y trace el problema a un error menor en una biblioteca estándar de ruby
  2. Dedique 15 minutos a realizar un pequeño parche de mono para eliminar los errores de la biblioteca de rubíes, y coloque los protectores 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 tiene un aspecto similar, excepto con el parche de monopatín, es una solución de 15 minutos y una "extracción" de 5 segundos, mientras que sin ella, se produce dolor y sufrimiento.

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

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