2010-12-07 6 views
9

Solía ​​hacer una gran cantidad de programación web en Rails (PHP antes de eso) antes de comenzar a estudiar ingeniería informática.¿Cansado de las pruebas no semánticas para compensar el tipado dinámico? ¿Sugerencias?

Desde entonces, he hecho un montón de trabajo escolar en C, y algunas cosas personales en Objective-C (cosas de Mac). Aprendí a amar la escritura estática.

Pero ahora tengo que hacer un poco de desarrollo web profesional (freelance) y he recogido Rails una vez más. Me resulta realmente molesto escribir pruebas de verificación de tipo no semánticas. Los obtuve de forma gratuita de los compiladores C y Objective-C. Me encantó presionar Crear y hacer que el sistema verificara todo mi código para ver que A puede llamar a B, B puede llamar a una oscura biblioteca C, etc. Todo lo que tenía que hacer era probar la semántica. Pero con Rails, soy el compilador. :(

¿Alguien treaded este mismo camino son mis únicas opciones para el desarrollo web ASP.NET MVC con C# y Java + x marco Buscando algunas sugerencias, o incluso algo de simpatía ...?: P?

Por cierto, hago una referencia específica a Rails en lugar de a Ruby porque no me importa la naturaleza dinámica de Ruby para cosas simples como secuencias de comandos o lo que no. Pero como Rails depende de tantas gemas y ya que uno generalmente agrega una serie de otras gemas , el tipado dinámico convierte en un problema

Gracias

edición:.!

Seguí la sugerencia de pst y busqué en Scala. Al leer el libro Programación en Scala, escrito por el creador del lenguaje, Martin Odersky, encontré este texto que de muchas maneras expresa mis preocupaciones y un poco más. Lectura muy interesante.

tomado de la página 52 de Programación de Martin Odersky en Scala:

Scala se escribe de forma estática

Un sistema de tipo estático clasifica variables y expresiones de acuerdo con los tipos de valores que desempeñe y cálculo. Scala se destaca como un lenguaje con un sistema de tipo estático muy avanzado . Partiendo de un sistema de tipos de clases anidadas muy similar a Java, le permite parametrizar los tipos con genéricos, para combinar tipos usando intersecciones , y para ocultar detalles de tipos usando tipos abstractos. Estos dan una base sólida para la construcción y componiendo sus propios tipos, de modo que pueden diseñar interfaces que están en el mismo tiempo seguro y flexible para usar.

Si te gusta lenguajes dinámicos como Perl, Python, Ruby, o Groovy, que que le resulte un poco extraño que el sistema de tipo estático de Scala aparece como uno de sus puntos fuertes. Después de todo, la ausencia de un sistema estático de tipo ha sido citada por algunos como una gran ventaja de de los lenguajes dinámicos. Los argumentos más comunes contra tipos estáticos son que hacen programas demasiado prolijo, impiden programadores de expresarse como lo deseen, y hacen imposibles ciertos patrones de dinámicas modificaciones de los sistemas de software.

Sin embargo, a menudo estos argumentos no van en contra de la idea de tipos estáticos en general, pero en contra de sistemas específicos de tipo , que son percibidos a ser demasiado prolijo o demasiado inflexible. Para instancia, Alan Kay, el inventor de el lenguaje Smalltalk, una vez comentó: "No estoy en contra de los tipos, pero no conozco de ningún tipo de sistema que no sea un dolor completo, así que todavía me gusta dinámica escribir “

Esperamos que convencer en este libro que el sistema de tipo de Scala está lejos de ser un‘dolor total’de hecho, direcciones muy bien dos de los habituales preocupaciones acerca de tipos estáticos..: se evita la verbosidad a través del tipo se obtiene inferencia y flexibilidad a través de la coincidencia de patrones y varias formas nuevas de escribir y componer tipos. Con estos impedimentos fuera del camino, se pueden apreciar mejor los beneficios clásicos de los sistemas de tipo estático . Entre los más importantes de estos , los beneficios son propiedades verificables de abstracciones de programa, refactorizaciones seguras, y mejor documentación de .

propiedades verificables

sistemas de tipo estático pueden probar la ausencia de ciertos errores en tiempo de ejecución. Por ejemplo, pueden probar propiedades como: booleanos nunca son agregados a enteros; no se puede acceder a las variables privadas desde fuera de su clase ; las funciones se aplican al número correcto de argumentos ; solo se agregan cadenas a un conjunto de cadenas .

Otros tipos de errores no se detectan por los sistemas de tipo estático de hoy. Para la instancia , generalmente no detectarán funciones no terminadas, violaciones de límites de matriz , o divisiones por cero. Tampoco detectarán que su programa no se ajusta a su especificación (¡suponiendo que haya una especificación , eso es!). Los sistemas de tipo estático han sido descatalogados como por no ser muy útiles. El argumento indica que dado que tales sistemas tipo pueden detectar solo errores simples, mientras que las pruebas unitarias proporcionan una cobertura más amplia , ¿para qué preocuparse con los tipos estáticos ?

Creemos que estos argumentos fallan el punto.Aunque un sistema estático de tipo no puede reemplazar las pruebas de la unidad , puede reducir el número de pruebas de unidad necesarias al tener en cuenta algunas propiedades que de lo contrario deben probarse. Del mismo modo, la prueba de la unidad no puede reemplazar el tipado estático. Después de todo, como dijo Edsger Dijkstra, las pruebas solo pueden probar la presencia de errores , nunca su ausencia. Por lo tanto, el garantiza que el tipado estático da puede ser simple, pero son reales garantías de un formulario que ninguna cantidad de prueba puede entregar.

refactorizaciones seguras

Un sistema de tipo estático proporciona una red de seguridad que le permite hacer cambios a una base de código con un alto grado de confianza . Considere por ejemplo una refactorización que agrega un parámetro adicional a un método. En un lenguaje tipado estáticamente puede hacer el cambio, volver a compilar su sistema y simplemente corregir todas las líneas que causan un error de tipo. Una vez que haya terminado con esto, es seguro que ha encontrado todos los lugares que necesitan ser cambiados. Lo mismo vale para muchas otras refactorizaciones simples como cambiando el nombre de un método, o moviendo los métodos de una clase a otra. En en todos los casos, una comprobación de tipo estático será y proporcionará suficiente seguridad de que el nuevo sistema funciona igual que el anterior.

Documentación

tipos estáticos son documentación del programa que se comprueba por el compilador para corrección. A diferencia de un comentario normal, una anotación de tipo nunca puede estar fuera de la fecha (al menos no si el archivo fuente que lo contiene ha pasado recientemente un compilador ). Además, los compiladores y los entornos de desarrollo integrados pueden hacer uso de las anotaciones de tipo para proporcionar una mejor ayuda de contexto. Para ejemplo, un entorno de desarrollo integrado puede mostrar todos los miembros disponibles para una selección por determinar el tipo estático de la expresión en el que la selección es hecha y mirando hacia arriba todos los miembros de ese tipo.

+0

¿Tiene un ejemplo que muestra por qué este tipo de prueba es necesaria al realizar el desarrollo de Rails? – zetetic

+0

Zetetic: propio banco de pruebas de Rails tiene ejemplos inumerous, como https://github.com/rails/rails/blob/master/activerecord/test/cases/calculations_test.rb test_count_with_too_many_parameters_raises def assert_raise (ArgumentError) {Cuenta .contar (1, 2, 3)} extremo https://github.com/rails/rails/blob/master/activerecord/test/cases/associations_test.rb def test_include_with_order_works assert_nothing_raised {Account.find (: primero ,: order => 'id',: include =>: firm)} assert_nothing_raised {Account.find (: first,: order =>: id,: include =>: firm)} end – Alexandre

+0

Alguien ha intentado escribir ASP MVC con F #? – Gabe

Respuesta

7

Esta es una de mis "quejas" sobre los lenguajes dinámicos. Quiero probar la semántica, no escribir errores ;-) Dicho esto, un buen marco/configuración de prueba es realmente una necesidad en todas las situaciones no triviales y una buena cobertura de código y requisitos probados es/son importantes.

