Al elaborar el diseño de un nuevo sistema, ¿es mejor comenzar con un lenguaje de tipo estático (como Haskell) o un lenguaje de tipo dinámico (como Ruby)?
Argumentos en los que puedo pensar:
Con un lenguaje estático, puede crear rápidamente una especificación y alcance para lo que hará el programa. Con un lenguaje dinámico, puede crear rápidamente una demostración funcional para presentar al cliente para su revisión.
Con un lenguaje dinámico, a menudo evita tener que reorganizar las estructuras de datos y refactorizar el código cuando cambia su diseño. Con un lenguaje estático, puede definir tipos antes de la implementación, manteniendo el código para mantenerlo muy pequeño.
Con un lenguaje estático, debe averiguar de antemano qué hará su programa. Con un lenguaje dinámico, puede comenzar a escribir código y dejar que el diseño crezca orgánicamente. Como dice Paul Graham en Hackers and Painters :
Un lenguaje de programación es para pensar en programas, no para expresar programas que ya has pensado.
Con un lenguaje estático, el compilador puede ayudar a identificar muchos tipos de errores. Con un lenguaje dinámico, puede comenzar a probar y encontrar errores antes.
La tipificación estática y dinámica tiene ventajas y desventajas en lo que respecta a la creación de prototipos. Sin embargo, ambos me parecen enfoques igualmente válidos. Según sus experiencias, ¿cuál es mejor en última instancia?
Notas
Prototipos en lenguaje natural
Un tercer tipo de lenguaje a considerar: el lenguaje natural. En lugar de crear prototipos en el código, uno puede crear un prototipo por escrito. El cliente puede leer su documentación y criticar su diseño desde el principio, pero no puede jugar con una demostración funcional. Si está bien escrito, la documentación puede facilitar la implementación en cualquier idioma. Advertencias:
La documentación puede ser tediosa de leer y difícil de digerir sin poder verla. Especulo que un cliente preferiría experimentar con algo que funciona en lugar de leer un muro de texto (e imágenes).
Crear prototipos de una aplicación en inglés en lugar de en definiciones de tipo es más detallado y menos concreto.
Los tipos de Haskell son descriptivos
Tenga en cuenta que los tipos son particularmente descriptivos en Haskell, más que en muchos lenguajes estáticos como C ++ y Java. Por ejemplo, supongamos que tengo una función con este tipo de firma en Haskell:
foo :: forall a. [a] -> a
Una función que, para cualquier tipo a
, toma una lista de elementos de tipo a
y devuelve un valor de tipo a
.
Incluso sin saber el nombre de la función, sé con certeza que:
No realiza entrada / salida ni modifica ningún valor (bueno, a menos que use unsafePerformIO incorrectamente), porque Haskell es puramente funcional.
No puede tratar los elementos como, por ejemplo, enteros, porque tiene que admitir cualquier tipo.
Se tiene que utilizar la lista de entrada (que, o lanzar una excepción o entrar en un bucle infinito). De lo contrario, ¿de dónde obtendría un valor de tipo
a
?
Por lo tanto, lo único que podría hacer esta función (aparte de fallar) es extraer un elemento de la lista de entrada y devolverlo. Aunque todavía no sé qué artículo usará, [a] -> a
me cuenta casi todo lo demás.
fuente
Respuestas:
Voy a ponerme del lado de Paul Graham en este caso: la escritura dinámica es más útil para crear programas de forma orgánica, que es exactamente lo que debería ser la creación de prototipos. El punto es hacer algo rápidamente que demuestre la funcionalidad del producto final, no el producto final en sí. La tipificación estática se trata de la corrección formal, bueno, aparentemente; al menos debería ser (como en Haskell o Agda), pero la escritura dinámica se trata de la corrección práctica, que es lo que más importa cuando se realizan prototipos.
En el lenguaje correcto, se pueden proporcionar sugerencias de tipo estático después del hecho como una optimización (y para proporcionar mayor seguridad para futuros cambios), o el prototipo se puede reescribir en un lenguaje de tipo estático una vez que el prototipo haya aclarado y solidificado los requisitos .
fuente
Creo que el problema del tipo estático frente al dinámico no es tan importante como muchas personas piensan que es.
Yo uso ambos. A veces uno es simplemente más útil que otro en una situación dada. Esto suele deberse a la necesidad de utilizar alguna herramienta / biblioteca / tecnología específica. Así que elegí lo que funciona bien con los otros componentes que tengo.
Creo que una de las cosas que a la gente le gusta de los lenguajes dinámicos es que muchos se interpretan; Puede modificarlos mientras se ejecutan de manera interactiva utilizando una consola REPL . Cualquier lenguaje con una función eval o algo equivalente puede hacer esto. Entonces, al menos para este aspecto, el sistema de tipos es realmente irrelevante.
Puede construir prototipos usando cosas que no tienen ningún tipo de sistema formal como scripts de shell. (Sin embargo, tienen REPL ...)
fuente
Haga lo que funcione mejor para usted y para lo que está tratando de hacer. Me parece que actualmente prototipo mejor en un lenguaje estático. La creación de prototipos con un sistema de tipo expresivo le permite hacer algunas cosas interesantes:
Escribir firmas de funciones sin implementaciones correspondientes. Mi código de Haskell en la etapa inicial a menudo tiene declaraciones como:
foo :: Foo -> Bar
foo _ = error "no definido"
Esto es porque quiero tener una idea de lo que
foo
hace cuando escribo código que lo usa, sin tener que tener una copia de trabajofoo
. En otros idiomas, esto se logra con algo comothrow new Exception()
, que es algo que nunca haría en código real, pero que ayuda mucho en las primeras etapas.:t
al GHCi (Haskell REPL) para descubrir qué fue lo que acabo de escribir. Por ejemplo, esto puede decirle cuán genérico es un fragmento de código, revelando así los requisitos de diferentes fragmentos de su código y la estructura correspondiente.Conal Elliot describió su visión de Haskell para ayudar con el desarrollo de iPhone de esta manera:
"Una vez que estaba escribiendo Haskell, la maquinaria imperativa desapareció de la vista y no pude evitar comenzar a ver patrones esenciales. Jugar con esos patrones me llevó a nuevas ideas ... Estoy agradecido de tener este lenguaje perezoso de orden superior con un rico la escritura estática como herramienta de pensamiento, para ayudarme a obtener información y eliminar mis errores. Es una ventaja para mí que el lenguaje también sea ejecutable ". Fuente
Así es. Uno de los dioses de la programación funcional piensa que el valor principal de Haskell es un lenguaje de modelado, en lugar de un lenguaje de implementación. Otros gurús piensan cosas similares: Erik Meijer usa Haskell para ayudar a aclarar el álgebra subyacente y los patrones que eventualmente entran en marcos orientados a objetos.
Sin embargo, la razón más importante para la creación de prototipos en un lenguaje estricto es que muchas veces las cosas que uno quiere "prototipar" no son las ingeniosas aplicaciones web de etapa temprana que Paul Graham quiere financiar. A menudo necesitas crear un prototipo:
En cada uno de estos casos, realmente desea utilizar un lenguaje cercano al lenguaje de implementación eventual de manera significativa.
Aunque un poco
no tiene
undefined
instancias "correctas" (siempre termina sin producir un error o ). Eso es porquePero no podría existir una función desde
[]
hasta que no tenga instancias.a
a
fuente
¿Te refieres a prototipos de características o diseño ?
Los prototipos de funciones tratan de mostrar una función al cliente antes de comenzar el desarrollo desde cero en el lenguaje de implementación final, por lo que el objetivo es escribir esa función lo más rápido posible sin preocuparse por errores o mantenimiento. Los lenguajes dinámicos permiten un equilibrio entre la corrección y la productividad al permitir hacks feos que ningún lenguaje de tipo estático aceptaría, lo que los hace, en teoría, más adecuados para escribir prototipos desechables rápidos. Por supuesto, en la práctica, la habilidad del desarrollador es más importante que el lenguaje, pero un codificador igualmente hábil tanto en Haskell como en Ruby probablemente crearía un prototipo más rápido en Ruby, y el código resultante sería un desastre.
Los prototipos de diseño consisten en encontrar un diseño de programa adecuado mediante prueba y error. Los trucos feos son inútiles: solo importa la capacidad de refactorizar diseños rápidamente. Un requisito fundamental para la refactorización masiva es un conjunto de pruebas automatizadas. En lenguajes dinámicos, esto suele ser un conjunto de pruebas unitarias escritas por el desarrollador, que lleva bastante tiempo escribir. En lenguajes tipados estáticamente, las firmas de tipo sirven como pruebas automatizadas y permiten al compilador detectar cualquier inconsistencia causada por cambios en el código. Los lenguajes tipados estáticamente brillan en la refactorización de formas que ningún lenguaje tipado dinámicamente puede lograr.
fuente
Dinámico, especialmente si sabe que el producto real tendría que estar en uno de varios lenguajes estáticos populares para ser lo suficientemente rápido como para resolver el problema real en la naturaleza. Hacer esto lo protegerá automáticamente de cometer el error de usar el prototipo como producto final.
fuente
Cualquier idioma con el que estés más familiarizado.
Dinámico vs estático realmente no importa. Funcional vs OO realmente no importa. El mejor ajuste, características o lo que sea, generalmente no tienen sentido.
El único punto de creación de prototipos es la velocidad de implementación (escritura de código) porque necesita cambiar mucho el programa. Y debes ser más rápido con tu mejor idioma.
Si tiene dos mejores idiomas, tanto dinámicos como estáticos, apostaría por el estático. Porque el estático generalmente puede manejar la complejidad, mientras que el dinámico falla en algún momento. Y nadie sabe realmente qué tan grande será el prototipo.
fuente