Arquitectura Limpia (Clean Architecture)

Parte 3

2025-02-03

La Arquitectura Limpia (Clean Architecture) es un enfoque de diseño de software propuesto por Robert C. Martin que busca la independencia de los sistemas con respecto a frameworks, bases de datos y detalles de implementación. Su principal objetivo es lograr código mantenible, flexible y fácil de probar.

A través de la separación de responsabilidades, Clean Architecture permite que los sistemas sean adaptables a cambios tecnológicos sin alterar la lógica de negocio principal. En este artículo, exploraremos sus principios, beneficios, estructura y cómo aplicarla en proyectos de software modernos.

 

Historia de la Arquitectura Limpia

La Arquitectura Limpia fue propuesta por Robert C. Martin en 2012, consolidando una serie de principios y patrones de diseño que habían evolucionado a lo largo de los años en el desarrollo de software. Uncle Bob ya había trabajado en enfoques como SOLID y la arquitectura hexagonal, que influyeron directamente en este modelo arquitectónico.

Antes de la Arquitectura Limpia, muchas aplicaciones eran altamente dependientes de frameworks y bases de datos, lo que generaba problemas de mantenibilidad y escalabilidad. Con el tiempo, los desarrolladores comenzaron a darse cuenta de la importancia de separar la lógica de negocio de la infraestructura tecnológica, lo que llevó a la formalización de Clean Architecture como un estándar de buenas prácticas en el diseño de software.

Clean Architecture se basa en conceptos previos como la Arquitectura en Capas, la Arquitectura Hexagonal (Ports and Adapters) de Alistair Cockburn y la Arquitectura en Cebolla (Onion Architecture) de Jeffrey Palermo, pero con un enfoque más claro en la independencia de los componentes y la testabilidad del código.

 

Principios Fundamentales de Clean Architecture

La Arquitectura Limpia sigue varios principios clave que garantizan la modularidad y la independencia de los componentes del software:

1. Independencia de Frameworks

  • La aplicación no debe depender de frameworks específicos.
  • Los frameworks son herramientas, no dictan la arquitectura.

2. Independencia de la Interfaz de Usuario

  • La UI puede cambiar sin afectar la lógica de negocio.
  • Se pueden crear diferentes interfaces (web, móvil, CLI) sin alterar el núcleo.

3. Independencia de la Base de Datos

  • Se puede cambiar la base de datos sin modificar la lógica de negocio.
  • La lógica no debe depender de detalles de almacenamiento.

4. Independencia de Detalles Externos

  • La lógica de negocio es agnóstica a frameworks, bibliotecas o herramientas externas.

 

Estructura de Clean Architecture

La arquitectura se organiza en capas concéntricas, donde cada capa tiene reglas claras sobre cómo interactuar con las demás:

1. Entidades (Core/Enterprise Business Rules)

  • Representan las reglas de negocio más generales.
  • Son independientes de cualquier tecnología o framework.

2. Casos de Uso (Application Business Rules)

  • Contienen la lógica específica de aplicación.
  • Orquestan el comportamiento del sistema según los requerimientos del negocio.

3. Adaptadores de Interfaz (Interface Adapters)

  • Transforman datos entre la capa de aplicación y los controladores, la UI, bases de datos o APIs externas.
  • Incluyen controladores, presentadores y gateways.

4. Infraestructura y Frameworks (Frameworks & Drivers)

  • Contiene herramientas externas como bases de datos, frameworks web y bibliotecas de terceros.
  • No debe contener lógica de negocio.

 

Beneficios de Clean Architecture

Alta mantenibilidad: Separación clara de responsabilidades facilita cambios sin afectar todo el sistema.

Facilidad para pruebas: Permite testear la lógica de negocio sin depender de la infraestructura.

Escalabilidad: Permite agregar nuevas funcionalidades sin afectar capas internas.

Flexibilidad tecnológica: Se puede cambiar la base de datos o framework sin alterar la lógica de negocio.

 

Organización del Proyecto en Clean Architecture