Si quiere ir por la ruta de tipado estático en la JVM (tengo), le recomiendo mirar Scala. Viniendo de Ruby, es mucho menos doloroso (y en realidad es muy divertido de diferentes maneras) que ir a Java. Puedes "mantener" las cosas que das por sentado: una sintaxis basada en expresiones, cierres, la capacidad de omitir tipos en muchos lugares (no tan abiertos como Ruby, pero obtienes comprobación de tipos en tiempo de compilación ;-), todo (*) - OO is-an-object, métodos de acceso unificado, capacidad de construir DSL fácilmente y azúcar, y obtener los beneficios de un lenguaje estáticamente tipado con inferencia de tipo local, coincidencia de patrones, un marco de recopilación relativamente rico y integración decente con Java (incluidos los numerosos marcos web, también hay algunos marcos específicos de Scala que aprovechan el lenguaje Scala).

C# 3.0/4.0 (y .NET3.5 +) no es demasiado mal ya sea (pero evitar C# 2.0, que ahora es de esperar que un vestigio), con la introducción de LINQ/cierres, tipo básico inferencia y otras características agradables del lenguaje La considero "aceptable" para la mayoría de las tareas (adivine cómo calificaría Java como un lenguaje ;-). Sin embargo, C# es un lenguaje CLR-target (hay/había un puerto .NET Scala, pero no estoy seguro del estado, aunque no es la plataforma principal).

