[{"data":1,"prerenderedAt":76},["ShallowReactive",2],{"profile-pt-BR":3,"articles-pt-BR-{}":27},{"brandName":4,"fullName":5,"headline":6,"manifesto":7,"contactIntro":11,"avatar":12,"manifestoImage":13,"social":14},"Danilo Fernando","Danilo Fernando - Engenheiro de Software","Software bem construído, integrações confiáveis e arquitetura pensada para durar.",[8,9,10],"Minha jornada é guiada pela crença de que código é apenas uma ferramenta para resolver problemas de negócio complexos. Com sólida experiência em ecossistemas Java e Spring, dedico meus esforços a sistemas que não apenas funcionam, mas que são fáceis de manter e evoluir.","Especialista em APIs robustas e integrações críticas, acredito que maturidade técnica se reflete na capacidade de tomar decisões ponderadas, equilibrando inovação com as necessidades reais da organização.","Busco impacto real: Clean Code não é estética, é necessidade econômica para garantir a sustentabilidade do produto a longo prazo.","Estou sempre aberto a novas oportunidades profissionais, troca de experiências técnicas ou discussões sobre arquitetura e desenvolvimento de software.","\u002Fimages\u002Fprofile\u002Fdanilo.webp","\u002Fimages\u002Fprofile\u002Fdanilo_manifesto.webp",[15,19,23],{"kind":16,"label":17,"href":18},"email","E-mail","mailto:danilo.bossanova@hotmail.com",{"kind":20,"label":21,"href":22},"linkedin","LinkedIn","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fdanilo-fernando-dev\u002F",{"kind":24,"label":25,"href":26},"github","GitHub","https:\u002F\u002Fgithub.com\u002Fdanilobossanova",[28,41,52,64],{"slug":29,"title":30,"excerpt":31,"category":32,"tags":33,"readTimeMinutes":37,"publishedAt":38,"author":4,"coverImage":39,"body":40},"outbox-pattern-na-pratica","Outbox pattern na prática com Spring Boot","Como garantir entregas at-least-once sem depender de transações distribuídas.","Arquitetura",[34,35,36],"eventos","spring-boot","kafka",9,"2025-03-01","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Foutbox\u002F1200\u002F600","## O problema\n\nPublicar eventos de forma confiável junto de uma transação de banco é uma das\narmadilhas clássicas de sistemas distribuídos. Se você grava no Postgres e\ndepois publica no Kafka:\n\n```java\n@Transactional\npublic void confirm(Order order) {\n    orderRepository.save(order);       \u002F\u002F ✅ transação do banco\n    kafkaTemplate.send(\"orders\", order); \u002F\u002F ❌ fora da transação\n}\n```\n\nBasta um crash entre as duas chamadas para o banco dizer *\"confirmado\"* e o\nmundo nunca saber.\n\n## Outbox pattern\n\nA ideia é gravar o evento na **mesma transação** do banco, em uma tabela\n`outbox`. Um relay lê a tabela e publica de fato.\n\n### Schema mínimo\n\n```sql\nCREATE TABLE outbox (\n    id           UUID PRIMARY KEY,\n    aggregate    VARCHAR(64)  NOT NULL,\n    event_type   VARCHAR(128) NOT NULL,\n    payload      JSONB        NOT NULL,\n    created_at   TIMESTAMPTZ  NOT NULL DEFAULT now(),\n    published_at TIMESTAMPTZ\n);\nCREATE INDEX outbox_unpublished_idx\n    ON outbox (created_at) WHERE published_at IS NULL;\n```\n\n### Relay\n\nUm job simples lê eventos não publicados, envia ao broker e marca como\npublicado. O importante é:\n\n1. **Idempotência do consumidor** — o relay vai republicar em caso de falha.\n2. **Monitoramento do lag** — alerta se `outbox` crescer mais rápido que\n   consumir.\n3. **Batch controlado** — não trave o DB puxando 10k de uma vez.\n\n### Gotchas\n\n- Nunca dependa de ordem estrita do broker; use `aggregate_id` no particionamento.\n- Não faça *dead-letter* dentro da mesma tabela — crie `outbox_failed`.\n- Sempre grave o schema version do payload.\n\n## Quando evitar\n\nSe o seu sistema não precisa de garantia at-least-once, o outbox é overkill.\nUm `@TransactionalEventListener` do Spring resolve 80% dos casos.",{"slug":42,"title":43,"excerpt":44,"category":32,"tags":45,"readTimeMinutes":48,"publishedAt":49,"author":4,"coverImage":50,"body":51},"custo-real-da-complexidade","O custo real da complexidade desnecessária","Por que over-engineering costuma ser o caminho mais rápido para o fracasso de um projeto.",[46,47],"clean-architecture","decisões-técnicas",5,"2025-02-10","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fcomplexity\u002F1200\u002F600","## Complexidade cobrada com juros compostos\n\nComplexidade é a maior causa de falência técnica que já vi de perto. Cada\nabstração \"por precaução\" é um contrato implícito com o futuro — e o futuro\nsempre cobra a conta.\n\n> \"A única coisa mais cara que resolver o problema errado é resolver o\n> problema certo com três camadas de indireção que ninguém pediu.\"\n\n### Sinais de alerta\n\n- Abstrações que existem para um único caso de uso.\n- Frameworks internos para coisas que o ecossistema já resolve.\n- \"Vamos deixar plugável\" **antes** de existirem dois plugs.\n- Configuração dinâmica para algo que muda uma vez por ano.\n- Camadas de mapeamento entre objetos idênticos.\n\n### Heurística prática\n\nAntes de criar uma abstração, pergunte:\n\n1. Existem **dois** clientes reais hoje?\n2. O custo de extrair depois é proibitivo?\n3. O comportamento realmente varia, ou só o nome?\n\nSe a resposta for \"não\" para as três, **inline é a resposta certa**.\n\n### Um exemplo concreto\n\n```java\n\u002F\u002F Antes — flexibilidade que ninguém pediu\npublic interface UserNotifier {\n    void notify(User user, NotificationPayload payload);\n}\npublic class EmailUserNotifier implements UserNotifier { \u002F* ... *\u002F }\n\n\u002F\u002F Depois — o sistema só manda email, ponto\npublic class EmailService {\n    public void sendWelcome(User user) { \u002F* ... *\u002F }\n}\n```\n\nQuando o segundo canal aparecer, você extrai a interface em **cinco minutos**,\ncom testes verdes e com a cabeça clara sobre o que realmente muda.\n\n### Resumo\n\nComece pela dor real, não pela elegância teórica. Clean Code é sobre **custo\nde manutenção**, não sobre quantidade de interfaces por megabyte.",{"slug":53,"title":54,"excerpt":55,"category":56,"tags":57,"readTimeMinutes":60,"publishedAt":61,"author":4,"coverImage":62,"body":63},"testes-integracao-que-nao-mentem","Testes de integração que não mentem","Estratégias com TestContainers para manter CI\u002FCD rápida sem sacrificar a confiança no código.","Spring Boot",[58,35,59],"testes","testcontainers",8,"2025-01-18","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Ftests\u002F1200\u002F600","## Suites verdes, código frágil\n\nUm suite verde sem confiança é pior do que nenhum suite — ela te dá licença\npra dar deploy enquanto o sistema queima.\n\n### O padrão que funciona\n\n1. **TestContainers** para dependências reais (Postgres, Kafka, Redis).\n2. **Fixtures determinísticos** — nada de `@Sql` + random.\n3. **Um seed por teste**, sem estado compartilhado.\n4. **Assertions em dados**, não em número de chamadas de mock.\n\n```java\n@Testcontainers\n@SpringBootTest\nclass OrderConfirmationIT {\n    @Container\n    static PostgreSQLContainer\u003C?> db = new PostgreSQLContainer\u003C>(\"postgres:16\")\n        .withInitScript(\"db\u002Finit.sql\");\n\n    @DynamicPropertySource\n    static void props(DynamicPropertyRegistry reg) {\n        reg.add(\"spring.datasource.url\", db::getJdbcUrl);\n    }\n}\n```\n\n### O que isso compra\n\n- Testes que **viram verdes junto do código**, não depois.\n- Refactors sem medo.\n- Conversas objetivas em code review.",{"slug":65,"title":66,"excerpt":67,"category":68,"tags":69,"readTimeMinutes":72,"publishedAt":73,"author":4,"coverImage":74,"body":75},"decisoes-tecnicas-peso-do-legado","Decisões técnicas e o peso do legado","Ser senior tem menos a ver com \"como codar\" e mais a ver com \"quando não codar\".","Carreira",[70,71],"carreira","liderança-técnica",6,"2024-12-05","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fcareer\u002F1200\u002F600","## Seniority é contexto\n\nO trabalho muda de *\"resolver o problema certo\"* para *\"escolher qual problema\nresolver\"*. Isso exige pouco sobre como codar e muito sobre **saber dizer não**.\n\n### O peso do legado\n\nCódigo herdado é o custo que você **não pagou** quando o sistema nasceu.\nCada atalho do passado virou uma dívida a juros altos. O trabalho do senior\nnão é reescrever tudo — é escolher *qual pedaço* da dívida merece ser quitado\nneste trimestre.\n\n### O mapa que uso\n\n- **Alta dor + alto risco** → refatoração cirúrgica com testes novos.\n- **Alta dor + baixo risco** → substitui e segue.\n- **Baixa dor + alto risco** → monitora e documenta o perigo.\n- **Baixa dor + baixo risco** → **deixa em paz**.",1776457051148]