¿Cómo evitar los típicos "errores de lenguaje dinámico"?

42

Recientemente he invertido un par de horas en JavaScript porque quería beneficiarme de la enorme base de usuarios. Al hacerlo, noté un patrón que la mayoría de las personas atribuyen a los lenguajes dinámicos. Hace que las cosas funcionen realmente rápido, pero una vez que su código alcanza un cierto tamaño, pierde mucho tiempo con errores de tipografía, ortografía y refactorización en general. Errores que un compilador normalmente me evitaría. Y no tengo que buscar errores en la lógica cuando acabo de hacer un error tipográfico en otro módulo.

Teniendo en cuenta los increíbles siguientes JavaScript y otros lenguajes escritos dinámicamente, creo que hay algo mal con mi enfoque. ¿O es solo el precio que tiene que pagar?

Para decirlo de manera más concisa:

  • ¿Cómo aborda un proyecto de JavaScript (o cualquier otro lenguaje dinámico para el caso) con ~ 2000 LOC?
  • ¿Hay herramientas para evitar que cometa esos errores? He intentado fluir por Facebook y JSHint que de alguna manera ayudan, pero no detectan errores tipográficos.
TomTom
fuente
2
A pesar de que hay maneras de mitigar los costos, no son los costes .
dcastro
29
Intentaría escribir su programa en un lenguaje de tipo estático que se compilara en javascript, como Typescript, Scala.js o Elm.
dcastro
66
pruebas, pruebas, más pruebas e informes de cobertura.
njzk2
77
~ 2000 LOC es un proyecto pequeño. Debe encajar fácilmente en lo que un lenguaje dinámico hace fácil y bien. Si está luchando con ese tipo de proyecto de tamaño, tiene un problema más fundamental con sus habilidades de programación que cualquier cosa que sea relevante específicamente para lenguajes dinámicos.
Jack Aidley
55
@JackAidley No estuvo de acuerdo. OP se utiliza para centrarse en problemas de alto nivel y no si un identificador está escrito correctamente. Esa es la habilidad de programación. Asegurarse de que la ortografía sea correcta puede ser realizada por un alumno de grado medio y / o un soporte de herramientas.
mucaho

Respuestas:

37

Específicamente hablando de JavaScript, podría usar TypeScript en su lugar. Ofrece algunas de las cosas a las que te refieres. Citando el sitio web:

Los tipos permiten a los desarrolladores de JavaScript utilizar herramientas y prácticas de desarrollo altamente productivas, como la comprobación estática y la refactorización de código al desarrollar aplicaciones de JavaScript.

Y es solo un superconjunto de JS, lo que significa que parte de su código existente funcionará bien con TS:

TypeScript comienza con la misma sintaxis y semántica que millones de desarrolladores de JavaScript conocen hoy. Use el código JavaScript existente, incorpore bibliotecas populares de JavaScript y llame al código TypeScript desde JavaScript.

VinArrow
fuente
11
... y TypeScript es esencialmente Ecmascript 6.
Robert Harvey
11
Uh, esa cita duele. Simplemente muestra que Microsoft siempre ha sido una empresa de idiomas estáticos que simplemente no entiende los lenguajes dinámicos. ¿"Tipos habilitan ... refactorización de código"? De Verdad? ¿El departamento de relaciones públicas de Microsoft se da cuenta de que la refactorización de códigos como práctica se inventó en Smalltalk (un lenguaje dinámico) y existía incluso antes que en Forth (un lenguaje sin tipo)? ¿Que la primera herramienta automatizada de refactorización era parte de un Smalltalk IDE, incluso antes de que los lenguajes estáticos tuvieran IDE? ¿Que los IDE modernos de Smalltalk tienen herramientas de refactorización al menos tan poderosas, si no más, que Java, C # y C ++? Vamos.
Jörg W Mittag
55
TypeScript es un gran lenguaje en sí mismo, ¿por qué tienes que intentar empujarlo con tanta tontería?
Jörg W Mittag
29
@ Jörg No sé lo suficiente sobre Smalltalk, pero cada IDE sola JavaScript o Python que he visto es millas detrás de lo que es un IDE bueno para Java o C # puede hacer. También hay algunas cosas que son simplemente imposibles de hacer en un lenguaje dinámico (algunas de las refactorizaciones más populares realmente): digamos que tiene una función pública foo(x) { return x.bar;}o algo así. Como no hay información de tipo y la función es pública (por lo tanto, no puede conocer a todas las personas que llaman), es imposible que se dé cuenta si se debe cambiar el nombre de la barra a baz si cambia el nombre de alguna clase.
Voo
10
Esta respuesta dice que la solución a los "errores de lenguaje dinámico" no es utilizar un lenguaje dinámico en absoluto.
bgusach
19

