Sé que javascript utiliza la tipificación de pato y al principio pensé que esto facilitaría el polimorfismo en comparación con lenguajes fuertemente tipados como C #. Pero ahora mis funciones que toman argumentos están llenas de cosas como:
if(myObj.hasSomeProperty())
o
if(myObj.hasSomeMethod())
o
if(isNumber(myParam))
etc.
Esto es realmente feo para mí. Vengo de un fondo de C # y encuentro que las interfaces definidas son mucho mejores.
Me pregunto si intento aplicar incorrectamente estrategias que son efectivas en lenguajes estáticamente escritos y ¿hay alguna forma mejor de hacerlo en JavaScript?
Sé que no podría verificarlo, pero rastrear los errores de tiempo de ejecución de JavaScript puede ser una pesadilla, ya que no siempre ocurren donde el error realmente ocurre en el código.
javascript
polymorphism
duck-typing
Legión
fuente
fuente
Respuestas:
Simple: no siempre verifique las propiedades y los métodos.
En Ruby, lo que llamas se llama "mecanografía de pollo". En un lenguaje de tipo dinámico, simplemente confía en que la persona que llama le pasa un objeto adecuado. El trabajo de la persona que llama es honrar su parte del contrato.
Está confundiendo múltiples ejes ortogonales de escribir aquí. Hay cuatro ejes ortogonales de escritura:
Como mencionó C #: en su mayoría está tipado estáticamente, pero admite el tipeo dinámico a través del tipo
dynamic
, en su mayoría está tipeado nominalmente, pero los tipos anónimos usan tipeo estructural, y se puede argumentar que los patrones sintácticos (como la sintaxis de comprensión de consultas LINQ) son duck -tipo o estructuralmente tipado, en su mayoría está explícitamente tipado pero admite tipeo implícito para argumentos de tipo genérico y variables locales (aunque el caso de la variable local es bastante extraño en comparación con la mayoría de los otros idiomas, porque no puede dejar el tipo fuera, sino que debe darle un pseudotipo explícitovar
, en otras palabras, si quieres un tipo implícito, tienes que decirlo explícitamente). Si C # tiene un tipo fuerte o débil, es una cuestión de qué definición de los dos términos que usa, sin embargo, tenga en cuenta que puede haber muchos errores de tipo de tiempo de ejecución en C #, especialmente debido a la covarianza de matriz insegura.La depuración no es una habilidad fácil de aprender. Sin embargo, existen técnicas para facilitar la depuración, por ejemplo, Saff Squeeze es una técnica descrita por Kent Beck que utiliza pruebas y refactorización para la depuración:
fuente
IComparer<T>.Compare(T, T)
solo está claro en la documentación, no en el tipo. Y enjava.util.Collections.binarySearch(java.util.List<T>)
qué tipo de dice que el ...De hecho, la práctica típica es no verificar. Y sí, esto significa que obtendrá errores de JavaScript que se informan en otras partes del problema real. Pero en la práctica, no creo que esto sea un gran problema.
Cuando trabajo en JavaScript, estoy constantemente probando lo que estoy escribiendo. En la mayoría de los códigos, tengo pruebas unitarias que se ejecutan automáticamente cada vez que guardo mi editor. Cuando algo inesperadamente sale mal, lo sé casi de inmediato. Tengo un área de código muy pequeña en la que podría haber cometido el error, ya que casi siempre es lo último que toco que tiene el error.
Cuando recibo un error de tiempo de ejecución, al menos tengo el seguimiento de la pila, y en el caso de un error en el navegador, tengo la capacidad de ir a cualquier nivel del seguimiento de la pila e inspeccionar las variables. Por lo general, es fácil rastrear el origen del valor incorrecto y, por lo tanto, rastrearlo hasta el problema original.
Si eres como yo cuando escribí principalmente en lenguajes estáticamente escritos, escribí bloques de código más grandes antes de probar y no tenía práctica en rastrear un valor de donde vino. La programación en un lenguaje como javascript es diferente, tienes que usar diferentes habilidades. Sospecho que programar así parece mucho más difícil, porque esas no son las habilidades que has desarrollado trabajando en otros lenguajes como C #.
Dicho esto, creo que hay mucho que decir sobre los tipos explícitos. Son excelentes para la documentación y la detección temprana de errores. Creo que en el futuro veremos una mayor adopción de cosas como Flow y Typecript que agregan la comprobación de tipo estático al javascript.
fuente
Creo que estás haciendo lo correcto, solo necesitas encontrar el estilo que sea más agradable a la vista. Aquí hay algunas ideas:
En lugar de que
if(myObj.hasSomeProperty())
puedas usarif( myobj.prop !== undefined )
. Esto, por cierto, funcionará solo en modo no estricto, en modo estricto que tendría que usarif( typeof myobj.prop !== 'undefined' )
.Puede descargar parte de la verificación de tipos para validar por separado. Esto tiene la ventaja de poder omitir la validación una vez que las interfaces están maduras, por ejemplo
if( is_valid( myobject ))
, dóndeis_valid
comienzaif( !DEBUG ) return true;
.A veces tiene sentido clonar la entrada en una forma canónica, en cuyo caso podría recopilar los diversos objetivos de validación en la función / objeto de clonación. Por ejemplo, en
my_data = Data( myobj, otherstuff )
elData
constructor podría ejecutar convenientemente todas las diversas validaciones en un lugar central.Podría usar alguna biblioteca que (con un costo de rendimiento) simplifique su validación de tipo en algo más elegante. Incluso si no va a tomar esta ruta a largo plazo, puede que le resulte cómodo llevarlo a su propio estilo sin problemas. Algunos ejemplos incluyen xtype.js , type-check , validator.js , etc.
fuente