Si se permite la aplicación de parches mono tanto en Ruby y Python, ¿por qué es más controvertida en Ruby?

StackOverflow https://stackoverflow.com/questions/717506

Pregunta

En muchas conversaciones que he oído sobre Ruby en que las personas han expresado sus reservas sobre el idioma, el tema de la aplicación de parches mono aparece como una de sus principales preocupaciones.

Sin embargo, rara vez escucho los mismos argumentos expuestos en el contexto de Python aunque también se permite en el lenguaje Python.

¿Por qué esta diferencia?

¿Tiene Python incluye diferentes tipos de medidas de seguridad para minimizar los riesgos de esta función?

¿Fue útil?

Solución

Como programador de Python que ha tenido un sabor de Rubí (y le gusta), creo que hay algo de un paralelo irónico cuando Python estaba empezando a ser popular.

C y Java programadores ‘bash’ Python, afirmando que no era un lenguaje real, y que la naturaleza dinámica de sus tipos sería peligroso, y permitir a la gente a crear ‘malo’ código. Como Python se hizo más popular, y las ventajas de su tiempo de desarrollo rápido se hizo evidente, por no hablar de la sintaxis menos detallado:

// Java
Person p = new Person();
# Python
p = Person()

empezamos a ver algunas de las características más dinámicas aparecen en versiones posteriores de Java. Autoboxing y -unboxing que sea menos molesto para hacer frente a las primitivas, y los genéricos nos permite código una vez y lo aplicamos a muchos tipos.

Fue con cierta diversión que vi una de las características clave de Ruby flexibles - Mono de parches, siendo considerado como peligroso por la multitud de Python. Después de haber empezado a enseñar a los estudiantes de Ruby este año, creo que la posibilidad de ‘fijar’ la implementación de una clase existente, incluso uno que es parte del sistema, es muy potente.

Sin duda, puede arruinar mal y su programa puede bloquearse. Puedo segfault en C con bastante facilidad, también. Y aplicaciones de Java pueden morir en llamas muerte.

La verdad es que veo mono de parches como el siguiente paso en la programación dinámica y meta. Divertido, ya que ha estado presente desde Smalltalk.

Otros consejos

Es una técnica menos practicada en Python, en parte porque las clases "básicas" en Python (las implementadas en C) no son realmente modificable. En Ruby, por el contrario, debido a la forma en que se implementa internamente (no mejor, sólo diferente) casi cualquier cosa se puede modificar de forma dinámica.

Filosóficamente, es algo que tiende a ser mal visto en el seno de la comunidad Python, claramente menos por lo que en el mundo Ruby. No sé por qué usted afirma que es más controvertido (puede vincular a una referencia de autoridad?) - mi experiencia ha sido que el mono-aplicación de parches es una técnica aceptada si uno en el que el usuario debe ser consciente de las posibles consecuencias

Las lenguas pueden permitir, pero tampoco comunidad tolera la práctica. Monkeypatching no es tolerada en ambos idiomas, pero se entero de que más a menudo en Ruby porque la forma de clase abierta que utiliza hace que sea muy, muy fácil de monkeypatch una clase y debido a esto, que es más aceptable en la comunidad Ruby, pero todavía mal visto . Monkeypatching simplemente no es tan frecuente o tan fácil en Python, por lo que no se oye los mismos argumentos en contra de esa comunidad. Python no hace nada que Ruby no hace para impedir la práctica.

La razón por la que se oye / leer sobre él con más frecuencia en Ruby es que esta en Ruby:

class MyClass
  def foo
    puts "foo"
  end
end
class MyClass
  def bar
    puts "bar"
  end
end

le dará una clase que contiene dos métodos, foo y bar, mientras que esta en Python:

class MyClass:
    def foo(self):
        print "foo"
class MyClass:
    def bar(self):
        print "bar"

te dejará con una clase que sólo contiene el método bar, como la redefinición de una clase clobbers la definición anterior por completo. Para monkeypatch en Python, que realmente tiene que escribir lo siguiente:

class MyClass:
    def foo(self):
        print "foo"
def bar(self):
    print "bar"
MyClass.bar = bar

que es más duro que la versión de Ruby. Esto convierte el código Ruby mucho más fácil de monkeypatch de código Python.

"no Python incluye diferentes tipos de medidas de seguridad para minimizar los riesgos de esta función?"

Sí. La comunidad se niega a hacerlo. La salvaguardia es del todo social.

En realidad en Python que es un poco más difícil de modificar los tipos básicos.

Por ejemplo imaginemos, que se redefine entero.

Ruby:

class Fixnum 
   def *(n)
      5 
   end 
end

ahora 2 * 2 rendimientos 5.

Python:

>>> class int(int):
    def __mul__(self, x):
        return 5


>>> 2*2
4
>>> int(2)*int(2)
5

En Python, cualquier literal ("", {}, 1.0, etc) crea una instancia de la clase estándar, incluso si se trató de monkeypatch y redefinido la clase correspondiente en el espacio de nombres.

Simplemente no va a trabajar cómo se destinen:

class str():
    # define your custom string type
    ...

a = "foo"      # still a real Python string
a = str("foo") # only this uses your custom class

Creo que los parches mono sólo debe utilizarse como última solución.

Normalmente los programadores de Python saben cómo una clase o un método comportan. Ellos saben que la clase xxx es hacer las cosas de una determinada manera.

Cuando el mono parchear una clase o un método, que está cambiando su comportamiento. Otros programadores de Python que utilizan esta clase pueden ser muy sorprendido si esa clase se comporta de manera diferente.

La forma normal de hacer las cosas es la subclasificación. De esa manera, otros programadores sabe que están utilizando un objeto diferente. Pueden utilizar la clase original o la subclase si así lo desean.

Si usted quiere hacer algunos parches mono en Python, es relativamente fácil, siempre y cuando no se está modificando un tipo incorporado (int, float, str).

class SomeClass:
    def foo(self):
        print "foo"

def tempfunc(self):
    print "bar"
SomeClass.bar = tempfunc
del tempfunc

Esto añadirá el método bar a SomeClass y casos incluso existentes de esa clase puede usar ese método inyectado.

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