JavaScript legible por humanos: una historia de dos expertos





Todo el mundo quiere ser un experto. Pero, ¿qué significa eso? A lo largo de los años, me he encontrado con dos tipos de personas llamadas "expertos". Un experto del primer tipo es una persona que no solo conoce todos los engranajes del idioma, sino que también usa todos estos engranajes, independientemente de si es beneficioso. Un experto del segundo tipo también conoce todas las sutilezas sintácticas, pero es más selectivo a la hora de elegir una herramienta para resolver un problema, teniendo en cuenta una serie de factores, tanto relacionados como no relacionados con el código.



Adivinemos qué tipo de experto le gustaría ver en su equipo. Segundo, ¿verdad? Este es el tipo de desarrollador que se esfuerza por producir código legible por humanos, cadenas de JavaScript que otras personas puedan entender y que sean fáciles de mantener. Pero la característica "legible" rara vez se define; de ​​hecho, suele estar en el ojo del espectador. Entonces, ¿a dónde nos lleva esto? ¿Por qué debemos esforzarnos si nuestro objetivo es un código legible? ¿Existe una elección claramente correcta o incorrecta en este caso? Depende mucho.



La elección obvia



Para facilitar el trabajo del desarrollador, TC39 ha agregado muchas características nuevas a ECMAScript en los últimos años, incluidos muchos patrones probados tomados de otros lenguajes. Una de esas innovaciones introducidas en ES2019 es el método Array.prototype.flat () . Toma un argumento de profundidad o infinito y alinea la matriz. Si no hay argumentos, la profundidad predeterminada de la matriz es 1.



Antes de que apareciera esta adición, se requería la siguiente sintaxis para alinear la matriz a un solo nivel.



let arr = [1, 2, [3, 4]];
[].concat.apply([], arr);

// [1, 2, 3, 4]

      
      





Al agregar flat (), puede describir la misma característica con solo una función expresiva.



arr.flat();

// [1, 2, 3, 4]

      
      





¿Es la segunda línea de código más fácil de leer? Absolutamente sí. De hecho, ambos expertos estarían de acuerdo con esto.



No todos los desarrolladores conocen la existencia de flat (). Pero no es necesario saberlo de antemano, ya que flat () es un verbo comprensible, por lo que queda claro lo que está sucediendo aquí. Es mucho más intuitivo que concat.apply ().



Este es el caso poco común en el que puede responder con seguridad qué sintaxis es mejor: nueva o antigua. Ambos expertos, familiarizados con las dos sintaxis, elegirán la segunda. Elegirán la línea de código que sea más corta, más clara y más fácil de mantener.



Pero la elección y el compromiso no siempre son tan sencillos.



Compruebe si hay piojos



Lo maravilloso de JavaScript es su increíble versatilidad. Por eso está en todas partes de la web. Si es bueno o malo desde su punto de vista es otra cuestión.



Pero tal versatilidad trae consigo la paradoja de la elección. El mismo código se puede escribir de muchas formas diferentes. ¿Cómo se determina cuál es la "correcta"? Ni siquiera se puede abordar una solución de este tipo si no conoce todas las opciones disponibles y no comprende lo que no alcanzan.



Probemos la programación funcional con map () como ejemplo. Analizaré algunas iteraciones aquí; todas conducirán al mismo resultado.



Aquí está la versión más concisa de todos nuestros ejemplos de map (). Tiene la menor cantidad de caracteres y todos caben en una línea. Construiremos sobre esta versión.



const arr = [1, 2, 3];

let multipliedByTwo = arr.map(el => el * 2);

// multipliedByTwo  [2, 4, 6]

      
      





El siguiente ejemplo agrega solo dos caracteres: paréntesis. ¿Hemos perdido algo? ¿Lo has comprado? ¿El clima hace que siempre sea necesario usar paréntesis en una función que tiene más de un parámetro? Creo que sí, lo hace. No hay nada de malo en agregarlos aquí, pero la consistencia del código aumentará significativamente cuando inevitablemente tenga que escribir una función con muchos parámetros. De hecho, en el momento de escribir este artículo, resultó que se requería que Prettier tuviera esta restricción; allí no pude crear una función de flecha sin paréntesis.



