Tema: architecture
-
Pipeline, fan-out, orquestador y panel de críticos: qué patrón multiagente conviene a cada tarea
Un pipeline conviene a tareas con una secuencia fija de transformaciones; el fan-out paralelo conviene a subpreguntas independientes o a intentos repetidos sobre los que votar; un orquestador con trabajadores conviene a tareas cuya descomposición solo se conoce en tiempo de ejecución; un panel de críticos conviene a resultados que necesitan revisión frente a varios criterios; cada uno multiplica el costo en tokens y añade una capa de coordinación que puede fallar por sí misma.
-
DACI y RACI para decisiones técnicas: una persona que aprueba, contribuyentes nombrados
DACI nombra a quien impulsa (driver) la decisión, a una única persona que aprueba y la toma, a contribuyentes que tienen voz pero no voto, y a partes informadas que conocen el resultado; RACI asigna roles de responsable, quien rinde cuentas, consultado e informado a las tareas. Cualquiera de los dos funciona para decisiones técnicas cuando los roles se escriben antes de que empiece la discusión.
-
Convenciones de inyección de dependencias en .NET: tiempos de vida, ámbitos y la trampa de la dependencia cautiva
Microsoft.Extensions.DependencyInjection registra servicios en un IServiceCollection con tiempo de vida transient, scoped o singleton, y los inyecta mediante constructores públicos; las reglas documentadas son nunca inyectar un servicio scoped en un singleton, dejar que el contenedor libere lo que creó, evitar llamadas de tipo localizador de servicios, y validar los ámbitos para que las dependencias cautivas fallen al arrancar en lugar de filtrar estado entre solicitudes.
-
Event sourcing y CQRS: qué se gana y qué cuesta
Event sourcing almacena cada cambio de estado como un evento inmutable y obtiene el estado actual reproduciéndolos; CQRS separa el modelo de escritura de los modelos de lectura. Ambos añaden capacidad de auditoría y flexibilidad al precio de mayor complejidad y de consistencia eventual.
-
Elegir Go o Rust para un nuevo servicio: un procedimiento de decisión sin benchmarks
Decidir entre Go y Rust para un servicio a partir de propiedades documentadas de cada lenguaje y de las limitaciones del equipo, en lugar de a partir del folclore de los benchmarks: el modelo de gestión de memoria, el estilo de manejo de errores y de concurrencia, la forma de la carga de trabajo, las bibliotecas con las que el servicio debe comunicarse, y quién lo mantendrá dentro de dos años.
-
La deuda técnica como decisión consciente con contabilidad
La metáfora de Cunningham: el código que no es del todo correcto es un crédito, y cada minuto de trabajo extra que exige es el interés. La metáfora solo funciona si la deuda se contrae de forma consciente, se anota y se evalúa con regularidad; como término genérico para todo lo que resulta feo, o como excusa para el descuido, carece de valor.
-
Elegir una herramienta o skill con un modelo de decisión: Choice para ordenar, Noul para abstenerse
Por qué un Choice sobre las herramientas candidatas responde a una pregunta relativa (cuál candidato encaja mejor) mientras que un Noul por candidato responde a una pregunta absoluta (si este turno necesita una herramienta en absoluto), y cómo el cookbook de sugerencia de skills de TypeSafe combina ambos sobre un catálogo de 182 skills: una solicitud las ordena todas, una segunda lee las tres mejores y puede rechazarlas todas.
-
Recorrido por un servicio de carga de archivos: tickets directos al almacenamiento, escaneo asíncrono y cuotas
Un recorrido de diseño para cargas que evitan los servidores de aplicación: un ticket que reserva cuota y devuelve una URL de carga firmada, un paso de finalización que verifica el objeto almacenado, un worker de escaneo que lo promueve o lo elimina, reglas de ciclo de vida para las cargas abandonadas, y un modelo de estado que explica cada objeto almacenado.
-
Recorrido por un servicio de notificaciones: canales, preferencias, intentos de entrega y reintentos
Un recorrido de diseño para un servicio de notificaciones multicanal: una API de ingesta con clave de idempotencia, un enrutador que expande una notificación en entregas por canal tras comprobar las preferencias, colas y calendarios de reintento por canal, manejo de callbacks para tokens inválidos, y qué dejar para después.
-
Almacenar datos derivados en PostgreSQL: columnas generadas frente a vistas materializadas
Una columna generada deriva un valor por fila a partir únicamente de esa fila, ya sea de forma virtual (calculada en la lectura) o almacenada (calculada en la escritura), y solo puede usar expresiones inmutables; una vista materializada almacena el resultado de cualquier consulta y está tan actualizada como su último REFRESH. Conviene usar columnas generadas almacenadas para la normalización por fila que deba indexarse, vistas materializadas para agregados costosos que puedan quedar desactualizados, y una tabla de resumen mantenida al día cuando ninguna de las dos encaja.
-
Diseño de la memoria de un agente: qué conservar, qué resumir y qué olvidar
La memoria de un agente tiene tres niveles: la ventana de contexto, un cuaderno de tareas y un almacén duradero entre sesiones; decidir por elemento a qué nivel pertenece, mantener la memoria duradera pequeña y revisable, y eliminar lo que ya no es cierto.
-
Eventos enviados por el servidor frente a WebSockets
Los eventos enviados por el servidor transmiten eventos de texto del servidor al cliente sobre HTTP normal, con reconexión automática e identificadores de último evento; los WebSockets ofrecen un canal bidireccional con capacidad binaria y protocolo propio. Elegir SSE para actualizaciones en un solo sentido y WebSockets cuando el cliente debe enviar con frecuencia.
-
Abstenerse como agente: cuándo no actuar es la salida correcta
El espacio de salidas de un agente debería incluir un «no decidido» deliberado para cada acción automatizada: qué es la abstención, por qué un clasificador o un agente que carece de ella convierte todos los casos poco claros en una acción errónea, y cómo incorporar la abstención mediante opciones explícitas, umbrales mínimos de confianza, límites dependientes de lo que está en juego y una vía para aquello de lo que se ha abstenido.
-
¿Cuándo sigue mereciendo la pena el enrutamiento en el cliente ahora que los navegadores ofrecen bfcache, prerenderizado y transiciones de vista entre documentos?
Pregunta abierta: los enrutadores en página se adoptaron para evitar las cargas completas de página, a costa de servir un shell, gestionar los 404, restaurar el desplazamiento y el foco, y un paquete que debe llegar primero; la caché de retroceso/avance, la API Speculation Rules y las transiciones de vista entre documentos abordan ahora las motivaciones originales en los sitios de varias páginas. ¿Para qué sitios y qué patrones de interacción sigue ganando de forma mensurable un enrutador en página?
-
¿A partir de qué tamaño de repositorio necesitan los equipos herramientas de compilación para monorepos más allá de Git puro?
Pregunta abierta: el sparse checkout, el clon parcial y los filtros de CI por directorio cubren la primera etapa de un repositorio único en crecimiento; ¿a partir de qué tamaño, número de equipos o tiempo de compilación han comprobado los equipos que se volvía necesaria una herramienta de grafo de compilación con caché remota, y cuánto costó la transición?
-
Elegir entre hilos, procesos y asyncio para una carga de trabajo en Python
Clasificar primero la ruta crítica: la espera de E/S se ajusta a asyncio (muchas conexiones, bibliotecas asíncronas) o a un pool de hilos (pocas llamadas bloqueantes); el trabajo de CPU en Python puro necesita procesos o una compilación sin GIL (free-threaded); el código nativo que libera el GIL puede usar hilos. Acotar cada pool, elegir explícitamente el método de arranque de los procesos y escribir la ruta de apagado.
-
Recorrido por un acortador de URL: generación de claves, estado de redirección y controles contra abusos
Un recorrido de diseño para un acortador de URL: claves aleatorias en base62 con reintento ante colisiones, una ruta de redirección que toca una sola caché y un único almacén, 302 en lugar de 301 cuando los destinos deben seguir siendo revocables y contables, comprobaciones contra abusos en la creación, y una lista de lo que no conviene construir primero.
-
Registros de decisiones de arquitectura
Un registro de decisión de arquitectura recoge una decisión significativa con su contexto, la decisión en sí, su estado y sus consecuencias, en un archivo breve conservado junto con el código.
-
Caché en aplicaciones: tiempos de expiración, invalidación y protección frente a la avalancha
Una caché de aplicación contiene datos derivados y puede perderse en cualquier momento; solo permanece correcta mediante una invalidación deliberada: tiempo de expiración por clase de dato, borrado en lugar de sobrescritura al escribir, identificador de versión en la clave y un bloqueo contra la recarga simultánea de claves activas.
-
ETL frente a ELT: dónde se ejecuta la transformación y qué cambia con ello
ETL transforma los datos en un motor independiente antes de cargarlos en el destino; ELT carga primero los datos en bruto y los transforma con el propio procesamiento del almacén de destino. La elección determina dónde se paga el cómputo, qué datos en bruto llegan al almacén, y con qué facilidad puede volver a ejecutarse una transformación.
Legible por máquina: JSON