La Arquitectura Limpia afecta directamente la forma en que se estructura y organiza un proyecto de software. Siguiendo sus principios, se recomienda dividir el código en capas bien definidas para garantizar la separación de responsabilidades y la independencia de los componentes. A continuación, explicamos cómo organizar un proyecto bajo este modelo:

Separación en Capas

El código debe dividirse en capas bien estructuradas, cada una con una responsabilidad específica:

  • Capa de Entidades (Entities): Contiene las reglas de negocio más generales y reutilizables.
  • Capa de Casos de Uso (Use Cases): Define la lógica de aplicación y las interacciones entre las entidades.
  • Capa de Adaptadores de Interfaz (Interface Adapters): Maneja la conversión de datos entre la aplicación y las entradas/salidas externas.
  • Capa de Infraestructura (Infrastructure & Frameworks): Incluye bases de datos, frameworks y bibliotecas externas.

Organización de Archivos y Carpetas

Se recomienda una estructura de archivos clara y modular para aplicar Clean Architecture en un proyecto real, podemos seguir una estructura de carpetas organizada por capas:

/ src
  / core
    / entities
    / usecases
  / infrastructure
    / database
    / frameworks
  / application
    / controllers
    / gateways
  / ui
    / views
    / api

Implementación de Clean Architecture en Node.js

A continuación, presentamos una implementación sencilla de Clean Architecture en Node.js con una estructura de archivos bien definida.

Estructura del Proyecto

/ src
  / core
    / entities
      user.ts
    / usecases
      getUser.ts
  / infrastructure
    / database
      userRepository.ts
  / application
    / controllers
      userController.ts
    / gateways
      userGateway.ts
  / ui
    / routes
      userRoutes.ts
  server.ts

1. Definiendo la Entidad (Entity)

Archivo: src/core/entities/user.ts

export class User {
  constructor(public id: number, public name: string) {}
}

2. Creando el Caso de Uso (Use Case)

Archivo: src/core/usecases/getUser.ts

import { User } from "../entities/user";
import { UserRepository } from "../../infrastructure/database/userRepository";

export class GetUserUseCase {
  constructor(private userRepository: UserRepository) {}
  
  execute(userId: number): User {
    return this.userRepository.findById(userId);
  }
}

3. Implementando el Repositorio (Infrastructure Layer)

Archivo: src/infrastructure/database/userRepository.ts

import { User } from "../../core/entities/user";

export class UserRepository {
  private users = [new User(1, "John Doe"), new User(2, "Jane Doe")];

  findById(id: number): User {
    return this.users.find(user => user.id === id) || new User(0, "Not Found");
  }
}

4. Creando el Controlador (Application Layer)

Archivo: src/application/controllers/userController.ts

import { GetUserUseCase } from "../../core/usecases/getUser";
import { UserRepository } from "../../infrastructure/database/userRepository";

export class UserController {
  private getUserUseCase = new GetUserUseCase(new UserRepository());

  getUser(req, res) {
    const userId = parseInt(req.params.id, 10);
    const user = this.getUserUseCase.execute(userId);
    res.json(user);
  }
}

5. Configurando las Rutas (UI Layer)

Archivo: src/ui/routes/userRoutes.ts

import express from "express";
import { UserController } from "../../application/controllers/userController";

const router = express.Router();
const userController = new UserController();

router.get("/user/:id", (req, res) => userController.getUser(req, res));

export default router;

6. Configurando el Servidor

Archivo: server.ts

import express from "express";
import userRoutes from "./src/ui/routes/userRoutes";

const app = express();

app.use(express.json());
app.use(userRoutes);

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});

Con esta implementación sencilla de Clean Architecture en Node.js, logramos modularidad y separación de responsabilidades, permitiendo un mantenimiento y escalabilidad eficientes.

Últimas publicaciones

Guía para Líderes Tecnológicos: Actividades Clave al Unirse a un Nuevo Equipo

14/02/2025

Ver articulo

Patrones de Observabilidad en Microservicios

05/02/2025

Ver articulo

Transacciones Distribuidas en Microservicios y Patrones Usables

05/02/2025

Ver articulo
Whatsapp Mentores Tech