Hay algunos enfoques que pueden ayudar:

Examen de la unidad

Escriba pruebas unitarias donde sea posible. Confiar exclusivamente en las pruebas manuales o encontrar errores en la naturaleza es impredecible.

Usar marcos

En lugar de rodar el tuyo y arriesgar la introducción de errores, usa marcos establecidos siempre que sea posible.

Prefiero CSS / lenguajes de alto nivel

Donde puede ceder funcionalidad a CSS o cualquier lenguaje de alto nivel en el que esté escribiendo

Refactor

Refactorizar para reducir la cantidad de código. Menos código = menos lugares para que las cosas salgan mal.

Reutilizar

Reutilice el código existente donde pueda. Incluso si el código no coincide exactamente, puede ser mejor copiar, pegar y modificar en lugar de escribir algo nuevo.

IDEs

Los IDEs modernos generalmente tienen al menos algo de soporte de Javascript. Algunos editores de texto también son compatibles con Javascript.

Robbie Dee
fuente
55
Si bien es cierto, su consejo se aplica básicamente a todos los lenguajes de programación y apunta principalmente a corregir errores lógicos en lugar de aquellos que surgen de lenguajes dinámicos.
edmz
1
"su consejo se aplica básicamente a todos los lenguajes de programación" . Muy cierto, de una manera similar a pasar por los engranajes desde proyectos de pasatiempos hasta soluciones empresariales totalmente gordas, lo que requiere una cantidad cada vez mayor de restricciones, de manera similar, cuanto más Javascript esté escrito, más disciplina necesitará si las ruedas no funcionan salir rápidamente Eric Lippert describe esto muy bien.
Robbie Dee
44
"Prefiero CSS / lenguajes de alto nivel" - Realmente no entiendo lo que significa este bit en relación con JavaScript: ¿estás diciendo que muevas elementos (como animación, tal vez?) A hojas de estilo en lugar de código JS? ¿Cómo se relaciona CSS con los lenguajes de alto nivel?
otra vez
@anotherdave Mucho de lo que solía ser el dominio de Javascript ahora se puede lograr en CSS3. Algunas funciones también podrían trasladarse a un lenguaje de nivel superior que estaría sujeto a controles más estrictos.
Robbie Dee
44
@anotherdave Mucho de lo que la gente intenta hacer con JavaScript es extraño e inapropiado. Bibliotecas que proporcionan herramientas de lenguaje estándar, marcos que proporcionan elementos HTML estándar con poco más, código que replica funcionalidades básicas como anclas, emulación MVC, estilo, reimplementación DOM, abstracción AJAX, renderización de objetos triviales (reimplementar SVG), funciones de relleno múltiple que no beneficiar al usuario ... Debe minimizar la cantidad de JS que escribe. Si puede hacerlo sin JS, hágalo sin JS.
bjb568
2

Una herramienta que aún no se ha mencionado es la búsqueda de texto simple, local de archivo o de todo el proyecto .

Suena simple, pero cuando incluye algunas expresiones regulares puede hacer un filtrado básico a avanzado, por ejemplo, buscar palabras ubicadas en la documentación o el código fuente.

