2009-05-18 26 views
6

Soy un codificador de Ruby. Para mí, monkeypatching es cambiar, en tiempo de ejecución, métodos de clases o módulos en un proyecto externo. Lo que me interesa, es qué mecanismo tiene en su lugar que lo protegerá de algunos de los abusos de esa bonita función. Sigue, algunos escenarios que he encontrado, donde monkeypatching me ha mordido.¿Cómo maneja Smalltalk con monkeypatching?

Aunque no conozco Smalltalk en absoluto, ese lenguaje ha estado allí mucho antes que Ruby. Hice algunas investigaciones para ver si Smalltalk resolvió algunos de estos problemas y cómo lo hizo, pero no encontró mucho en Google. Así que aquí estoy, preguntando por Smalltalkers si pueden compartir su sabiduría.

Escenario A: bug fijación conflicto

Proyecto A y B dependen de proyecto C. Proyecto C tiene un error. Los lanzamientos del Proyecto A y B contienen una solución para el proyecto C.

Si su código usa el Proyecto A y B, ¿cómo puede saber que los parches no entrarán en conflicto?

Escenario B: insecto anticuado fijación de

Proyecto C libera una versión menor fija de su proyecto.

Si carga el proyecto A, ¿aún se aplicará el parche, con posible rotura? Me interesa saber si hay algún mecanismo en funcionamiento, por ejemplo, para no cargar el parche si el código está solucionado.

Escenario C: extensiones en conflicto

Proyecto A y B proyecto de uso de clase C de Foo. Ambos agregan un método de utilidad a Foo, digamos, #toDate. La versión toDate de A devuelve una cadena de fecha y la de B un objeto Fecha.

Si carga ambos proyectos (con C dep), ¿hay algún mecanismo que advierta/prevenga el conflicto? ¿O tendrá que esperar hasta que el tiempo de ejecución arroje un error debido a una expectativa incorrecta en un método?

Sobre la actualización pregunta

La lectura de las respuestas, se dan cuenta de que mi pregunta era demasiado amplio y vago. Así que aquí hay una versión reescrita de esto.

+0

es la capacidad de monkeypatch realmente un problema? – CookieOfFortune

+0

Sus críticas al monopatching parecen bastante lejanas. No hay nada inherente en el monopatching que conduzca a abstracciones que goteen más que en el diseño inicial de la clase. Tampoco es intrínsecamente más "difícil" que otros códigos. Dividir un objeto en diferentes archivos es cierto, aunque algunos argumentarían que tener módulos manejables es algo bueno; de hecho, se considera una buena práctica agrupar la funcionalidad relacionada en Objective-C. Quizás sus problemas son más con los codificadores que con las características del lenguaje. – Chuck

+0

En cualquier cae, la noción de dividir cosas en archivos separados está fuera de lugar; smalltalk no hace las cosas de esa manera. –

Respuesta

1

Dice "¡Sí! ¡Adelante!"

Toda la idea realmente apareció primero en Smalltalk.

Vaya a la clase raíz en el explorador de clases, y puede agregar todos los métodos a la imagen que desee.

Recuerde, sin embargo, que Smalltalk tiene una imagen muy diferente del mundo que los otros idiomas habituales (el único otro común, como Smalltalk fue APL). Usted tiene una imagenque contiene el conjunto de código y tiempo de ejecución paquete. Cuando cambias la imagen, cada bit de código en la imagen se ve afectado. Otras imágenes no son cambiadas Puede tener conjuntos de cambios para volver a cargar sus hacks favoritos, pero básicamente están importando código en la imagen.

1

Los Smalltalkers no usan el término 'parche de mono', pero tengo la sensación de que el 'método predominante' es el término más cercano.Es decir, anula un método de una clase en el paquete A, con un método de la misma clase en el paquete B. Por lo tanto, cuando carga un paquete B, se anula el método original en A.

Las anulaciones de método tienen sus ventajas pero son mucho más desventajosas cuando no se usan con cuidado, por lo que en general tendemos a evitarlas. También depende del dialecto Smalltalk: en VisualWorks, por ejemplo, las herramientas admiten anulaciones bastante bien, mientras que en Squeak no es así.

+0

+1 por reconocer la importancia del uso de términos en cada (sub) cultura, -1 por confundir con anulación de método (una cosa totalmente diferente) – Javier

+0

Obviamente no es algo tan diferente, después de leer el artículo de Wikipedia sobre el parche de monos. Bueno, parece que en Smalltalk somos parches de mono simplemente cambiando algún método en una imagen en vivo. Estamos haciendo eso todo el tiempo de todos modos. –

+0

En Newspeak, es realmente el mismo :) –

5

En Smalltalk, tradicionalmente hemos llamado a esto primordial. Dependiendo de las herramientas de control de versiones que use con Smalltalk, usted tampoco;

  • crear una nueva versión del paquete que originalmente poseía la clase/método (s) de que se trate
  • crear un nuevo paquete, que será el propietario de la sustitución de la clase/método (s) de que se trate

En VisualWorks y ObjectStudio (el Smalltalk con el que estoy más familiarizado), se utiliza este último enfoque. En VA Smalltalk, donde se utiliza Envy, se adopta el enfoque anterior. Creo que Squeak seguiría el último enfoque usando Monticello, pero no estoy del todo seguro.

En la mayoría de las implementaciones de Smalltalk, es fácil ver tanto la versión original del código reemplazado como la anulación actualmente instalada.

En las aplicaciones cliente, las anulaciones realmente solo le afectan cuando actualiza a una nueva versión de Smalltalk del venor (o del equipo Squeak, et al.). Para aplicaciones de servidor, donde múltiples aplicaciones pueden residir en el servidor, debe ser mucho más cuidadoso con lo que decida hacer.

Las modificaciones (o parches de mono, como las llama) son una herramienta poderosa, pero debe tener cuidado sobre cómo usarlas, y si las usa, debería volver a examinar si las necesita en una base regular. En mi agregador de noticias de código abierto, BottomFeeder, he eliminado muchas de las modificaciones que establecí inicialmente.

0

Respondiendo a mí mismo, aquí está mi punto de vista actual:

Escenario A y B

Dado que todo el código es abierto, lo mejor sería fijar el proyecto rota directamente. Las herramientas como código de administración de git ya se fusionan, por lo que no necesitamos depender de un mergin en tiempo de ejecución, que no siempre funcionaría.

Dependiendo de la disposición de la versión anterior para fusionar la solución y la velocidad para lanzar una nueva versión, puede prever producir un monopatch. En ese caso, lo mejor sería contar con un mecanismo que dicen:

monkeypatch(ClassName, :method, &newcode) of the broken project 
is applied if project.version in [a set of releases where the bug exist] 
if the project version is unknown to the monkeypatch, 
    raise an error to tell the developer to fix the monkeypatch (check if bug exist). 
if a monkeypatch for that project, classname and method already exist, yell 

Se trata de la parte superior de la cabeza. Podría ser problemático si una corrección de errores requiere más que un cambio de método.

Escenario C: TODO

+0

Para el escenario C, la mejor forma de evitar conflictos es utilizar el espacio de nombres del selector, así que si tiene paquete Foo y paquete Bar, ambos desean extender el comportamiento de alguna clase, como agregar #toDate: método , lo extiendes 2 veces: el paquete Foo se extiende usando fooToDate: nombre, y el paquete Bar, - barToDate:. y el problema ha desaparecido :) –