Playbook

Código DDD: entidad, objeto de valor y agregado (Codigo Ddd Entidad Objeto DE Valor Y Agregado)

¿Cómo funcionan los patrones tácticos DDD? Objeto de valor, entidad, agregado, servicio de dominio, servicio de aplicación y límites del repositorio con un ejemplo de orden real...

DDD: lenguaje empresarial del software

Parte 2 de 4

DDD tactical patterns showing value objects, entities, and aggregate boundaries

Pregunta de este artículo

En la primera parte comenzamos con el lenguaje y las reglas del negocio. Ahora la pregunta es: ¿Dónde guardamos estas decisiones en el código? Usaremos el mismo dominio de comercio electrónico: dinero, línea de pedido, flujo de pedido y pago.```text Money + Address + Quantity → Value Object OrderLine + Order → Entity Order (Root) + OrderLine → Aggregate Repository → Aggregate Root'u yükler ve kaydeder


## Conceptos en la primera mención```text
📦 Value Object
Kimliği olmayan, değeriyle tanımlanan ve değişmez tutulması gereken kavram.

📦 Entity
Nitelikleri değişse de kimliği boyunca aynı kalan nesne.

📦 Aggregate
Birlikte tutarlı kalması gereken nesnelerin transaction sınırı.

📦 Aggregate Root
Aggregate'e dışarıdan girilebilen tek kapı.
```Por ejemplo, dos `Money(100, "TRY")` representan el mismo valor; Dos órdenes tienen identidades diferentes incluso si sus sumas son iguales.

## Comenzar con objeto de valor

Value Object enseña mejor la forma de pensar en DDD. `decimal` no es dinero per se: conlleva reglas de moneda, redondeo, descuento e impuestos. Almacene estas reglas dentro del concepto en lugar de distribuirlas a la capa de servicio.```csharp
public sealed record Money(decimal Amount, string Currency)
{
    public Money Add(Money other)
    {
        if (Currency != other.Currency) throw new DomainException("Currency mismatch");
        return new Money(Amount + other.Amount, Currency);
    }
}
```El objeto de valor es inmutable: cuando el valor cambia, se crea una nueva instancia. Por lo tanto, la misma dirección, correo electrónico, rango de fechas o valor de moneda no produce efectos secundarios inesperados en diferentes pasos de la transacción. La comparación se realiza en función del contexto; Por lo tanto, el costo de igualdad es O(m) con el número de campos, pero el costo de cambio disminuye porque la regla de negocios permanece en un solo lugar.

## Entidad: identidad y ciclo de vida

`Order` es una entidad. Puede cambiar su dirección o total; Sigue siendo el mismo orden. La diferencia no está en utilizar definidores, sino en modelar la transición como comportamiento laboral.```text
❌ order.Status = Paid
✓ order.ConfirmPayment(payment)

❌ order.Total = total - discount
✓ order.ApplyDiscount(discount)
````ConfirmPayment` verifica en un solo lugar como comprobante de pago, que el pedido no ha sido cancelado y que la transición es legal. La tarea de la entidad no es mover todos los datos, sino prevenir situaciones no válidas en su ciclo de vida.

## Agregado: no un grupo de objetos, sino un límite de coherencia

El pedido y sus líneas deben permanecer consistentes dentro de la misma transacción: el número de líneas es positivo, el total es igual a la suma de las líneas y la línea no se puede cambiar una vez confirmado el pedido. Entonces `Order` se convierte en raíz agregada para `OrderLine`.```text
Order aggregate
  ├─ OrderLine
  ├─ ShippingAddress
  └─ Total