Ha sido una herramienta efectiva para mí (además de los analizadores estáticos), y dado el tamaño de su proyecto de 2k LOC, que en mi opinión no es particularmente grande, espero que funcione de maravilla.

mucaho
fuente
2
grepva un largo camino. A menos que no hagas cosas dinámicas demasiado raras, funciona. Sin embargo, se siente muy manual si está acostumbrado a IDEs para lenguajes tipados estáticos.
bgusach
1

Actualmente estoy refactorizando varios miles de líneas de código en un gran proyecto AngularJS. Una de las mayores molestias es averiguar el contrato exacto de una función determinada. A veces terminé leyendo la documentación de la API porque los elementos de la respuesta API sin procesar se asignaron a variables que pasaron por 6 capas de código antes de ser modificadas y devueltas a través de 6 capas más de código.

Mi primer consejo es diseñar por contrato . Tome datos específicos, produzca resultados específicos, evite los efectos secundarios y documente esas expectativas utilizando TypeScript o al menos JSDoc.

Mi segundo consejo es implementar tantas verificaciones como sea posible. Seguimos el estándar AirBnB y usamos eslint en toda nuestra base de código. Los ganchos de compromiso verifican que siempre seguimos el estándar. Naturalmente, tenemos una batería de pruebas de unidad y aceptación, y todas las confirmaciones deben ser revisadas por un compañero.

Cambiar de un editor de texto (Sublime Text) a un IDE adecuado (WebStorm) también facilitó mucho el trabajo con código en general. WebStorm usará JSDoc para dar pistas sobre los tipos de parámetros esperados y generar un error si proporciona el tipo incorrecto o utiliza el valor de retorno de la manera incorrecta.

En JavaScript, las nuevas características, como símbolos y captadores / establecedores, pueden ayudar a imponer un cierto nivel de calidad al agregar aserciones a la asignación de variables (por ejemplo, asegúrese de que el entero esté dentro del rango o que el objeto de datos tenga ciertos atributos).

Desafortunadamente, no creo que haya una verdadera solución para evitar errores de lenguaje dinámico, solo una serie de medidas que pueden ayudar a reducir su frecuencia.

Nicolas Bouliane
fuente
0

Mi respuesta a la pregunta "¿Cómo aborda un proyecto de JavaScript (o cualquier otro lenguaje dinámico para el caso) con ~ 2000 LOC?"

Desarrollo aplicaciones de formulario PDF. Me acerco a mi proyecto de desarrollo de software JavaScript (independientemente del tamaño del código fuente) usando los elementos y anotaciones netas de Petri. El método no está vinculado a ninguna tecnología de lenguaje de programación en particular. Por lo tanto, puede usarse para otros "lenguajes de programación".

Creo un diagrama de la lógica de la aplicación. Para mantener el diagrama ordenado, agrego la mayoría de mis anotaciones a un formulario que utilizo con el diagrama. Las entradas en el formulario incluyen referencias a propiedades o funciones. Luego escribo el código fuente basado en la información en el diagrama y las entradas en el formulario. El método es sistemático porque cada código fuente escrito se asigna directamente desde el diagrama y las entradas en el formulario. El código fuente se puede verificar fácilmente porque también sigo las convenciones de nomenclatura y codificación cuando escribo el código.

Por ejemplo, he elegido una convención según la cual todas las funciones son prototipos. Si el rendimiento se convierte en un problema, puede mejorarse declarando las funciones en el constructor. Para algunas propiedades uso matrices. Nuevamente, si el rendimiento se convierte en un problema, se puede mejorar mediante el uso de referencias directas.

También uso eval. Esto puede reducir en gran medida el tamaño del código fuente. Debido a problemas de rendimiento, uso eval al comienzo o parte de la inicialización de mi aplicación; Nunca lo uso en la "lógica de tiempo de ejecución": esta es otra convención de codificación que sigo.

John Frederick Chionglo
fuente