GUIA ATIVO
IA · PERSONALIZADO

System Design — Desafio Técnico

Pessoa Desenvolvedora Android Sênior | GOK Inovação Digital


O Cenário

Você acaba de assumir como Android Sênior em um projeto da GOK para um cliente do segmento financeiro: uma fintech de médio porte que processa pagamentos via Pix, boleto e cartão.

O app atual tem ~800 mil usuários ativos mensais, foi construído há 4 anos com arquitetura monolítica, navegação baseada em Activities, callbacks aninhados e sem separação de camadas. O time anterior saiu. Você precisa propor a arquitetura do app reescrito — com uma restrição crítica:

Atenção: O app não pode parar. Releases continuam acontecendo a cada duas semanas enquanto a refatoração ocorre.

O backend já foi modernizado: existe um BFF (Backend for Frontend) dedicado ao mobile, um API Gateway com rate limiting e circuit breaker, e microsserviços independentes para pagamentos, autenticação e notificações.

O entrevistador abre com a seguinte pergunta:

“Me descreve como você arquitetaria esse app do zero — considerando que ele precisa continuar evoluindo em paralelo com a refatoração, que opera em ambiente financeiro crítico e que o time é pequeno.”


Requisitos do Sistema

Funcionais

Não Funcionais

Dimensão Requisito
Disponibilidade Tolerância zero a crash em fluxos de pagamento
Performance Telas de pagamento devem renderizar em menos de 300ms após navegação
Segurança Tokens OAuth2 não podem ser armazenados em SharedPreferences plano; proteção contra repackaging e hooking
Escalabilidade Arquitetura que permita múltiplos devs trabalhando em features paralelas sem conflito
Testabilidade Cobertura mínima de 70% nas camadas de domínio e dados
Observabilidade Crashes e erros de transação rastreáveis com contexto suficiente para reprodução

Os Desafios Ocultos

Estes são os pontos que o entrevistador não menciona explicitamente, mas espera que um candidato sênior levante por conta própria. Não espere ser perguntado — antecipe.


1. Migração incremental sem feature freeze

A reescrita não pode ser do tipo big bang. É necessário propor uma estratégia de convivência entre código legado e código novo.

A abordagem recomendada é o padrão Strangler Fig aplicado ao mobile: módulos novos convivem com telas antigas até que a migração esteja completa, feature por feature.

Dica estratégica: Se você não levantar esse ponto, o entrevistador vai perguntar diretamente: “Como você garante que o app funcione durante a transição?” Sair na frente demonstra senioridade.


2. Consistência de estado em fluxos de pagamento

O QR Code dinâmico do Pix tem janela de expiração. O estado da transação no cliente precisa ser gerenciado em pelo menos três cenários críticos:

Erro comum: Tratar o timeout como falha definitiva. Em ambiente financeiro, um timeout ambíguo exige estado pendente, não erro.


3. Segurança do token e superfície de ataque

EncryptedSharedPreferences é a camada mínima aceitável — não o teto. Em dispositivos rooteados, essa proteção é insuficiente.

A abordagem correta envolve:

Dica estratégica: Segurança mobile é feita em camadas. Não existe proteção absoluta no dispositivo — o objetivo é elevar o custo do ataque.


4. Custo real da modularização em time pequeno

Modularização não é bala de prata. Ela traz overhead concreto: tempo de build, complexidade de navegação entre módulos e convenções que precisam ser mantidas.

Em um time pequeno com pressão de entrega, defender modularização completa desde o primeiro dia sem reconhecer esse custo é um sinal de imaturidade técnica.

Dica estratégica: Proponha modularização incremental — comece com 2 a 3 módulos core e expanda conforme o time e o produto amadurecem.


5. Modo offline e consistência de dados

“Modo offline parcial” parece simples, mas esconde uma decisão arquitetural relevante: quando o cache local e o servidor divergem após a reconexão, qual é a fonte da verdade?

A abordagem correta para dados financeiros:


6. Observabilidade além do Crashlytics

O Crashlytics captura crashes. Mas o que captura os erros silenciosos?

Dica estratégica: Pense em logging estruturado de eventos de negócio, não apenas em crash analytics. Em ambiente financeiro, o que não foi logado pode não ser auditável.


As Perguntas do Entrevistador

As perguntas seguem uma progressão intencional: começam amplas, afunilam em trade-offs e terminam em cenários de pressão.


Abertura

“Por onde você começaria? Me descreve a arquitetura em alto nível antes de entrar nos detalhes.”

O que está sendo avaliado: Capacidade de estruturar o raciocínio antes de codar e clareza de comunicação técnica.


Aprofundamento arquitetural

“Você escolheu Clean Architecture com MVI. Por que MVI e não MVVM nesse contexto específico? Quais são os trade-offs reais dessa decisão para o time?”

