Deno 2 ha revolucionado el desarrollo con JavaScript y TypeScript al proporcionar un entorno moderno, seguro y modular. Su sistema de importación basado en URL y su soporte nativo para TypeScript facilitan la creación de aplicaciones bien estructuradas y mantenibles. En este artículo, exploraremos las mejores prácticas para lograr modularidad en proyectos con Deno 2.

1. Introducción a la modularidad en Deno 2 Link to heading

La modularidad se refiere a dividir un programa en componentes más pequeños e independientes. En Deno 2, cada archivo actúa como un módulo independiente, importado y exportado mediante URLs. Esto elimina la necesidad de gestores de paquetes como npm y fomenta un enfoque más directo para manejar dependencias.

Ventajas de la modularidad en Deno 2 Link to heading

  • Mantenibilidad: El código está organizado y es fácil de entender.
  • Reutilización: Los módulos pueden reutilizarse en diferentes proyectos.
  • Escalabilidad: Es más fácil agregar nuevas funcionalidades.
  • Colaboración: Los equipos pueden trabajar en diferentes módulos de forma independiente.

2. Estructura de carpetas recomendada Link to heading

Una estructura de carpetas bien organizada es esencial para la modularidad. Una configuración recomendada para proyectos en Deno es:

project/
├── src/
│   ├── controllers/
│   │   └── userController.ts
│   ├── services/
│   │   └── userService.ts
│   ├── utils/
│   │   └── logger.ts
│   └── deps.ts
├── tests/
│   └── userService_test.ts
├── mod.ts
└── README.md
  • src/: Contiene el código principal de la aplicación.
  • deps.ts: Centraliza las dependencias externas.
  • tests/: Almacena los archivos de prueba.
  • mod.ts: Archivo principal que expone los módulos necesarios.

3. Uso de deps.ts para centralizar dependencias Link to heading

En Deno, es común utilizar un archivo deps.ts para centralizar todas las dependencias externas, lo que facilita su gestión y actualización.

Ejemplo de deps.ts Link to heading

export { Application, Router } from "https://deno.land/x/oak/mod.ts";
export { assertEquals } from "https://deno.land/std/testing/asserts.ts";
export { config } from "https://deno.land/x/dotenv/mod.ts";

Uso en un módulo Link to heading

import { Application, Router } from "../deps.ts";

const app = new Application();
const router = new Router();

router.get("/", (context) => {
  context.response.body = "Hello, Deno!";
});

app.use(router.routes());
app.listen({ port: 8000 });

4. Importaciones y exportaciones claras Link to heading

Las importaciones y exportaciones claras mejoran la legibilidad del código.

Exportaciones nombradas Link to heading

Prefiere exportar funciones y clases de manera nombrada:

// logger.ts
export function logInfo(message: string): void {
  console.log(`[INFO]: ${message}`);
}

Importaciones claras Link to heading

Importa solo lo necesario para evitar confusión:

import { logInfo } from "./utils/logger.ts";

logInfo("Application started");

5. Modularización de funcionalidades Link to heading

Servicios Link to heading

Los servicios encapsulan la lógica de negocio.

// userService.ts
export async function getUsers(): Promise<Array<User>> {
  return [{ id: 1, name: "John Doe" }];
}

Controladores Link to heading

Los controladores gestionan las solicitudes HTTP.

// userController.ts
import { Router } from "../deps.ts";
import { getUsers } from "../services/userService.ts";

const router = new Router();

router.get("/users", async (context) => {
  context.response.body = await getUsers();
});

export default router;

Utilidades Link to heading

Las utilidades ofrecen funciones auxiliares reutilizables.

// logger.ts
export function logError(message: string): void {
  console.error(`[ERROR]: ${message}`);
}

6. Testing modular Link to heading

Deno incluye soporte integrado para pruebas, lo que facilita el desarrollo modular.

Ejemplo de prueba Link to heading

import { getUsers } from "../src/services/userService.ts";
import { assertEquals } from "../src/deps.ts";

deno.test("getUsers devuelve una lista de usuarios", async () => {
  const users = await getUsers();
  assertEquals(users.length, 1);
  assertEquals(users[0].name, "John Doe");
});

7. Ejemplo práctico: API REST modular Link to heading

Estructura del proyecto Link to heading

project/
├── src/
│   ├── controllers/
│   │   └── userController.ts
│   ├── services/
│   │   └── userService.ts
│   ├── deps.ts
│   └── mod.ts
├── tests/
│   └── userService_test.ts
└── README.md

mod.ts Link to heading

Archivo principal que inicia la aplicación:

import { Application } from "./deps.ts";
import userRouter from "./controllers/userController.ts";

const app = new Application();
app.use(userRouter.routes());

console.log("Server running on http://localhost:8000");
app.listen({ port: 8000 });

8. Conclusión Link to heading

La modularidad en Deno 2 no solo mejora la organización del código, sino que también facilita la escalabilidad y mantenibilidad de los proyectos. Al seguir las mejores prácticas descritas, como centralizar dependencias, usar importaciones claras y escribir pruebas modulares, puedes garantizar que tus aplicaciones sean robustas y fáciles de gestionar a medida que crecen.