Dış dünya → Order.AddLine() / Order.ConfirmPayment()
Dış dünya ↛ OrderLine'a doğrudan yazmaz
```Hacer que Aggregate sea grande produce bloqueos y conflictos de versión, no seguridad. Actualice el agregado más único posible en la solicitud de escritura. Conéctese a otro Agregado por ID en lugar de por referencia de objeto; Si se requiere coordinación, utilice eventos de dominio o orquestación de aplicaciones. Esto limita los conflictos de simultaneidad positivos y los costos de instalación innecesarios.

## Servicio de dominio y servicio de aplicaciones

Si una regla no pertenece naturalmente a un único Agregado, puede ser un Servicio de Dominio: por ejemplo, fijación de precios basada en el tipo de cambio. Por el contrario, el Servicio de Aplicación gestiona el caso de uso: carga el pedido, llama al comportamiento, lo guarda y completa la transacción.

| Capa | Responsabilidad |
| --- | --- |
| Objeto de valor/Entidad/Agregado | Mantenimiento de reglas de negocio e invariantes |
| Servicio de dominio | Cuenta de dominio puro que no pertenece a Aggregate |
| Servicio de aplicaciones | Orquestación de casos de uso, transacciones y llamadas de adaptadores |

Poner reglas en el servicio de aplicaciones es un regreso del modelo anémico a la capa de servicio.

## Repositorio: no API de tabla

El repositorio le da al dominio la sensación de una colección en memoria; No es un detalle de SQL u ORM. En lugar de crear un repositorio para cada tabla, utilícelo solo para Aggregate Roots. Reemplazar directamente la entidad secundaria con `OrderLineRepository.Find()` omite las reglas que mantiene Root.```text
order = orderRepository.get(orderId)
order.confirmPayment(payment)
orderRepository.save(order)
```Este límite también permite la verificación independiente de la infraestructura del comportamiento del dominio con un repositorio simulado en pruebas. El constructor vacío de ORM o el requisito de carga ansiosa no deberían dar forma al modelo de dominio; El mapeo es responsabilidad del adaptador.

## Coincidencias que crean falsa confianza```text
❌ Value Object = küçük DTO
✓ Value Object değer, doğrulama ve davranış taşır.

❌ Aggregate = mümkün olduğunca büyük nesne grafiği
✓ Aggregate = küçük tutulmuş transaction ve consistency boundary.

❌ Domain Service = iş kuralı çöplüğü
✓ Yalnızca tek Aggregate'e ait olmayan saf domain davranışı.

❌ Repository = her tablo için CRUD API
✓ Repository = Aggregate Root'un kalıcılık sınırı.

Lista de verificación de solicitud

  1. ¿Están circulando como primitivos conceptos como Money, Email, Address, Quantity?
  2. ¿Cada comportamiento de la Entidad realmente previene un estado no válido?
  3. ¿Una solicitud de escritura intenta actualizar atómicamente varios agregados?
  4. ¿El Servicio de Aplicación toma decisiones o simplemente organiza?
  5. ¿El Repositorio sólo instala Aggregate Roots?

Comience primero con la regla comercial más cara; No convierta todo el sistema en DDD táctico a la vez.

Lo que debes recordar de este artículo

El objeto de valor lleva el valor y las reglas del concepto. La entidad mantiene la identidad y el ciclo de vida. Aggregate establece un pequeño límite de transacciones para mantener la coherencia. El repositorio reúne este límite con la permanencia.

El objetivo del DDD táctico no es agregar más clases, sino evitar que la regla de negocio se filtre a la capa equivocada.

En la siguiente sección examinaremos cómo hablar de estos límites en el sistema más grande: contexto acotado, mapeo de contexto y descomposición dentro del monolito.

FAQ

Frequently asked questions

¿Qué es el objeto de valor?

Un concepto que no tiene identidad, se define por su valor y debe mantenerse constante.

¿Qué es la entidad?

Un objeto que permanece igual en toda su identidad aunque sus cualidades cambien.

¿Es correcto "Objeto de valor = DTO pequeño"?

El objeto de valor conlleva valor, validación y comportamiento.

¿Qué soluciona esta sección?

En la primera parte comenzamos con el lenguaje y las reglas del negocio. Ahora la pregunta es: ¿Dónde guardamos estas decisiones en el código? Usaremos el mismo dominio de comercio electrónico: dinero, línea de pedido, flujo de pedido y pago. En la primera parte comenzamos con el lenguaje y las reglas del negocio. Ahora la pregunta es: ¿Dónde guardamos estas decisiones en el código? Usaremos el mismo dominio de comercio electrónico: dinero, línea de pedido, flujo de pedido y pago.

Principios de ingeniería aprendidos

  • Value Object combina datos primitivos con semántica empresarial y validación.
  • El agregado debe ser pequeño y tener un límite de consistencia claro.
  • El Servicio de Aplicaciones gestiona el proceso; el comportamiento del dominio decide.

Continuar leyendo

Continuar leyendo

Siguiente en la serie

Siguiente en la serie

Misma serie

Paylaş