Como mencioné Scala, también debería mencionar F # (ahora un lenguaje .NET "oficial") que toma el enfoque "Funcional con OO" siendo similar a OCaml - Scala es más bien al revés y describiría como "OO con funcional". He escuchado argumentos a favor/en contra de F # en comparación con C# w.r.t el sistema de tipo, pero no tengo experiencia práctica con F #. Puede que te guste o no el cambio de paradigma.

Happy coding.

+0

Hola pst. Gracias por dirigirme a Scala. Empecé a leer el libro Programación en Scala y parece poner todas mis garras. Echa un vistazo a mi pregunta actualizada con un poco de texto del libro. – Alexandre

1

Este tipo de prueba no se suele realizar en Rails. En lugar de molestarte por tener que hacerlo, considera no preocuparte por ello. O tal vez haga un mejor trabajo al explicar por qué cree que es un problema, ya que la mayoría de los programadores de Rails no lo hacen.

actualización

La persona que escribió test_include_with_order_works es asegurarse de que los carriles interpretará un símbolo de la misma como una cadena en este caso particular. Eso no parece ser algo que deba probar, ya que Rails ya ha proporcionado y probado esta funcionalidad para usted.Francamente, estoy un poco sorprendido de que alguien se preocupe si un símbolo funcionará o no como una cadena. Todos sabemos que puede y a menudo lo hace.

En general, creo que el framework de Rails debe garantizar cosas que no se hacen para que su implementación se ajuste a su diseño. Creo que la filosofía de trabajo en los lenguajes de tipado dinámico es que el código del cliente no pasará los parámetros que romperán los métodos que están llamando. Si lo hacen, no tienen ningún uso para llamar a los métodos. No tiene que perder el tiempo asegurándose de que sus métodos generen excepciones cuando se proporcionan demasiados parámetros, cuando su método puede tan fácilmente (y debería) ignorar los parámetros adicionales.

Por lo tanto, no estoy seguro de si los ejemplos que ha proporcionado realmente demuestran la necesidad de realizar pruebas no semánticas en Rails.

+0

Hola Samo, publiqué una respuesta al comentario de zetetic sobre mi pregunta que también aborda tu comentario. La base de pruebas de Rails tiene numerosas pruebas como esas. – Alexandre

+0

@Alexandre: actualizó mi respuesta – Samo

2

Como mencionas Rails, y dado que te has interesado por Scala, definitivamente deberías marcar Lift. Aquí hay un 2008 interview con su creador y un 2009 presentation (video), que enlazo porque, aunque antiguo, comparan Lift con alternativas en otros idiomas.

Si levantar no es lo tuyo, puedes estar seguro de que hay other Scala web frameworks.

Cuestiones relacionadas