2009-09-28 26 views
5

Siempre trabajé en lenguajes tipados estáticos (C/C++, Java). He estado jugando con Clojure y realmente me gusta.De la escritura estática a la escritura dinámica

Una cosa que me preocupa es: decir que tengo una ventana que toma 3 módulos como argumentos y en el camino los requisitos cambian y necesito pasar otro módulo a la función. Solo cambio la función y el compilador se queja en todas partes donde lo usé. Pero en Clojure no se quejará hasta que se llame a la función. Puedo hacer una búsqueda y reemplazo de expresiones regex pero parece que hay una posibilidad de perder una llamada y pasará desapercibida hasta que realmente se llame a esa función. ¿Cómo lidian ustedes con esto?

+4

¿Cómo pueden lidiar con esto? En mi experiencia, la respuesta correcta sería "No muy bien". –

Respuesta

8

Esta es una de las razones por las que el desarrollo automatizado de pruebas/pruebas es incluso más importante en los lenguajes de tipado dinámico. No he usado Clojure (uso principalmente Ruby), así que desafortunadamente no puedo recomendar un marco de prueba específico.

+2

+1. esencialmente, el sistema de tipo estático es solo un conjunto autogenerado de pruebas unitarias (como le gusta señalar a uno de mis amigos evangelizadores dinámicos). Debe codificarlos a mano en el lenguaje dinámico, lo que le brinda mayor flexibilidad pero también un mayor esfuerzo. Depende de usted y de su diseño particular decidir si esa compensación está a favor de un lenguaje dinámico o estático. – rmeador

+1

se pasa por alto el hecho de que lidiar con el sistema de tipo estático requiere esfuerzo. La pregunta es, ¿cuál es mayor? – jshen

+2

@jshen: ¿pero cuánto esfuerzo? En un * buen * lenguaje tipado estáticamente, puede olvidarse que está tipado estáticamente. Solo en basura como la familia C de idiomas, tienes que recordar constantemente al compilador los tipos de todo. – jalf

0

Pierde cierto nivel de refactorización y escribe seguridad cuando se mueve a lenguajes dinámicos. Cuanta más información tenga el compilador, más podrá hacer en tiempo de compilación para usted.

+0

Disculpe mi ignorancia, pero ¿cómo la escritura dinámica hace que pierda cierto nivel de refactorización? – khelll

+0

Probablemente signifique "refactorización automática" aquí. –

+0

Creo que la oración significa "seguridad de refactorización". – DigitalRoss

0

Tim Bray lo discute here, crítica de la cual por Cedric es here, y post en artima discutiéndolo extensamente.

3

Lo primero que que me gustaría mencionar es que Bruce Eckel ha escrito un artículo muy interesante llamado Strong Typing vs Strong Testing (el enlace está inactivo en este momento, por desgracia, pero espero que sea pronto).

Su idea es que cuando se trata de lenguajes compilados, el compilador solo actúa como el primer paso automático de prueba automática. Cuando realice el cambio a un lenguaje dinámico, perderá este primer nivel de prueba automática. Pero en ambos casos, este primer nivel automático es solo una parte de las pruebas, y ni siquiera una parte muy importante.

Su punto es que si está desarrollando programas correctamente, es decir, haciendo algún tipo de pruebas y pruebas de regresión, la falta de un compilador solo lo obligará a agregar algunas pruebas más básicas, de todos modos, por lo que no es gran pérdida.

Así que supongo que la primera respuesta que le doy es, concéntrese en sus pruebas, algo que debería hacer de todos modos, y tales cambios no deberían afectarlo demasiado.

Lo segundo que me gustaría mencionar es que muchos lenguajes dinámicos que he visto (por ejemplo, Python) tienen mejores habilidades para cambiar los métodos/clases sin romper el código existente.

Por ejemplo, con Python, si su método solía aceptar dos parámetros pero ahora requiere un tercero, siempre puede agregar un parámetro predeterminado sin romper ningún código existente, pero que ahora puede utilizar. Esta es una técnica muy básica, pero en el caso de Python (y supongo que la mayoría de los otros lenguajes dinámicos también), estas técnicas pueden ser mucho más interesantes; dado que son dinámicos, puede cambiar prácticamente la implementación de funciones para módulos específicos, cambiar lo que significan las variables, etc.

Sugiero ver qué técnicas tiene Clojure que permiten cosas similares, y decidir si se aplican en tu situación

1

La cobertura de la prueba es definitivamente importante. Pero un lenguaje de tipeo dinámico te permitirá trabajar de una manera diferente. En un lenguaje fuertemente tipado (como Java), un cambio en la interfaz debe modificar todas las personas que llaman. En Ruby, podrías hacer esto, pero probablemente no lo harás.En su lugar, probablemente agregará flexibilidad al método en una de varias maneras. A saber:

  • tiende a tener muy pocos métodos que toman hasta tres parámetros en Ruby (a diferencia de Java). Debido a que no tiene una interfaz sólida de Java, puede dividir el problema en partes y pasos más pequeños. Es mucho más común escribir métodos que toman solo 1 parámetro, y luego refactorizar cuando se vuelve más complejo.
  • es posible-- y común-- dejar el comportamiento anterior en su lugar al agregar más argumentos. Por ejemplo, si tiene que agregar un tercer argumento a un método de dos argumentos, establecerá su valor predeterminado para preservar el comportamiento anterior (y le ahorrará un refactor). Si está familiarizado con las bibliotecas de Javascript como jQuery, se aprovechan de esto en todas partes con argumentos "opcionales".
  • similar a los argumentos opcionales, los métodos pueden crecer para tomar una lista de parámetros flexible. Con una sólida cobertura de prueba, puede agregar fácilmente un nuevo comportamiento a un método existente y saber con seguridad que no ha roto el código existente. En Rails, métodos como "render" toman una amplia gama de opciones.
2

Hace lo mismo que hizo si el método era parte de una interfaz pública de la que no era el único usuario.

Agregue un nuevo método con el módulo extra y cambie el antiguo para llamar al nuevo con un valor predeterminado adecuado.

Ah, y si su programa es tan grande, asegúrese de que tiene buenas pruebas (prueba de SI debe hacer más simple que Java)

1

no está completamente sin el apoyo del compilador en Clojure. En el ejemplo específico que das, es la ariadidad de la función que cambió, que se recogió compilando el código de Clojure. ¡Todavía estoy haciendo una transición de tipeo dinámica y fuerte y encuentro esto reconfortante!

Cuestiones relacionadas