🧪 Problem-Driven Systems Lab

🔵 Caso 07 — .NET 8#

⬅️ Caso 07 · ⚖️ Comparativa de los 7 stacks · 🔵 Perfil de .NET · 🧬 Todos los perfiles

Stack .NET operativo del caso 07. Strangler con routing por consumer + ACL como Func<Request,Response> registrado en runtime.

Primitivas .NET nativas#

PrimitivaRol
ConcurrentDictionary<string, Func<Request,Response>>Tabla de routing mutable en runtime. Registrar nuevo modulo = 1 linea, sin reload del proceso.
Func<Request, Response> delegateACL como closure que filtra contrato — la firma del delegate es el contrato.
record Request/ResponseInmutables, audit-friendly, sin boilerplate.
Interlocked.IncrementContadores lock-free de calls / migrations.

Contraste#

Legacy — cambio toca shared_schema, blast radius alto:

csharp
// todos los consumers pegan al mismo monolito
int blastRadius = 4;   // 4 modulos afectados al unisono
int risk = 8;

Strangler — routing table consulta primero si hay handler nuevo:

csharp
if (routingTable.TryGetValue($"{consumer}:{op}", out var handler))
    return handler(req);   // routedTo=new-module
// fallback al monolito con ACL acotada al consumer

Rutas#

RutaQue muestra
/healthliveness
/change-legacy?consumer=billing&op=changeblast_radius=4 — afecta todo el monolito
/change-strangler?consumer=billing&op=changerouted_to=new-billing-svc — monolito intocado
/flowsmigration_progress por consumer + routing_table_size
/diagnostics/summarycontraste legacy vs strangler
/reset-labreinicia contadores

Hub#

docker compose -f compose.dotnet.yml up -d --build
curl "http://127.0.0.1:8500/07/change-strangler?consumer=billing&op=change"

Modo aislado#

docker compose -f cases/07-incremental-monolith-modernization/dotnet/compose.yml up -d --build
curl "http://127.0.0.1:857/change-strangler?consumer=billing&op=change"

Por que Func<T,R> y no interface IHandler#

Una interfaz requiere clase + ctor + registro. Un Func<Request,Response> es la firma minima: el delegate es el contrato. Registrar un modulo nuevo en ConcurrentDictionary<string, Func<Request,Response>> es una linea — equivalente exacto del ConcurrentHashMap<String, Function<Request,Response>> de Java. Si el modulo crece a tener estado, basta capturar variables en el closure o pasar a una clase implementando IHandler — pero hasta entonces, la firma minima gana.

Ver esta carpeta en GitHub ↗