¿Qué tal si pudieras inventar tu propio lenguaje?
\n\nImagina: escribes código que se lee como texto en inglés común. Sin paréntesis innecesarios, sin for ni if, solo instrucciones claras y entendibles. ¿Suena a ciencia ficción? Pues no lo es. Esto es un DSL (Domain-Specific Language) — un lenguaje específico del dominio, creado para una tarea concreta.
En PythonLib a menudo hablamos de cómo hacer el código más limpio y expresivo. Hoy vamos a abordarlo desde un ángulo inesperado: tomaremos JavaScript y lo convertiremos en una herramienta para crear tus propios mini-lenguajes. ¿Para qué? Para que tus configuraciones dejen de ser un «batiburrillo» y la lógica de negocio suene como música.
\n\n¿Listo para convertirte en lingüista del mundo de la programación? ¡Allá vamos!
\n\nDSL: ¿qué es y para qué sirve?
\n\nUn DSL (lenguaje específico del dominio) es un lenguaje de programación (o una extensión sintáctica del mismo) creado para resolver problemas de un área específica. A diferencia de los lenguajes de propósito general (C++, Python, Java), un DSL no intenta abarcarlo todo. Su objetivo es ser lo más expresivo posible dentro de su nicho.
\n\nEjemplos de la vida real:
\n- \n
- SQL — lenguaje para trabajar con bases de datos. \n
- HTML — lenguaje de marcado para páginas web. \n
- Regex — lenguaje para búsqueda por patrones. \n
- Makefile — lenguaje para describir la compilación de proyectos. \n
Ahora imagina que puedes crear un lenguaje igual de conveniente para tu tarea: para describir reglas de negocio, para configurar bots, para construir consultas complejas a APIs. Crear un DSL en JavaScript es un superpoder que hace que el código sea autodocumentado y reduce la barrera de entrada para nuevos desarrolladores.
\n\nDSL internos y externos: dos caminos hacia un mismo objetivo
\n\nDSL interno (Embedded DSL)
\nEs una capa adicional sobre un lenguaje existente. Usas la sintaxis de JavaScript, pero construyes con ella los «ladrillos» de un nuevo lenguaje. El ejemplo más popular es la Fluent API (cadenas de métodos).
\n\nVentajas: no necesitas escribir un analizador sintáctico, usas todas las capacidades del lenguaje anfitrión (depuración, tipos, herramientas).
\nDesventajas: estás limitado por la sintaxis de JavaScript (no puedes crear nuevos operadores).
DSL externo
\nInventas tu propia sintaxis desde cero y luego escribes un analizador sintáctico (o compilador) que la convierte en JavaScript.
\n\nVentajas: total libertad sintáctica, puedes crear un lenguaje muy conciso.
\nDesventajas: necesitas escribir y mantener el analizador sintáctico, es más difícil de depurar.
Para la mayoría de los proyectos, un DSL en JavaScript comienza con el enfoque interno: es más simple y se puede implementar hoy mismo.
\n\nEscribiendo nuestro primer DSL: de la configuración a la poesía
\n\nVamos a crear un DSL interno para describir rutas en una aplicación web. En lugar de escribir:
\n\nconst routes = [\n { path: '/users', handler: usersHandler, method: 'GET' },\n { path: '/users/:id', handler: userById, method: 'GET' },\n { path: '/users', handler: createUser, method: 'POST' }\n];\n\nQueremos escribir así:
\n\nconst router = new Router();\nrouter\n .get('/users', usersHandler)\n .get('/users/:id', userById)\n .post('/users', createUser);\n\nYa es mejor, ¿verdad? Pero esto es solo el comienzo. Un DSL real debe ser aún más expresivo.
\n\nPaso 1: Fluent API (Cadenas de métodos)
\n\nLa forma más sencilla de crear un lenguaje específico del dominio es devolver this desde cada método.
class Router {\n constructor() {\n this.routes = [];\n }\n\n get(path, handler) {\n this.routes.push({ path, handler, method: 'GET' });\n return this; // clave para la cadena\n }\n\n post(path, handler) {\n this.route