Tema: architecture
-
Pipeline, fan-out, orquestrador e painel de críticos: qual padrão multiagente serve para qual tarefa
Um pipeline serve para tarefas com sequência fixa de transformações; o fan-out paralelo, para subquestões independentes ou tentativas repetidas sobre as quais votar; o orquestrador com workers, para tarefas cuja decomposição só se conhece em tempo de execução; o painel de críticos, para saídas que exigem revisão segundo vários critérios. Todos multiplicam o custo em tokens e acrescentam uma camada de coordenação que pode falhar por conta própria.
-
DACI e RACI para decisões técnicas: um único aprovador e contribuidores definidos
O DACI define um driver que conduz a decisão, um único aprovador que a toma, contribuidores que têm voz mas não voto e informados que recebem o resultado; o RACI atribui a tarefas os papéis de responsável, aprovador final (accountable), consultado e informado. Ambos funcionam para decisões técnicas, desde que os papéis sejam registrados antes de a discussão começar.
-
Convenções de injeção de dependência no .NET: tempos de vida, escopos e a armadilha da dependência capturada
O Microsoft.Extensions.DependencyInjection registra serviços em um IServiceCollection com tempo de vida transient, scoped ou singleton e os injeta por construtores públicos. As regras documentadas: nunca injetar um serviço scoped em um singleton, deixar o contêiner descartar o que ele criou, evitar chamadas de service locator e validar os escopos para que dependências capturadas falhem na inicialização em vez de vazarem estado entre requisições.
-
Event sourcing e CQRS: o que oferecem e quanto custam
O event sourcing guarda cada mudança de estado como um evento imutável e obtém o estado atual por reprodução (replay); o CQRS separa o modelo de escrita dos modelos de leitura. Ambos trazem auditabilidade e flexibilidade, ao preço de mais complexidade e de consistência eventual.
-
Escolher entre Go e Rust para um novo serviço: um procedimento de decisão sem benchmarks
Como decidir entre Go e Rust para um serviço com base nas propriedades documentadas das linguagens e nas restrições da equipe, e não em folclore de benchmarks: modelo de gerenciamento de memória, estilo de erros e concorrência, perfil da carga, bibliotecas com as quais o serviço precisa se comunicar e quem fará a manutenção daqui a dois anos.
-
Dívida técnica como decisão consciente, com registro contábil
A metáfora de Cunningham trata código ainda não totalmente correto como um empréstimo, e cada minuto de trabalho extra nele é o juro. Só funciona se a dívida for assumida de forma consciente, registrada e reavaliada com regularidade; como rótulo para tudo o que é feio ou como desculpa para desleixo, não vale nada.
-
Selecionar uma ferramenta ou skill com um modelo de decisão: Choice para ordenar, Noul para se abster
Por que um Choice sobre ferramentas candidatas responde a uma pergunta relativa (qual candidata serve melhor), enquanto um Noul por candidata responde a uma pergunta absoluta (este turno precisa mesmo de uma ferramenta), e como o cookbook de sugestão de skills da TypeSafe combina os dois sobre um catálogo de 182 skills: um pedido ordena todas, e um segundo lê as três primeiras e pode rejeitá-las todas.
-
Passo a passo de um serviço de upload de arquivos: tickets de envio direto ao storage, varredura assíncrona e cotas
Um passo a passo de design para uploads que não passam pelos servidores de aplicação: um ticket que reserva cota e devolve uma URL assinada de envio, uma etapa de conclusão que verifica o objeto armazenado, um worker de varredura que o promove ou o apaga, regras de ciclo de vida para uploads abandonados e um modelo de status que explica cada objeto armazenado.
-
Passo a passo de um serviço de notificações: canais, preferências, tentativas de entrega e retentativas
Roteiro de projeto para um serviço de notificações multicanal: API de ingestão com chave de idempotência, roteador que expande cada notificação em entregas por canal após verificar as preferências, filas e políticas de retentativa por canal, tratamento de callbacks para tokens inválidos e o que deixar para depois.
-
Armazenar dados derivados no PostgreSQL: colunas geradas ou views materializadas
Uma coluna gerada deriva um valor por linha apenas a partir dessa mesma linha, podendo ser virtual (calculada na leitura) ou armazenada (calculada na escrita), e aceita só expressões imutáveis; uma view materializada guarda o resultado de qualquer consulta e só está tão atualizada quanto o último REFRESH. Use colunas geradas armazenadas para normalização por linha que deva ser indexada, views materializadas para agregações caras que podem ficar defasadas e uma tabela de resumo mantida quando nenhuma das duas serve.
-
Design de memória para agentes: o que persistir, o que resumir e o que esquecer
A memória de um agente tem três camadas: a janela de contexto, um scratchpad da tarefa e um armazenamento durável entre sessões. Decida para cada item a camada a que ele pertence, mantenha a memória durável pequena e revisável e apague o que deixou de ser verdade.
-
Server-sent events versus WebSockets
Server-sent events stream text events from server to client over plain HTTP with automatic reconnection and last-event IDs; WebSockets provide a bidirectional binary-capable channel with its own protocol. Choose SSE for one-way updates and WebSockets when the client must send frequently.
-
Abster-se como agente: quando não agir é a saída correta
O espaço de saída de um agente deve incluir um deliberado "não decidido" para cada ação automatizada: o que é a abstenção, por que um classificador ou agente sem ela converte todo caso incerto em ação errada e como incorporá-la com opções explícitas, limites mínimos de confiança, limiares conforme o risco e um destino para os casos abstidos.
-
Quando o roteamento no cliente ainda compensa, agora que os navegadores oferecem bfcache, prerendering e view transitions entre documentos?
Pergunta em aberto: os roteadores in-page foram adotados para evitar carregamentos completos de página, ao custo de servir o shell, tratar 404, restaurar scroll e foco e depender de um bundle que precisa chegar primeiro; o back/forward cache, a Speculation Rules API e as view transitions entre documentos já atendem às motivações originais em sites multipágina. Em quais sites e padrões de interação um roteador in-page ainda leva vantagem mensurável?
-
A partir de que tamanho de repositório as equipes precisam de ferramentas de build para monorepo além do Git puro?
Pergunta em aberto: sparse checkout, partial clone e filtros de CI por diretório cobrem a primeira fase de um repositório único em crescimento; a partir de que tamanho, número de equipes ou tempo de build as equipes concluíram que uma ferramenta de grafo de build com cache remoto se tornou necessária, e quanto custou a transição?
-
Como escolher entre threads, processos e asyncio para uma carga de trabalho em Python
Classifique primeiro o caminho crítico: espera por I/O combina com asyncio (muitas conexões, bibliotecas assíncronas) ou com um pool de threads (poucas chamadas bloqueantes); trabalho de CPU em Python puro exige processos ou um build free-threaded; código nativo que libera a GIL pode usar threads. Limite todos os pools, escolha explicitamente o método de início de processos e escreva o caminho de encerramento.
-
Passo a passo de um encurtador de URLs: geração de chaves, status de redirecionamento e controles contra abuso
Um roteiro de projeto para um encurtador de URLs: chaves aleatórias em base62 com nova tentativa em caso de colisão, um caminho de redirecionamento que usa um cache e um armazenamento, 302 em vez de 301 quando os destinos precisam ser revogáveis e contabilizáveis, verificações de abuso na criação e uma lista do que não construir primeiro.
-
Registros de decisão de arquitetura
Um registro de decisão de arquitetura documenta uma decisão significativa com seu contexto, a decisão em si, seu status e suas consequências, em um arquivo curto mantido junto ao código.
-
Cache em aplicações: tempo de expiração, invalidação e proteção contra o efeito manada
Um cache de aplicação guarda dados derivados e pode ser perdido a qualquer momento; só se mantém correto com invalidação deliberada: expiração por classe de dados, remoção em vez de sobrescrita ao escrever, versão na chave e um bloqueio contra o recarregamento simultâneo de chaves muito acessadas.
-
ETL versus ELT: onde a transformação é executada e o que isso muda
No ETL, os dados são transformados em um motor separado antes de serem carregados no destino; no ELT, os dados brutos são carregados primeiro e transformados com o processamento do próprio armazenamento de destino. A escolha define onde se paga pela computação, quais dados brutos chegam ao data warehouse e com que facilidade uma transformação pode ser reexecutada.
Legível por máquina: JSON