¿Cuáles son los beneficios (y desventajas) de un lenguaje de tipificación débil?

Soy un gran fan de PHP y obviamente es un lenguaje muy débil. Me doy cuenta de que algunos de los beneficios incluyen la independencia general de cambiar los tipos de variables sobre la marcha y similares.

Lo que me pregunto son los inconvenientes. ¿Qué puede obtener de un lenguaje fuertemente tipado como C que de otra manera no podría obtener de un lenguaje débil como PHP? También con la configuración de tipo (como doble ($ variable)), se podría argumentar que incluso un lenguaje de tipo débil puede actuar como uno de tipo fuerte.

Asi que. Tipo débil. ¿Cuáles son algunos de los beneficios que no incluí? Más importante aún, ¿cuáles son los inconvenientes?

La ventaja citada de la escritura estática es que hay clases completas de errores detectados en el momento de la comstackción, que no pueden alcanzar el tiempo de ejecución. Por ejemplo, si tiene una clase o interfaz de tipo estático como parámetro de función, es muy probable que no pase un objeto del tipo incorrecto (sin una conversión explícita e incorrecta, es decir).

Por supuesto, esto no le impide pasar el objeto equivocado del tipo correcto, o una implementación de una interfaz donde le ha dado las funciones correctas pero hacen las cosas incorrectas. Además, si tiene una cobertura de código del 100%, por ejemplo, gente de PHP / Python / etc, ¿a quién le importa si detecta el error en el momento de la comstackción o en el tiempo de ejecución?

Personalmente, he tenido momentos de diversión en idiomas con escritura estática y tiempos de diversión en idiomas sin. Rara vez es el tema decisivo, ya que nunca tuve que elegir entre dos idiomas que son idénticos a su tipo de escritura y normalmente hay cosas más importantes de las que preocuparse. Encuentro que cuando estoy usando lenguajes de tipo estático deliberadamente “me apoyo en el comstackdor”, tratando de escribir código de tal manera que si está mal, no se compile. Por ejemplo, hay ciertos refactores que puede realizar al hacer un cambio en un lugar, y luego corregir todos los errores de comstackción que resultan, repetir hasta comstackr de forma limpia. Hacer lo mismo ejecutando un conjunto completo de pruebas varias veces puede no ser muy práctico. Pero no es extraño que los IDE automaticen los mismos refactores en otros idiomas o que las pruebas se completen rápidamente, por lo que es una cuestión de lo que es conveniente, no de lo que es posible.

Las personas que tienen una preocupación legítima más allá de la conveniencia y la preferencia de estilo de encoding son las que trabajan en pruebas formales de la corrección del código. Mi impresión ignorante es que la deducción de tipo estático puede hacer la mayoría (pero no todo) del trabajo que hace la tipificación estática explícita y ahorra un desgaste considerable en el teclado. Entonces, si la escritura estática obliga a las personas a escribir código de una manera que facilite la prueba, entonces podría haber algo de eso en ese punto de vista. Digo “si”: no lo sé, y no es como si la mayoría de la gente probara su código estático de todos modos.

cambiando tipos de variables sobre la marcha y tal

Creo que eso es de dudoso valor. Siempre es tan tentador hacer algo como (Python / Django):

user = request.GET['username'] # do something with the string variable, "user" user = get_object_or_404(User,user) # do something with the User object variable, "user" 

Pero realmente, ¿debería usarse el mismo nombre para diferentes cosas dentro de una función? Tal vez. Probablemente no. La “reutilización”, por ejemplo, las variables de enteros para otras cosas en lenguajes tipificados estáticamente tampoco se recomienda. El deseo de no tener que pensar en nombres de variables descriptivos y concisos, probablemente el 95% del tiempo no debería invalidar el deseo de un código no ambiguo …

Por cierto, la tipificación generalmente débil significa que se producen conversiones de tipo implícitas, y la tipificación fuerte significa que no lo hacen. Según esta definición, C está tipificado débilmente en lo que respecta a los tipos aritméticos, por lo que supongo que no es lo que quieres decir. Creo que se considera ampliamente que la tipificación fuerte completa es más una molestia que una ayuda, y la “tipificación débil completa” (cualquier cosa puede convertirse en cualquier otra cosa) no tiene sentido en la mayoría de los idiomas. Entonces, la pregunta que hay sobre cuántas y qué conversiones implícitas se pueden tolerar antes de que su código sea demasiado difícil de entender. Vea también, en C ++, la dificultad continua para decidir si implementar operadores de conversión y constructores no explícitos de un argumento.

He estado usando tanto los lenguajes de tipo fuerte (como Java) y los de tipo débil (como JavaScript) desde hace algún tiempo. Lo que he encontrado es que la conveniencia de los lenguajes débiles escritos es ideal para aplicaciones pequeñas. Desafortunadamente, a medida que la aplicación aumenta de tamaño, se vuelve imposible de administrar. Se vuelve demasiado para mantener un registro en su cabeza y debe comenzar dependiendo de su IDE y el comstackdor cada vez más o la encoding se detiene. Es entonces cuando los lenguajes de tipo fuerte comienzan a ser más útiles, ya que la aplicación crece mucho.

Dos ejemplos que me vuelven loco constantemente en el JavaScript de tipo débil son las bibliotecas externas que no están bien documentadas y refactorizadas.

