Inicio / Artículos

La verdadera complejidad de JavaScript moderno proviene de las herramientas, no del lenguaje en sí.

Este artículo explica cómo las características principales de JavaScript, como async/await y la cadena opcional, simplifican el código, mientras que las herramientas y dependencias excesivas generan una complejidad innecesaria.

Editor: REACTAPP.TOP17 min de lectura3951 palabras

Fuentes: Modern JavaScript Is Simpler Than We Pretend

Hay un momento extraño en el desarrollo con JavaScript cuando te das cuenta de que sabes demasiado.

No tanto sobre el propio JavaScript.

Sí, demasiado sobre el ecosistema que rodea a JavaScript.

Aprendiste React. Luego aparecieron los hooks. Después entró en escena la gestión de estado, seguida por una biblioteca favorita para ello. Has formado opiniones firmes sobre cómo obtener datos en el cliente. Entiendes qué hace un bundler aunque rara vez abras su archivo de configuración. Has encontrado componentes servidores, señales, islands, entornos de ejecución en el edge, meta-marcos, herramientas de compilación, linteres, formateadores, gestores de paquetes, y nada menos que tres convenciones competidoras para organizar una carpeta llamada components.

Luego abres un archivo JavaScript muy pequeño y te das cuenta de que la lógica real se reduce a esto:

const users = await fetch("/api/users").then(res => res.json());

Eso es todo.

El lenguaje en sí suele ser sorprendentemente sencillo.

Lo que hace que el JavaScript moderno parezca abrumador es todo lo que se ha añadido encima de él.

Ver cómo los conjuntos de código en JavaScript pasan de unos pocos archivos a sistemas con cientos de dependencias indica que hemos confundido la sofisticación con una complejidad real.

Trabajar con JavaScript moderno no significa adoptar todas las nuevas características que ofrece.

Significa reconocer qué problemas el lenguaje ya ha resuelto por usted.

El lenguaje ha crecido silenciosamente

En el pasado, JavaScript tenía la reputación de ser un lenguaje extraño y diseñado apresuradamente que, de alguna manera, terminó siendo el motor de toda la web.

Parte de esa reputación era justificada.

Las versiones iniciales presentaban verdaderas dificultades. Las APIs de los navegadores no funcionaban de manera consistente en diferentes entornos. Razonar sobre código asíncrono era realmente complicado. El entorno de ejecución carecía de módulos integrados, por lo que los grandes conjuntos de código dependían de patrones que a menudo resultaban más complicados que el propio lenguaje.

El JavaScript de hoy es una historia completamente diferente.