let multipliedByTwo = arr.map((el) => el * 2);
      
      







Avanzar. Hemos agregado llaves y una declaración de devolución. Esto ahora empieza a sonar como una definición de función tradicional. En este momento, podría parecer una palabra clave, siempre que toda la lógica de la función sea disparar un cañón a los gorriones. Pero, si la función contiene más de una línea, definitivamente será necesaria esta sintaxis adicional. ¿Estamos asumiendo que no tendremos otras funciones de más de una línea? Parece dudoso.



let multipliedByTwo = arr.map((el) => {

  return el * 2;

});

      
      





A continuación, eliminamos la función de flecha por completo. Usamos la misma sintaxis que antes, pero ahora preferimos la palabra clave de función. Esto es interesante porque no hay escenario en el que esta sintaxis no funcione; para cualquier número de parámetros o cadenas, no tendremos ningún problema, por lo que aquí somos fuertes en uniformidad. Este código es más largo que nuestra primera definición, pero ¿es realmente tan malo? ¿Cómo perjudica esto a un programador nuevo oa alguien que no es experto en JavaScript, pero en algún otro lenguaje? ¿Alguien con un buen conocimiento de JavaScript se confundiría con esta sintaxis al comparar?



let multipliedByTwo = arr.map(function(el) {

  return el * 2;

});

      
      





Finalmente, llegamos a la última opción: pasar solo una función. Y timesTwo se puede escribir usando cualquier sintaxis que queramos. Nuevamente, no existe ningún escenario en el que pasar el nombre de la función resulte un problema para nosotros. Pero demos un paso atrás y pensemos si tal código podría confundir a alguien. Si recién está comenzando con este código base, ¿tiene claro que timesTwo es una función, no un objeto? Definitivamente, map () servirá como una pista aquí, pero tal detalle puede perderse. ¿Qué tal dónde se declara e inicializa timesTwo? ¿Es fácil encontrarlo? ¿Está claro qué hace y cómo afecta el resultado? Todas estas consideraciones son importantes.



const timesTwo = (el) => el * 2;

let multipliedByTwo = arr.map(timesTwo);

      
      





Como puede ver, aquí no hay una respuesta obvia. Pero elegir las opciones correctas al construir su base de código solo es posible si comprende todas las opciones y sus limitaciones. En particular, sabe que necesita paréntesis, llaves y palabras clave de retorno para que su código sea coherente.



Hay una serie de cuestiones a las que hay que prestar atención al escribir código. Los problemas de rendimiento suelen ser los más comunes. Pero al comparar fragmentos de código funcionalmente idénticos, la elección debe hacerse teniendo en cuenta las personas que tendrán que leer este código.



Tal vez lo nuevo no siempre sea mejor



Entonces, vimos un ejemplo muy pronunciado en el que ambos expertos preferirían la sintaxis más nueva, incluso si no es muy conocida. También hemos visto un ejemplo que plantea muchas preguntas pero no proporciona muchas respuestas. Ahora profundicemos en el código que escribí antes ... y eliminé. Este código me convirtió en un experto del primer tipo cuando resolví el problema con una construcción sintáctica poco conocida, descuidando así a mis colegas y la conveniencia de mantener nuestra base de código.



La asignación de desestructuración le permite descomprimir valores de objetos (o matrices). Por lo general, se parece a esto.



const {node} = exampleObject;
      
      







Aquí, en una línea, se inicializa una variable y se le asigna un valor. Pero puede que ese no sea el caso.



let node

;({node} = exampleObject)

      
      





En la última línea de código, el valor se asigna a una variable mediante la desestructuración, pero la variable se declara en una línea. Esto se hace a menudo, pero muchos no se dan cuenta de que es posible.



Echemos un vistazo más de cerca a este código. Aquí se impone el punto y coma incómodo, y esto está en el código donde el punto y coma no se usa para terminar líneas. Aquí el comando se incluye entre paréntesis y se agregan llaves; es completamente incomprensible lo que está sucediendo aquí. Es difícil leer esta línea, porque como experto no tenía absolutamente ningún derecho a escribir ese código.