Bibliotecas externas: cuando se trata de un lenguaje fuertemente tipado, el código de la biblioteca en sí proporciona documentación propia. Cuando creo una variable de tipo Persona, el IDE puede inspeccionar el código y decir que hay un getFirstName (), getLastName () y getFullName (). En lenguajes de tipo débil, este no es el caso ya que una variable podría ser cualquier cosa, tener cualquier tipo de variable o función y tener argumentos de función que también podrían ser cualquier cosa (no están explícitamente definidos). Como resultado, un desarrollador tiene que apoyarse en gran medida en la documentación, búsquedas en la web, foros de discusión y su memoria de usos pasados. Creo que puede llevar horas buscar cosas en JavaScript para bibliotecas externas, mientras que con Java simplemente presiono “.” Tecla y aparece todas mis opciones con la documentación adjunta. Cuando te encuentras con bibliotecas que no están completamente documentadas al 100%, puede ser realmente frustrante con lenguajes de tipo débil. Recientemente me encontré preguntando “¿Qué es el argumento ‘argumento’ en la función ‘dibujar’?” cuando se utiliza jqplot, una biblioteca de JavaScript bastante bien pero no completamente documentada. Tuve que pasar una o dos horas investigando el código fuente antes de finalmente darme por vencido y encontrar una solución alternativa.

Refactorización: con lenguajes fuertemente tipados, me encuentro capaz de refactorizar rápidamente simplemente cambiando el archivo que necesito cambiar y luego corregir los compiler errors. Algunas herramientas incluso se refactorizan para usted con un simple clic de un botón. Con los idiomas tipeados débiles, debe hacer una búsqueda y luego reemplazar con cuidado y luego probar, probar, PROBAR y luego probar un poco más. Rara vez está completamente seguro de haber encontrado y arreglado todo lo que rompió, especialmente en aplicaciones grandes.

Para necesidades simples y aplicaciones pequeñas, estas dos preocupaciones son mínimas o inexistentes. Pero si está trabajando con una aplicación con cientos de miles o millones de líneas de código, los lenguajes de tipo débil lo volverán loco.

Creo que muchos desarrolladores se enojan por esto y lo convierten en una discusión emocional, porque a veces nos parece que hay un enfoque correcto y otro incorrecto. Pero cada enfoque tiene sus ventajas, sus propias ventajas y desventajas. Una vez que reconozca que deja a un lado la emoción y elija la mejor opción para lo que necesita en este momento.

Débil y Fuerte son términos cargados. (¿Quieres ser un progtwigdor de lenguaje débil?) Dinámico y estático son mejores, pero me imagino que la mayoría de las personas preferiría ser un progtwigdor dynamic que uno estático. Yo llamaría a PHP un lenguaje promiscuo (Eso no es un término cargado;))

PHP:

 garbage_out = garbage_in * 3; // garbage_in was not initialized yet "hello world" + 2; // does this make sense? 

Permitir variables sin inicializar crea muy difícilmente encontrar errores de faltas de ortografía. Permitir operaciones en tipos no relacionados también es casi siempre un error que debe informarse. La mayoría de los lenguajes dynamics interpretados no permiten estas cosas por una buena razón. Puedes tener un lenguaje tipado dinámicamente sin permitir basura.

Se ha escrito muchos libros sobre este tipo de cosas. Hay una compensación inherente; con un lenguaje débilmente tipificado, muchas molestias simplemente dejan de ser. Por ejemplo, en Python nunca tienes que preocuparte por dividir un float por un int ; agregar un int a una list ; escribiendo argumentos de las funciones (¿sabía que OCaml tiene operadores especiales para agregar float porque (+) envía int s a int s!); olvidando que una variable puede ser nula … ese tipo de problemas simplemente desaparecen.

En su lugar vienen una gran cantidad de nuevos errores de ejecución: Python’s [0]*5 da, ¡espera, [0,0,0,0,0] ! OCaml, por toda la molestia de la tipificación fuerte, atrapa muchos errores con su comstackdor; Y es precisamente por eso que es bueno. Es una compensación.

Consulte esta tabla , que muestra los resultados del operador PHP == aplicado a pares de valores vacíos u otros valores principales de varios tipos, como 0 , "0" , NULL y "" . El operador no es conmutativo, y la tabla es bastante poco intuitiva, por decir lo menos. (No es que tenga mucho sentido preguntar si una cadena es igual a una matriz, para ser justos, pero puede hacerlo en un lenguaje débilmente tipado, que es el escollo, y puede que Turing lo ayude si el idioma lo intenta ” ayudarte.)

Directamente desde la wikipedia:

La ventaja de la tipificación débil es que requiere menos esfuerzo por parte del progtwigdor que la tipificación fuerte, ya que el comstackdor o intérprete realiza implícitamente ciertos tipos de conversiones. Sin embargo, una desventaja alegada es que los sistemas de progtwigción mal tipificados detectan menos errores en el momento de la comstackción y algunos de estos podrían permanecer después de que se hayan completado las pruebas.

Eso es casi lo mismo que yo diría. Sin embargo, tenga cuidado con la ambigüedad relativa de estos términos (“tipificación fuerte” y “tipificación débil”) ya que las conversiones implícitas difuminan la línea.

Fuente: http://en.wikipedia.org/wiki/Weak_typing

Debe comprender que PHP se creó para el contexto de las aplicaciones web. Todo en el contexto de la web es una cadena. Por lo tanto, es muy raro que una tipificación fuerte sea beneficiosa.