Todo el mundo quiere ser un experto. Pero, ¿qué significa eso? A lo largo de los años, he visto dos tipos de personas a las que se hace referencia como “expertos”. El experto 1 es alguien que conoce todas las herramientas del idioma y se asegura de usarlas todas, ya sea que ayude o no. Experto 2 también conoce cada parte de la sintaxis, pero son más exigentes con lo que emplean para resolver problemas, considerando una serie de factores, tanto relacionados con el código como no.
El artículo continúa a continuación
¿Puedes adivinar qué experto queremos que trabaje en nuestro equipo? Si dijiste Experto 2, tendrías razón. Es un desarrollador enfocado en entregar código legible: líneas de JavaScript que otros pueden entender y mantener. Alguien que pueda hacer easy lo complejo. Pero “legible” rara vez es definitivo; de hecho, se basa en gran medida en los ojos del espectador. Entonces, ¿dónde nos deja eso? ¿A qué deben aspirar los expertos al escribir código legible? ¿Hay opciones claras correctas e incorrectas? La respuesta es, depende.
Con el fin de mejorar la experiencia del desarrollador, TC39 ha agregado muchas funciones nuevas a ECMAScript en los últimos años, incluidos muchos patrones probados tomados de otros lenguajes. Una de esas adiciones, añadida en ES2019, es Array.prototype.flat()
Se necesita un argumento de profundidad o Infinity
y aplana una matriz. Si no se proporciona ningún argumento, la profundidad predeterminada es 1.
Antes de esta adición, necesitábamos la siguiente sintaxis para aplanar una matriz a un solo nivel.
let arr = (1, 2, (3, 4));
().concat.apply((), arr);
// (1, 2, 3, 4)
cuando añadimos flat()
esa misma funcionalidad podría expresarse mediante una única función descriptiva.
arr.flat();
// (1, 2, 3, 4)
¿La segunda línea de código es más legible? La respuesta es rotundamente sí. De hecho, ambos expertos estarían de acuerdo.
No todos los desarrolladores van a ser conscientes de que flat()
existe Pero no es necesario porque flat()
es un verbo descriptivo que transmite el significado de lo que está sucediendo. Es mucho más intuitivo que concat.apply()
.
Este es el raro caso en el que hay una respuesta definitiva a la pregunta de si la nueva sintaxis es mejor que la antigua. Ambos expertos, cada uno de los cuales está familiarizado con las dos opciones de sintaxis, elegirán la segunda. Elegirán la línea de código más corta, más clara y más fácil de mantener.
Pero las elecciones y las concesiones no siempre son tan decisivas.
La maravilla de JavaScript es que es increíblemente versátil. Hay una razón por la que está en toda la net. Ya sea que pienses que eso es bueno o malo la cosa es otra historia.
Pero con esa versatilidad viene la paradoja de la elección. Puede escribir el mismo código de muchas maneras diferentes. ¿Cómo determinas cuál es el camino “correcto”? Ni siquiera puede comenzar a tomar una decisión a menos que comprenda las opciones disponibles y sus limitaciones.
Usemos la programación funcional con map()
como el ejemplo. Veré varias iteraciones que arrojarán el mismo resultado.
Esta es la versión más resumida de nuestro map()
ejemplos Utiliza la menor cantidad de caracteres, todos caben en una línea. Esta es nuestra línea de base.
const arr = (1, 2, 3);
let multipliedByTwo = arr.map(el => el * 2);
// multipliedByTwo is (2, 4, 6)
El siguiente ejemplo agrega solo dos caracteres: paréntesis. ¿Se pierde algo? ¿Qué hay de ganado? ¿Hace alguna diferencia que una función con más de un parámetro siempre necesite usar los paréntesis? Yo diría que sí. Hay poco o ningún perjuicio en agregarlos aquí, y mejora la consistencia cuando inevitablemente escribe una función con múltiples parámetros. De hecho, cuando escribí esto, más bonita hizo cumplir esa restricción; no quería que creara una función de flecha sin los paréntesis.
let multipliedByTwo = arr.map((el) => el * 2);
Vayamos un paso más allá. Hemos agregado llaves y un retorno. Ahora esto está empezando a parecerse más a una definición de función tradicional. En este momento, puede parecer excesivo tener una palabra clave tan larga como la lógica de la función. Sin embargo, si la función tiene más de una línea, se requiere nuevamente esta sintaxis adicional. ¿Presumimos que no tendremos otras funciones que vayan más allá de una sola línea? Eso parece dudoso.
let multipliedByTwo = arr.map((el) => {
return el * 2;
});
A continuación, eliminamos la función de flecha por completo. Estamos usando la misma sintaxis que antes, pero la hemos cambiado por la operate
palabra clave. Esto es interesante porque no hay escenario en el que esta sintaxis no funcione; ningún número de parámetros o líneas causará problemas, por lo que la coherencia está de nuestro lado. Es más detallado que nuestra definición inicial, pero ¿es eso algo malo? ¿Cómo afecta esto a un nuevo codificador, o alguien que está bien versado en algo que no sea JavaScript? ¿Alguien que conozca bien JavaScript se sentirá frustrado por esta sintaxis en comparación?
let multipliedByTwo = arr.map(operate(el) {
return el * 2;
});
Finalmente llegamos a la última opción: pasar solo la función. Y timesTwo
se puede escribir usando cualquier sintaxis que nos guste. Nuevamente, no hay ningún escenario en el que pasar el nombre de la función trigger un problema. Pero dé un paso atrás por un momento y piense si esto podría ser confuso o no. Si es nuevo en este código base, ¿está claro que timesTwo
es una función y no un objeto? Seguro, map()
está ahí para darle una pista, pero no es descabellado pasar por alto ese detalle. ¿Qué tal la ubicación de dónde timesTwo
se declara e inicializa? Es fácil de encontrar? ¿Está claro lo que está haciendo y cómo está afectando este resultado? Todas estas son consideraciones importantes.
const timesTwo = (el) => el * 2;
let multipliedByTwo = arr.map(timesTwo);
Como puede ver, no hay una respuesta obvia aquí. Pero tomar la decisión correcta para su base de código significa comprender todas las opciones y sus limitaciones. Y sabiendo que la consistencia requiere paréntesis y llaves y return
palabras clave
Hay una serie de preguntas que debe hacerse a sí mismo al escribir código. Preguntas de actuación suelen ser los más comunes. Pero cuando observa un código que es funcionalmente idéntico, su determinación debe basarse en los humanos: cómo los humanos consumen el código.
Tal vez más nuevo no siempre es mejor#Sección 4
Hasta ahora hemos encontrado un ejemplo claro de dónde ambos expertos buscarían la sintaxis más nueva, incluso si no es universalmente conocida. También hemos visto un ejemplo que plantea muchas preguntas pero no tantas respuestas.
Ahora es el momento de sumergirse en el código que escribí antes… y eliminé. Este es el código que me convirtió en el primer experto, utilizando una sintaxis poco conocida para resolver un problema en detrimento de mis colegas y la capacidad de mantenimiento de nuestra base de código.
Asignación de desestructuración le permite desempaquetar valores de objetos (o matrices). Por lo common, se parece a esto.
const {node} = exampleObject;
Inicializa una variable y le asigna un valor en una sola línea. Pero no tiene por qué.
let node
;({node} = exampleObject)
La última línea de código asigna una variable a un valor mediante la desestructuración, pero la declaración de la variable tiene lugar una línea antes. No es raro querer hacer algo, pero muchas personas no se dan cuenta de que puedes hacerlo.
Pero mira ese código de cerca. Obliga a un punto y coma incómodo para el código que no usa punto y coma para terminar las líneas. Envuelve el comando entre paréntesis y agrega las llaves; no está del todo claro qué está haciendo esto. No es fácil de leer y, como experto, no debería estar en código lo que escribo.
let node
node = exampleObject.node
Este código resuelve el problema. Funciona, está claro lo que hace y mis colegas lo entenderán sin tener que buscarlo. Con la sintaxis de desestructuración, solo porque yo poder no significa que yo debería.
El código no lo es todo#sección5
Como hemos visto, la solución Skilled 2 rara vez es obvia basándose únicamente en el código; sin embargo, todavía hay distinciones claras entre qué código escribiría cada experto. Eso es porque el código es para que las máquinas lo lean y los humanos lo interpreten. ¡Entonces hay factores que no son de código a considerar!
Las elecciones de sintaxis que haces para un equipo de desarrolladores de JavaScript son diferentes a las que deberías hacer para un equipo de políglotas que no están inmersos en las minucias.
Tomemos propagación vs. concat()
como ejemplo.
Unfold se agregó a ECMAScript hace algunos años y ha disfrutado de una amplia adopción. Es una especie de sintaxis de utilidad en el sentido de que puede hacer muchas cosas diferentes. Uno de ellos es la concatenación de una serie de matrices.
const arr1 = (1, 2, 3);
const arr2 = (9, 11, 13);
const nums = (...arr1, ...arr2);
A pesar de lo poderosa que es la propagación, no es un símbolo muy intuitivo. Entonces, a menos que ya sepa lo que hace, no es muy útil. Si bien ambos expertos mayo suponga con seguridad que un equipo de especialistas en JavaScript está familiarizado con esta sintaxis, el Experto 2 probablemente se preguntará si eso es cierto para un equipo de programadores políglotas. En su lugar, el Experto 2 puede seleccionar el concat()
método en su lugar, ya que es un verbo descriptivo que probablemente pueda entender desde el contexto del código.
Este fragmento de código nos da el mismo resultado numérico que el ejemplo de propagación anterior.
const arr1 = (1, 2, 3);
const arr2 = (9, 11, 13);
const nums = arr1.concat(arr2);
Y ese es solo un ejemplo de cómo los factores humanos influyen en las opciones de código. Una base de código que es tocada por muchos equipos diferentes, por ejemplo, puede tener que mantener estándares más estrictos que no necesariamente se mantienen al día con la última y mejor sintaxis. Luego va más allá del código fuente principal y considera otros factores en su cadena de herramientas que hacen la vida más fácil o más difícil para los humanos que trabajan en ese código. Hay código que se puede estructurar de una manera que es hostil a las pruebas. Hay un código que te arrincona en una esquina para escalado futuro o adición de características. Hay un código que es menos eficazno manejar diferentes navegadoreso no es accesible. Todos estos son un issue en las recomendaciones que hace el Experto 2.
El experto 2 también considera el impacto de nombrar. Pero seamos honestos, incluso ellos no puedo hacerlo bien la mayor parte del tiempo.
Los expertos no prueban su valía usando cada pieza de la especificación; se prueban a sí mismos al conocer la especificación lo suficientemente bien como para implementar la sintaxis juiciosamente y tomar decisiones bien razonadas. Así es como los expertos se convierten en multiplicadores, cómo hacen nuevos expertos.
Entonces, ¿qué significa esto para aquellos de nosotros que nos consideramos expertos o aspirantes a expertos? Significa que escribir código implica hacerse muchas preguntas. Significa considerar a su audiencia de desarrolladores de una manera actual. El mejor código que puede escribir es el código que logra algo complejo, pero que aquellos que examinan su base de código lo entienden inherentemente.
Y no, no es fácil. Y a menudo no hay una respuesta clara. Pero es algo que debe considerar con cada función que escriba.