O que se espera: Ir além de “MVI é unidirecional”. Mencionar previsibilidade de estado em fluxos de pagamento, rastreabilidade de UI states para debug — e reconhecer o custo adicional de boilerplate em features simples.


Modularização

“Como você estruturaria os módulos? Como gerenciaria dependências compartilhadas — autenticação, tema, componentes de UI?”

O que se espera: Distinção entre feature modules, core modules e app module. Estratégia de navegação via contratos de interface ou navigation graph compartilhado. Reconhecimento do custo de configuração Gradle.


Cenário de falha

“O usuário confirmou um Pix. O app enviou a requisição para o BFF. A rede caiu antes da resposta chegar. O usuário reabre o app 30 segundos depois. O que acontece?”

O que se espera: Não existe resposta única correta — o entrevistador quer ver o raciocínio. Espera-se menção a:


Segurança

“Onde você armazenaria o access token e o refresh token? E se o device estiver rooteado?”

O que se espera: Keystore para derivação de chave, EncryptedSharedPreferences para armazenamento, detecção de root como camada adicional — e a clareza de que segurança mobile é um conjunto de camadas, não uma solução absoluta.


Migração incremental

“O app atual está em produção com 800 mil usuários. Como você refatora sem parar os releases?”

O que se espera: Strangler Fig pattern, feature branches por módulo, testes como rede de segurança para a migração e feature flags para ativação gradual das novas implementações.


Testabilidade

“Como você garante testabilidade em uma Clean Architecture com MVI? Me dá um exemplo concreto de como testaria o fluxo de confirmação de pagamento.”

O que se espera:


Pressão e ambiguidade

“O PM quer lançar o novo fluxo de Pix em 3 semanas. A arquitetura nova ainda não está pronta. O que você faz?”

O que se espera: Maturidade, não perfeição. O candidato não cede à pressão sem análise. Propõe alternativas concretas — feature flag no legado, escopo reduzido, débito técnico explícito — e comunica riscos com clareza para o PM.

Dica estratégica: Nessa pergunta, demonstrar que você não vai simplesmente dizer sim vale mais do que qualquer resposta técnica elaborada.


Trade-offs que Você Deve Levantar por Iniciativa Própria

Atenção: Um candidato sênior não espera ser perguntado sobre trade-offs. Ele os articula espontaneamente como parte do raciocínio arquitetural.

Decisão Trade-off a articular
Clean Architecture Mais testabilidade e flexibilidade, mas mais arquivos, mais boilerplate e curva de onboarding maior. Em times pequenos, pode gerar overhead real.
MVI vs MVVM MVI oferece rastreabilidade de estado superior para fluxos complexos, mas tem mais boilerplate em telas simples. Para um app misto, pode ser válido usar MVI seletivamente nos fluxos financeiros e MVVM nas demais telas.
Modularização completa vs incremental Modularização total reduz acoplamento e paraleliza o desenvolvimento, mas tem custo alto de configuração Gradle. Em time pequeno com pressão de entrega, começar com 2 a 3 módulos core é mais realista.
Offline-first vs online-first Offline-first melhora resiliência, mas para dados financeiros pode comunicar informações desatualizadas como verdade — um risco de UX e confiança. A abordagem correta: offline para leitura com indicador de staleness, online obrigatório para escrita.
Feature modules vs módulos por camada Feature modules isolam contextos de negócio. Módulos por camada são mais simples, mas criam acoplamento entre features. Para a GOK com time pequeno, feature modules com core compartilhado é o equilíbrio mais defensável.
EncryptedSharedPreferences vs Keystore direto EncryptedSharedPreferences é uma abstração conveniente, mas insuficiente em dispositivos comprometidos. A chave deve ser derivada pelo Keystore, com proteções adicionais como camadas complementares.
StateFlow vs LiveData StateFlow não está vinculado ao ciclo de vida do Android nativamente — exige repeatOnLifecycle para coleta segura. LiveData é mais simples, mas menos expressivo para estados complexos e não funciona bem com Compose. A escolha por StateFlow é a correta, mas o custo de gerenciamento de ciclo de vida precisa ser compreendido.
Strangler Fig vs Big Bang rewrite Big Bang garante consistência arquitetural, mas congela features por meses — inaceitável para 800 mil usuários em produção. Strangler Fig tem complexidade temporária e risco de inconsistência, mas é o único caminho viável. O candidato deve definir também o critério de “módulo pronto para migrar”.

Sinal de maturidade técnica: O candidato que espontaneamente diz “essa abordagem tem custo X, e em um time pequeno isso importa” demonstra que pensa em engenharia de produto — não apenas em engenharia de software. Esse é exatamente o perfil que separa um sênior executor de um sênior de referência.