Domain-Driven Design en Go: Cómo no ahogarse en capas de abstracción

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿Por qué su proyecto Go pide a gritos DDD?

\n\n

¿Alguna vez ha escrito un servicio en Go que comenzó con un par de endpoints y tres tablas en la base de datos, y seis meses después se convirtió en un monstruo con archivos handler.go de kilómetros de largo y números mágicos esparcidos por todo el código? ¿Le suena familiar? Yo también pasé por eso.

\n\n

El problema del desarrollo clásico en Go es que pensamos demasiado pronto en bases de datos y JSON, olvidándonos de lo principal: la lógica de negocio. Domain-Driven Design (DDD) viene al rescate justo cuando queremos poner orden en el caos. Pero, ¿cómo aterrizar DDD en Go si el lenguaje no nos mima con clases y herencia? Vamos a descubrirlo.

\n\n

En este artículo, le mostraré cómo aplicar Domain-Driven Design en proyectos Go sin fanatismo excesivo, con ejemplos de código funcionales y una estructura clara. Aprenderá a separar el grano de la paja y a hacer un código que sea comprensible no solo para la máquina, sino también para el analista de negocio.

\n\n

¿Qué es DDD y por qué lo necesita un desarrollador Go?

\n\n

Domain-Driven Design no trata sobre tecnología. Trata sobre el lenguaje. Se trata de que el código hable el idioma del negocio. Si su dominio es una tienda en línea, en el código debería haber Order, Product, Cart, y no DataTransferObject y EntityManager.

\n\n

Go, con su simplicidad y ausencia de magia, es ideal para DDD. Aquí no hay clases proxy ni reflexión que oculten la esencia. En Go, usted está obligado a ser honesto: si tiene un agregado, es una estructura explícita; si tiene un repositorio, es una interfaz.

\n\n

Los bloques de construcción principales de DDD que veremos son:

\n
    \n
  • Entity (Entidad) — objeto con un identificador único (por ejemplo, User).
  • \n
  • Value Object (Objeto de valor) — objeto inmutable que describe características (por ejemplo, Address).
  • \n
  • Aggregate (Agregado) — clúster de entidades que garantiza la consistencia (por ejemplo, Order con OrderItem).
  • \n
  • Repository (Repositorio) — colección de objetos que oculta los detalles de almacenamiento.
  • \n
  • Domain Service (Servicio de dominio) — operación que no encaja en una sola entidad.
  • \n
\n\n

Ahora, traduzcamos esto a Go.

\n\n

Estructura del proyecto: cómo no perderse en las carpetas

\n\n

La buena noticia: Go no impone ninguna estructura. La mala noticia: sin estructura, se ahogará rápidamente. Para DDD en Go, recomiendo la siguiente organización del código:

\n\n
your-project/\n├── cmd/\n│   └── server/\n│       └── main.go\n├── internal/\n│   ├── domain/          # Núcleo puro: entidades, reglas\n│   │   ├── order.go\n│   │   ├── product.go\n│   │   └── errors.go\n│   ├── application/     # Casos de uso / servicios de la aplicación\n│   │   ├── order_service.go\n│   │   └── product_service.go\n│   └── infrastructure/  # Bases de datos, API externas, manejadores HTTP\n│       ├── postgres/\n│       │   └── order_repository.go\n│       └── http/\n│           └── handler.go\n└── go.mod
\n\n

Tenga en cuenta: domain no importa infrastructure. Esta es la regla de oro de DDD: el dominio no sabe nada sobre bases de datos ni HTTP. Vive en un vacío de estructuras e interfaces puras.

\n\n

Escribiendo el dominio: Order y Value Objects

\n\n

Empecemos por el núcleo. Supongamos que estamos construyendo un sistema de gestión de pedidos. Así es como podría verse la entidad Order:

\n\n
// internal/domain/order.go\npackage domain\n\nimport (\n    "errors"\n    "time"\n)\n\ntype OrderStatus string\n\nconst (\n    OrderStatusPending   OrderStatus = "pending"\n    OrderStatusConfirmed OrderStatus = "confirmed"\n    OrderStatusCancelled OrderStatus = "cancelled"\n)\n\ntype OrderID string\n\ntype Order struct {\n    ID         OrderID\n    CustomerID string\n    Items      []OrderItem\n    Status     OrderStatus\n    CreatedAt  time.Time\n    Upd                

Blogs

Book Recommendations