let node

node = exampleObject.node

      
      





Este código resuelve el problema. Funciona, está claro lo que se está haciendo en él y mis compañeros lo entenderán sin mirar a ningún lado. En cuanto a la sintaxis destructiva, no debería usarla solo porque puedo .



El código no lo es todo



Como hemos visto, la decisión del Experto-2 rara vez se pregunta si procedemos únicamente del código; sin embargo, es fácil discernir qué código debe escribir cada experto. El punto es que las máquinas deben leer el código y la gente debe interpretarlo. Por lo tanto, debe considerar factores que no solo están relacionados con el código.



Trabajar en un equipo de desarrollo de JavaScript tendrá un enfoque diferente para la selección de código que trabajar en un equipo multilingüe, cuyos miembros están menos inmersos en las sutilezas lingüísticas.



Comparemos el operador de expansión y concat () como ejemplo.



El operador de propagación se agregó a ECMAScript hace unos años y ahora es muy común. Esta es una especie de sintaxis auxiliar con la que puedes hacer muchas cosas. En particular, concatenar varias matrices.



const arr1 = [1, 2, 3];

const arr2 = [9, 11, 13];

const nums = [...arr1, ...arr2];

      
      





Con todo el potencial del operador de extensión, su símbolo no es evidente. Entonces, si no sabe lo que hace, no le ayudará mucho. Si bien ambos expertos pueden calcular que el equipo de profesionales de JavaScript familiarizados con la sintaxis, el experto-2, tal vez, piense que es posible decir lo mismo sobre el equipo multilingüe de programadores. Por lo tanto, Expert-2 puede preferir el método concat () ya que es un verbo informativo que probablemente se puede entender a partir del contexto del código.



Este fragmento de código da el mismo resultado numérico que el ejemplo anterior con el operador de extensión.



const arr1 = [1, 2, 3];

const arr2 = [9, 11, 13];

const nums = arr1.concat(arr2);

      
      





Este es solo un ejemplo para mostrar cómo los factores humanos afectan la selección del código. La base de código a la que tienen acceso las personas de diferentes equipos puede estar regida por estándares más estrictos que no necesariamente se mantienen al día con todas las innovaciones sintácticas geniales. Luego, debe desviarse del código fuente principal y tener en cuenta otros factores relacionados con su kit de herramientas que pueden complicar o facilitar la vida de las personas que trabajan en este código. Existe un código que se puede estructurar para que sea difícil de probar . Hay un código que lo llevará a una esquina y no podrá escalar o agregar nuevas funciones . Hay código donde el rendimiento se ve afectado, no todos los navegadores son compatibles o tienen poca accesibilidad . Expert-2 tiene en cuenta todos estos factores en sus recomendaciones.



Expert-2 también tiene en cuenta el factor de denominación. Pero seamos honestos, incluso los expertos en la mayoría de los casos no se las arreglan para nombrar.



Conclusión



El verdadero experto no es alguien que aplica cada chirrido de la especificación, sino alguien que conoce la especificación lo suficientemente bien como para implementar racionalmente la sintaxis y tomar decisiones bien pensadas. Un experto que crece a este nivel puede preparar nuevos expertos.



¿Qué significa esto para quienes nos consideramos expertos o al menos aspiramos a convertirnos en expertos? Esto significa que hay muchas preguntas que debe hacerse cuando escribe código. Evalúe adecuadamente a aquellos desarrolladores que son su público objetivo. El mejor código que puede escribir es el código que resuelve algún problema complejo, pero que por definición es comprensible para quienes leerán su base de código.



Sí, es muy difícil. Y a menudo no hay una única respuesta. Pero deberías pensar en lo anterior cuando escribes cada una de tus funciones.






Nuestras máquinas virtuales se pueden utilizar para el desarrollo experto de Javascript.



Regístrese usando el enlace de arriba o haciendo clic en el banner y obtenga un 10% de descuento durante el primer mes de alquiler de un servidor de cualquier configuración.






All Articles