Esto es lo que ahora tiene a su disposición:

  • variables de ámbito de bloque mediante const y let
  • sintaxis de funciones concisa a través de funciones de flecha
  • desestructuración para extraer valores de objetos y arrays
  • interpolación de cadenas con literales de plantilla
  • parámetros por defecto que permiten omitir verificaciones manuales
  • sintaxis de expansión para copiar y combinar datos
  • un sistema de módulos nativo
  • clases, reservadas para los casos en que realmente sean necesarias
  • Una forma integrada de representar trabajos asíncronos a través de promesas
  • Sintaxis que hace que el trabajo asíncrono se lea como pasos ordinarios, es decir async y await
  • Acceso seguro a propiedades mediante enlace opcional
  • Una forma más limpia de recurrir a valores por defecto, mediante unión nula
  • Ayudas para arrays y colecciones integradas en el lenguaje
  • Verdadera privacidad dentro de las clases mediante campos privados
  • Generadores e iteradores para secuencias personalizadas
  • Estructuras de datos Map y Set dedicadas
  • Soporte sólido y nativo para JSON
  • Runtimes que se vuelven cada vez más potentes
  • Ninguna de las características de esa lista hace que el lenguaje sea difícil de usar.

    El verdadero problema es que los desarrolladores tienden a memorizar todo esto como un montón abrumador de sintaxis en lugar de tratarlo como una herramienta bastante compacta para expresar conceptos de programación cotidianos.

    Una vez que se comprenden las ideas subyacentes, la sintaxis deja de parecer intimidante.

    Probablemente no necesites la mitad de la arquitectura

    Una de las formas más rápidas de complicar excesivamente un proyecto en JavaScript es tomar decisiones arquitectónicas antes incluso de haber entendido el problema.

    Imagina un panel de control: necesita cargar algunos datos, permitir que el usuario los edite y guardar el resultado.

    Un primer enfoque sensato podría ser este:

    async function loadUsers() {
      const response = await fetch("/api/users");
    
      if (!response.ok) {
        throw new Error("Failed to load users");
      }  return response.json();
    }
    

    Luego, llamar a la función es tan sencillo como:

    const users = await loadUsers();
    

    Puedes crear una cantidad sorprendente de software funcional basándote únicamente en ese patrón.

    Pero las costumbres modernas nos llevan a hacer inmediatamente una serie de preguntas en su lugar:

    ¿Debería recurrir de inmediato a un framework?

    ¿Qué hay de una capa para obtener datos?

    ¿Necesita una biblioteca dedicada solo para gestionar el estado?

    ¿Debería haber un mecanismo de caché delante de sus solicitudes?

    ¿Es necesaria una biblioteca de validación de esquemas?

    ¿Cómo deberían organizarse las carpetas y los archivos?

    ¿Qué patrón deberían seguir sus componentes?

    ¿Qué herramientas de compilación deberían unir todo?

    ¿Qué enfoque debería usar el servidor para manejar las solicitudes?

    Estas preguntas pueden ser importantes con el tiempo.

    Rara vez son las preguntas adecuadas para comenzar.

    La primera pregunta siempre debería ser:

    ¿Qué es lo que realmente necesita esta aplicación?

    Esa distinción es importante porque toda abstracción tiene un costo.

    Cada uno agrega un concepto que otra persona tendrá que aprender antes de poder manipular el código con seguridad.

    Si una función sencilla cumple la función, probablemente no necesites una clase.

    Si un módulo cumple la función, probablemente no necesites un framework.

    Si un objeto sencillo puede almacenar tu estado, probablemente no necesites un sistema de gestión de estado.

    Si fetch() satisface tus necesidades, otra capa de obtención de datos podría ser simplemente una distancia adicional entre tú y la red.

    Nada de esto significa que los frameworks sean inherentemente una mala idea.

    Significa que un framework debería resolver un problema real que tengas, no uno que hayas asumido que tendrías.

    async y await eliminaron una gran cantidad de carga mental

    No todas las actualizaciones importantes en JavaScript moderno son llamativas.

    async y await son un excelente ejemplo de una mejora sutil pero significativa.

    Miremos el antiguo enfoque basado en callbacks:

    getUser(id, function (user) {
      getOrders(user, function (orders) {
        processOrders(orders, function (result) {
          console.log(result);
        });
      });
    });
    

    El problema no era solo que este código resultaba visualmente desagradable.

    Los callbacks profundamente anidados dificultaban enormemente rastrear el flujo de ejecución.

    Las promesas mejoraron la situación:

    getUser(id)
      .then(user => getOrders(user))
      .then(orders => processOrders(orders))
      .then(result => console.log(result));
    

    Luego, async y await acercaron aún más el código asíncrono a una lógica aparentemente secuencial y sencilla:

    const user = await getUser(id);
    const orders = await getOrders(user);
    const result = await processOrders(orders);
    
    console.log(result);
    

    Este es el tipo de característica que pasa desapercibida una vez se vuelve habitual.

    Eso es, de hecho, una señal de un buen diseño.

    Las características de un lenguaje bien diseñadas tienden a desaparecer en el uso cotidiano en lugar de llamar la atención sobre sí mismas.

    El error consiste en suponer que, dado que el comportamiento asíncrono es inherentemente complicado, la sintaxis que lo envuelve también tiene que serlo.

    La mayoría de las veces, no es así.

    El desestructurado no es una prueba de personalidad

    Algunos desarrolladores dependen tanto del desestructurado que el código ordinario se vuelve más difícil de analizar.

    Tomen esto:

    const { name, email, address: { city } } = user;
    

    Tiene su lugar.

    Pero otras veces, esto se lee con mayor claridad:

    const name = user.name;
    const email = user.email;
    const city = user.address.city;
    

    No hay puntos extra por meter más sintaxis en una sola línea.

    El desestructurado cobra sentido cuando hace que la conexión entre el código y los datos subyacentes sea más clara.

    Por ejemplo:

    function createUser({ name, email }) {
      // ...
    }
    

    Eso es expresivo.

    Indica al lector exactamente qué tipo de objeto espera la función.

    Pero una vez que el desestructuración se vuelve lo suficientemente anidada como para que el lector tenga que reconstruir mentalmente la estructura original del objeto, esta característica deja de ser útil y comienza a perjudicar.

    JavaScript moderno sigue siendo sencillo cuando se trata la sintaxis como una forma de comunicación, y no como decoración.

    La cadena opcional resolvió un problema real

    Algunas características realmente reducen la sobrecarga.

    La cadena opcional es un buen ejemplo.

    Antes de que existiera, a menudo se veía algo como:

    if (
      user &&
      user.profile &&
      user.profile.settings &&
      user.profile.settings.theme
    ) {
      return user.profile.settings.theme;
    }
    

    Ahora se puede escribir:

    return user?.profile?.settings?.theme;
    

    Eso no solo es más breve.

    Expresa directamente la intención.

    El desarrollador está, en efecto, diciendo:

    Este camino podría no existir. Si no es así, salir de forma segura.

    La misma lógica se aplica al coalescencia nula:

    const pageSize = options.pageSize ?? 20;
    

    que con frecuencia es más preciso que:

    const pageSize = options.pageSize || 20;
    

    Porque || trata los valores falsos como 0 o "" como si no existieran, mientras que ?? solo reacciona ante null o undefined.

    Características como estas merecen ser aprendidas porque eliminan la complejidad accidental en lugar de añadir adornos estilísticos.

    Aquí hay un filtro útil para aplicar a cualquier nueva sintaxis:

    ¿Hace esto que el código sea más fácil de comprender?

    Si la respuesta es sí, aprendelo.

    Si solo hace que el código se vea impresionante, procede con cautela.

    JavaScript moderno no significa acrobacias de programación funcional

    Existe otra fuente común de complejidad evitable: la suposición de que el JavaScript moderno debe escribirse en un estilo altamente funcional.

    A menudo te encontrarás con algo como:

    const result = users
      .filter(user => user.active)
      .map(user => ({
        ...user,
        displayName: `${user.firstName} ${user.lastName}`
      }))
      .reduce((groups, user) => {
        const key = user.department;
        groups[key] ??= [];
        groups[key].push(user);
        return groups;
      }, {});
    

    No hay nada de malo en eso por sí mismo.

    Pero es fácil olvidar que un bucle simple sigue siendo JavaScript perfectamente válido.

    Esta versión también puede ser igualmente razonable:

    const result = {};
    
    for (const user of users) {
      if (!user.active) continue;  const department = user.department;  if (!result[department]) {
        result[department] = [];
      }  result[department].push({
        ...user,
        displayName: `${user.firstName} ${user.lastName}`
      });
    }
    

    La versión con bucle ocupa más líneas.

    También puede ser más sencilla de seguir al depurar.

    El código profesional no se juzga por la cantidad de líneas que utiliza.

    Se juzga por el poco esfuerzo cognitivo innecesario que exige a quien lo lea después.

    A veces map, filter y reduce reducen ese esfuerzo.

    Otras veces un bucle hace el trabajo mejor.

    Saber cuándo usar qué herramienta es más importante que memorizar cada método de array disponible.

    El modelo de objetos de JavaScript es más sencillo una vez que dejas de luchar contra él

    Los objetos de JavaScript pueden simplemente almacenar datos:

    const user = {
      name: "Sarah",
      age: 31
    };
    

    También pueden almacenar funciones:

    const user = {
      name: "Sarah",
    
      greet() {
        return `Hello, ${this.name}`;
      }
    };
    

    Se pueden definir clases:

    class User {
      constructor(name) {
        this.name = name;
      }
    
      greet() {
        return `Hello, ${this.name}`;
      }
    }
    

    Pero las clases no son obligatorias en todas las situaciones.

    Un objeto simple junto con una función de fábrica suele ser igualmente claro:

    function createUser(name) {
      return {
        name,
    
        greet() {
          return `Hello, ${name}`;
        }
      };
    }
    

    Ninguno de los estilos es el mejor en todos los casos.

    La verdadera habilidad radica en reconocer qué necesita realmente un fragmento de código dado.

    Las clases tienen sentido cuando se trabaja con identidad real de objetos, comportamiento, gestión del ciclo de vida, herencia o encapsulación.

    Los objetos simples suelen ser adecuados para datos sencillos.

    Las funciones suelen ser adecuadas para transformaciones.

    Los módulos suelen ser adecuados para delimitar las partes de un sistema.

    No es necesario convertir cada concepto en una clase solo porque el lenguaje las soporte.

    El sistema de módulos se cuenta entre las características más fuertes de JavaScript

    Los módulos nativos resuelven silenciosamente un problema que antes generaba mucha complejidad innecesaria.

    Considere este patrón:

    // math.js
    export function add(a, b) {
      return a + b;
    }
    

    Junto con:

    // app.js
    import { add } from "./math.js";
    
    console.log(add(2, 3));
    

    Esta configuración crea una delimitación de dependencias clara. El módulo que importa solo incluye lo que realmente necesita. La dependencia en sí permanece visible en el código. Se puede probar la función por separado. Y todo esto no requiere meterlo todo en un espacio de nombres global extenso.

    Lo que lo hace significativo es que no se necesita un framework para lograr la modularidad. El lenguaje en sí mismo permite delinear líneas claras entre las partes de su sistema. Un proyecto podría organizarse de la siguiente manera:

    src/
      users.js
      orders.js
      payments.js
      validation.js
      config.js
      app.js
    

    sin obligar a que cada archivo demuestre un patrón de diseño.

    Un módulo bien estructurado suele hacer evidentes tres cosas con solo mirarlo: qué parte de la funcionalidad le pertenece, qué partes de esa funcionalidad pone a disposición del exterior y en qué otros fragmentos de código depende para funcionar.

    Una vez que estas cosas son evidentes, su proyecto ya está en buen estado.

    No todo necesita ser abstractado

    Este podría ser el punto más importante aquí.

    Es común que los desarrolladores introduzcan abstracción en cuanto detectan código repetido. Pero la repetición por sí sola no necesariamente es un problema que merezca solución.

    Digamos que tienes:

    const user = await fetch("/api/users/42");
    const order = await fetch("/api/orders/18");
    

    En algún momento podrías darte cuenta de que la lógica para manejar las respuestas se repite constantemente. Esa observación podría llevarte a escribir:

    async function getJson(url) {
      const response = await fetch(url);
    
      if (!response.ok) {
        throw new Error(`Request failed: ${response.status}`);
      }  return response.json();
    }
    

    Lo cual te permite simplificarlo a:

    const user = await getJson("/api/users/42");
    const order = await getJson("/api/orders/18");
    

    Esa abstracción merece su lugar, ya que tiene una función clara que desempeñar.

    Ahora contrasta eso con la creación de una fábrica genérica de solicitudes, un patrón de estrategia de solicitudes, una interfaz de repositorio, un adaptador de transporte, un envoltorio de respuesta y una capa de servicio completa antes incluso de haber realizado la segunda llamada a la API. En ese escenario en realidad no se ha reducido la complejidad; simplemente se ha trasladado al interior de la propia arquitectura.

    Este patrón aparece constantemente en los repositorios de código en JavaScript. Un desarrollador detecta dos líneas similares e inmediatamente comienza a diseñar para un futuro hipotético. Las buenas prácticas de ingeniería suelen recomendar el enfoque opuesto.

    Espera hasta que la repetición sea lo suficientemente evidente como para que se revele la abstracción adecuada.

    Las abstracciones introducidas demasiado temprano son notoriamente difíciles de eliminar posteriormente, sobre todo porque al final nadie puede asegurar con certeza si siguen realizando un trabajo útil.

    El navegador ya hace mucho por ti

    JavaScript moderno puede parecer más complicado de lo necesario en parte porque los desarrolladores pierden de vista cuánto puede hacer la plataforma en sí.

    Puedes manipular el DOM directamente. Puedes adjuntar oyentes de eventos. Puedes enviar solicitudes de red. Tienes almacenamiento web a tu disposición. Puedes crear trabajadores web. Puedes establecer conexiones WebSocket. Puedes gestionar el historial del navegador. Puedes trabajar con formularios nativos.

    Todo esto está disponible sin necesidad de recurrir a un paquete para cada tarea menor. Por ejemplo:

    const button = document.querySelector("#save");
    
    button.addEventListener("click", async () => {
      const response = await fetch("/api/save", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify({ message: "Hello" })
      });  if (!response.ok) {
        throw new Error("Save failed");
      }
    });
    

    Esa es una interacción completamente funcional en una aplicación real, sin la participación de ningún framework.

    Nada de esto es un argumento en contra de los frameworks: resuelven problemas reales. Pero la plataforma subyacente merece más reconocimiento del que suele recibir. Una vez que comprendes lo que el navegador y el lenguaje ya te ofrecen de forma gratuita, estás en una posición mucho mejor para decidir qué debería ser responsabilidad real de un framework.

    Las dependencias tienen un costo

    Instalar un paquete puede ahorrarte tiempo real. También puede obligarte a un compromiso a largo plazo con algo que podrías haber escrito tú mismo en diez líneas de código.

    Toma una pequeña utilidad como:

    function clamp(value, min, max) {
      return Math.min(Math.max(value, min), max);
    }
    

    Es muy probable que no necesite un paquete externo para eso. Pero cosas como la autenticación, la criptografía, el cálculo complejo de fechas, los clientes de base de datos, el procesamiento de imágenes y la lógica de validación avanzada pertenecen a una categoría completamente diferente.

    La lección aquí no es “evitar las dependencias a toda costa”. Se trata de ser consciente de lo que cada una realmente le cuesta.

    Cada dependencia conlleva:

    • mantenimiento continuo
    • implicaciones de seguridad
    • trabajo de actualización de versiones
    • documentación para leer
    • un árbol de dependencias transitivas
    • efectos en su proceso de compilación
    • otra abstracción más que debe aprender

    Los desarrolladores de JavaScript más competentes no son necesariamente aquellos que han memorizado la mayor cantidad de paquetes npm. Son aquellos que saben identificar cuándo un paquete en realidad no se necesita.

    TypeScript añade una complejidad percibida, pero eso es un tema aparte

    En proyectos con grandes bases de código, TypeScript puede mejorar significativamente la experiencia diaria de desarrollo. Al mismo tiempo, introduce una capa adicional al lenguaje.

    Acabas escribiendo cosas como:

    type User = {
      id: number;
      name: string;
      email: string;
    };
    

    Junto con:

    function getUser(id: number): Promise<User> {
      // ...
    }
    

    Esto tiene un valor real. Pero es importante separar la complejidad que proviene del lenguaje de la complejidad que surge de la configuración de las herramientas.

    El propio JavaScript no se ha vuelto más difícil simplemente porque un proyecto añade verificación de tipos, un linter, un bundler de módulos, un framework de interfaz gráfica, un conjunto de pruebas automatizadas y varios complementos de compilación. Lo que se ha vuelto más elaborado es tu entorno de desarrollo, y esa sofisticación puede resultar muy beneficiosa.

    Pero un conjunto de herramientas complejo no debería hacer que concluyas que el lenguaje en el que se basan es inherentemente complicado. A menudo, en realidad es bastante sencillo.

    La verdadera habilidad radica en elegir la abstracción más mínima y útil

    Hay un patrón que se repite en todo lo discutido hasta ahora.

    Escribir buen JavaScript tiene menos que ver con dominar cada función disponible y más con seleccionar la herramienta más ligera que cumpla la tarea.

    Necesitas transformar el contenido de un array? Utiliza map.

    Necesitas reducir un conjunto de valores? Utiliza filter.

    Necesitas secuenciar tareas asíncronas? Utiliza async y await.

    Necesitas un fragmento de lógica reutilizable con límites claros? Escribe una función o un módulo.

    Necesitas una colección donde las claves no estén limitadas a cadenas de texto? Examina Map.

    ¿Necesita garantizar la unicidad? Mire Set.

    ¿Necesita acceder de forma segura a una propiedad que podría faltar? Utilice la cadena opcional.

    ¿Necesita un valor por defecto solo cuando algo es null o undefined? Use ??.

    ¿Necesita un contenedor de datos sencillo? Un objeto servirá.

    ¿Necesita un comportamiento más avanzado y una identidad vinculada a sus datos? Una clase podría ser adecuada.

    ¿Necesita estructurar una aplicación realmente grande? Ahí es cuando merece la pena considerar un framework.

    Preste atención a esa secuencia.

    Comienza con el lenguaje en sí.

    Luego, observe lo que ya ofrece la plataforma.

    A continuación, las abstracciones pequeñas y diseñadas específicamente para un fin.

    Luego, las bibliotecas externas.

    Y finalmente, los frameworks.

    Invertir ese orden es la causa de mucha complejidad innecesaria.

    La simplicidad no es la ausencia de ingeniería

    Existe una suposición común pero engañosa sobre lo que realmente significa un código “simple”.

    Algunas personas equiparan la simplicidad con la falta de experiencia.

    Esa equivalencia no es válida.

    Imaginemos a alguien nuevo en este campo escribiendo algo como esto:

    function process(data) {
      // everything
    }
    

    A primera vista parece mínimo, pero resulta realmente difícil de mantener una vez que crece.

    Un desarrollador con más experiencia podría dividir la misma lógica en cinco módulos pequeños, cada uno con límites claros y bien definidos.

    Aunque hay más componentes, en realidad es mucho más fácil de comprender.

    Esa es una clase diferente y más significativa de simplicidad.

    El objetivo no es reducir la cantidad de archivos, la lista de dependencias o el número de líneas.

    El objetivo es eliminar la complejidad que no tiene justificación.

    Esa distinción cobra cada vez más importancia a medida que crece la base de código.

    Un script de solo veinte líneas aún puede resultar confuso.

    Una aplicación con dos mil líneas, sorprendentemente, puede ser fácil de seguir.

    El factor decisivo suele no ser la cantidad bruta de código.

    Se trata de si ese código hace que el modelo subyacente sea evidente para el lector.

    Deje de tratar cada nueva función como conocimiento obligatorio

    JavaScript evoluciona rápidamente, y ese ritmo genera su propio tipo de estrés.

    Se acostumbra a una forma de hacer algo, y unos meses después un enfoque diferente domina todas las discusiones.

    Aparece un nuevo framework.

    Un nuevo entorno de ejecución comienza a ganar popularidad.

    Un nuevo patrón de renderizado se convierte en la tendencia.

    Llega una nueva sintaxis.

    Es fácil sentir que constantemente se está quedando atrás.

    Lo más probable es que no sea así.

    No es necesario que absorbas cada nueva técnica de JavaScript en el instante en que alguien escribe un artículo al respecto.

    En lugar de eso, invierte en los fundamentos.

    Familiarízate con la programación asíncrona.

    Familiarízate con el ámbito de ejecución.

    Familiarízate con los cierres.

    Familiarízate con los objetos.

    Familiarízate con los módulos.

    Familiarízate con el bucle de eventos.

    Familiarízate con las promesas.

    Familiarízate con el manejo de errores.

    Familiarízate con las API que expone tu navegador o entorno de ejecución.

    Familiarízate con el seguimiento de cómo fluyen los datos dentro de una aplicación.

    Solo entonces adquiere nuevas herramientas, y únicamente cuando un problema real las requiera.

    Ese enfoque construye conocimientos que perduran.

    La familiaridad con un framework específico puede volverse obsoleta.

    Pero un modelo mental sólido de cómo funcionan los programas, generalmente no.

    El mejor código JavaScript a menudo parece aburrido

    Los desarrolladores suelen darse cuenta de esto con el tiempo.

    El código más fácil de mantener rara vez impresiona a nadie al leerlo por primera vez.

    No apila cinco abstracciones una encima de la otra.

    No requiere un diagrama para que la primera función tenga sentido.

    No utiliza todas las características que el lenguaje añadió en su última versión.

    A menudo, simplemente parece sencillo.

    Eso no es una crítica, es una ventaja.

    Al abrir el archivo, la intención queda inmediatamente clara:

    import { getUser } from "./users.js";
    
    export async function loadProfile(id) {
      const user = await getUser(id);  if (!user) {
        throw new Error("User not found");
      }  return {
        name: user.name,
        email: user.email
      };
    }
    

    Casi no hay nada que decodificar.

    La función obtiene información de un usuario.

    Verifica si esa búsqueda tuvo éxito.

    Devuelve los datos que realmente se necesitan.

    Nada aquí intenta demostrar lo inteligente que es su autor.

    Sencillamente evita que el lector realice trabajos innecesarios, y esa es una característica mucho más valiosa en el código.

    JavaScript moderno es más simple que nuestros proyectos

    JavaScript tiene sus propios problemas reales. Todo lenguaje los tiene.

    Pero gran parte de la complejidad que la gente atribuye al “JavaScript moderno” en realidad no proviene del lenguaje en sí.

    Proviene de las capas que se superponen sobre él.

    Frameworks.

    Sistemas de construcción.

    Dependencias.

    Convenciones.

    Abstracciones.

    Herramientas.

    Elegencias arquitectónicas.

    Algunas de estas capas están realmente justificadas.

    Otras no lo están.

    La pregunta correcta no es si una herramienta se considera moderna.

    La pregunta correcta es si realmente reduce la complejidad para el problema específico que tienes ante ti.

    Antes de recurrir a otra dependencia, verifica si la plataforma ya la cubre.

    Antes de introducir otra abstracción, comprueba si la duplicación que intentas resolver es real.

    Antes de agregar otra capa arquitectónica, analiza con precisión qué fallos se supone que debe prevenir.

    Antes de elegir otro framework, determina qué limitación en tu configuración actual estás tratando realmente de solucionar.

    Y antes de concluir que JavaScript en sí es demasiado complicado, intenta resolver el problema utilizando únicamente el lenguaje y la plataforma en la que se ejecuta.

    Podrías sorprenderte con el resultado.

    El lenguaje suele ser la parte más sencilla de todo el proceso.

    Son los desarrolladores quienes siguen acumulando capas sobre él.

    A veces, la decisión más innovadora que puedes tomar es eliminar una capa en lugar de añadir otra.

    El mejor JavaScript no es el código que utiliza la mayor cantidad de herramientas.

    Es el código en el que cada herramienta incluida realmente ha ganado su lugar.

    Lecturas relacionadas