[{"data":1,"prerenderedAt":246},["ShallowReactive",2],{"profile-pt-BR":3,"principles-pt-BR":27,"projects-pt-BR":58,"experience-pt-BR":137,"attitudes-pt-BR":187,"articles-pt-BR-{\"limit\":3}":211},{"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,33,38,43,48,53],{"id":29,"title":30,"description":31,"icon":32},"clean-architecture","Arquitetura limpa","Sistemas desacoplados que isolam lógica de negócio de infraestrutura e frameworks.","Layout",{"id":34,"title":35,"description":36,"icon":37},"robust-integrations","Integrações robustas","Conexões entre sistemas focadas em resiliência, falhas e consistência de dados.","Network",{"id":39,"title":40,"description":41,"icon":42},"readable-code","Código legível","Código que prioriza comunicação entre humanos e facilita revisão.","FileText",{"id":44,"title":45,"description":46,"icon":47},"decisions-with-context","Decisões com contexto","Escolhas baseadas em fatos, necessidades do negócio e restrições reais.","Brain",{"id":49,"title":50,"description":51,"icon":52},"clear-communication","Comunicação clara","Tradução de complexidade técnica em linguagem acessível a stakeholders.","MessageSquare",{"id":54,"title":55,"description":56,"icon":57},"continuous-evolution","Evolução contínua","Aprendizado constante aplicado à melhoria técnica e de processos.","TrendingUp",[59,88,113],{"slug":60,"title":61,"summary":62,"tags":63,"context":67,"solution":68,"result":69,"stack":70,"coverImage":75,"publishedAt":76,"metrics":77,"body":87},"motor-liquidacao-tempo-real","Motor de Liquidação em Tempo Real","Processamento de grandes volumes de transações financeiras com latência sub-segundo.",[64,65,66],"Fintech","Scalability","Event-Driven","O sistema existente não sustentava picos de volumetria, gerando filas e conciliações atrasadas.","Arquitetura orientada a eventos com Spring Boot, Kafka e idempotência por chaves naturais.","Redução de 40% no tempo de conciliação e 99,9% de disponibilidade operacional sob carga pesada.",[71,72,73,74],"Java 17","Spring Cloud","Kafka","PostgreSQL","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Ffintech\u002F1200\u002F800","2024-11-03",[78,81,84],{"label":79,"value":80},"Conciliação","-40%",{"label":82,"value":83},"Disponibilidade","99,9%",{"label":85,"value":86},"Throughput","12k tps","## Contexto\nO core de liquidação legado não escalava horizontalmente e acumulava filas durante picos de movimento...\n\n## Decisões técnicas\n- Kafka como backbone de eventos.\n- Outbox pattern para garantias at-least-once.\n- Idempotência por chave natural no consumidor.\n\n## Resultado\nEm três meses, o tempo médio de conciliação caiu 40%, com throughput estável acima de 12k transações por segundo.",{"slug":89,"title":90,"summary":91,"tags":92,"context":95,"solution":96,"result":97,"stack":98,"coverImage":103,"publishedAt":104,"metrics":105,"body":112},"gateway-integracao-multicanal","Gateway de Integração Multicanal","Centralização de marketplaces para estoque e pedidos unificados.",[93,94],"E-commerce","Integration","Cada marketplace possuía particularidades de API, causando retrabalho e inconsistência de estoque.","Camada de abstração com Adapter Pattern e orquestração por filas para desacoplar produtores e consumidores.","Integração de 5 novos parceiros em menos de 1 mês, com zero conflitos de sincronismo de estoque.",[99,100,101,102],"Spring Boot","Redis","Docker","JUnit 5","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fecommerce\u002F1200\u002F800","2024-08-12",[106,109],{"label":107,"value":108},"Parceiros integrados","+5",{"label":110,"value":111},"Tempo por parceiro","\u003C1 mês","## Contexto\nA operação dependia de scripts individuais por marketplace...\n\n## Solução\nUm adapter por canal, cache em Redis e testes de contrato por provider.\n\n## Impacto\nCinco marketplaces novos integrados em menos de um mês, sem inconsistência de estoque.",{"slug":114,"title":115,"summary":116,"tags":117,"context":120,"solution":121,"result":122,"stack":123,"coverImage":127,"publishedAt":128,"metrics":129,"body":136},"modernizacao-core-bancario","Modernização de Core Bancário","Migração controlada de um monólito legado para microserviços.",[118,119],"Legacy Recovery","Clean Arch","Monólito legado de alto acoplamento, deploys demorados e alto índice de incidentes em produção.","Strangler Fig Pattern extraindo domínios gradualmente com Arquitetura Hexagonal.","Melhoria de 60% no tempo de deploy e redução significativa da dívida técnica.",[124,99,125,126],"Java","Oracle","Kubernetes","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fbanking\u002F1200\u002F800","2024-03-22",[130,133],{"label":131,"value":132},"Deploy time","-60%",{"label":134,"value":135},"Incidentes críticos","-45%","## Contexto\nCore bancário monolítico com 10+ anos...\n\n## Estratégia\nStrangler Fig + Hexagonal para isolar domínios.\n\n## Resultado\nDeploys 60% mais rápidos e queda expressiva em incidentes.",[138,150,163,175],{"id":139,"title":140,"items":141},"backend","Backend",[142,145,148],{"name":143,"level":144},"Java (8, 11, 17)","Senior",{"name":146,"level":147},"Spring Boot \u002F Data \u002F Security","Expert",{"name":149,"level":147},"APIs RESTful",{"id":151,"title":152,"items":153},"architecture","Arquitetura e Qualidade",[154,157,160],{"name":155,"level":156},"Clean \u002F Hexagonal","Daily",{"name":158,"level":159},"JUnit \u002F Mockito \u002F TDD","Standard",{"name":161,"level":162},"Microserviços & Eventos","Advanced",{"id":164,"title":165,"items":166},"data-infra","Dados e Infra",[167,170,172],{"name":168,"level":169},"PostgreSQL \u002F Oracle \u002F MySQL","Proficient",{"name":171,"level":162},"Redis \u002F Caching",{"name":173,"level":174},"Docker \u002F K8s \u002F CI-CD","Practitioner",{"id":176,"title":177,"items":178},"frontend-other","Frontend e Outros",[179,182,185],{"name":180,"level":181},"Angular \u002F Vue (TypeScript)","Capable",{"name":183,"level":184},"Cloud (AWS\u002FAzure)","Basics",{"name":186,"level":162},"Kafka \u002F RabbitMQ",[188,192,195,199,203,207],{"id":189,"name":190,"icon":191},"responsibility","Responsabilidade","ShieldCheck",{"id":193,"name":194,"icon":52},"communication","Comunicação",{"id":196,"name":197,"icon":198},"collaboration","Colaboração","Users",{"id":200,"name":201,"icon":202},"discipline","Disciplina","ClipboardList",{"id":204,"name":205,"icon":206},"analytical","Pensamento Analítico","BarChart3",{"id":208,"name":209,"icon":210},"context","Respeito ao Contexto","Scale",[212,225,235],{"slug":213,"title":214,"excerpt":215,"category":216,"tags":217,"readTimeMinutes":221,"publishedAt":222,"author":4,"coverImage":223,"body":224},"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",[218,219,220],"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":226,"title":227,"excerpt":228,"category":216,"tags":229,"readTimeMinutes":231,"publishedAt":232,"author":4,"coverImage":233,"body":234},"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.",[29,230],"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":236,"title":237,"excerpt":238,"category":99,"tags":239,"readTimeMinutes":242,"publishedAt":243,"author":4,"coverImage":244,"body":245},"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.",[240,219,241],"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.",1776457051146]