← Back to list

Desbloqueando a Busca do PicPay

Modularização por Feature e Clean Architecture na Prática

Jonathan Giorgi Silveira in Inside PicPay · 2025-11-05 14:30 · 7 claps · 4.6 min read
#modularization #clean-architecture #android #tech #picpay
Open on Medium ↗
Wiki topics: 🏛️ · Architecture

Desbloqueando a Busca do PicPay: Modularização por Feature e Clean Architecture na Prática

A evolução contínua de um aplicativo na escala do PicPay esbarra em desafios como o acoplamento excessivo e a complexidade arquitetônica, que tornam a manutenção lenta e arriscada.

A feature de Busca é um exemplo prático desses problemas, com uma arquitetura por camadas que dificulta a agilidade dos times.

Este artigo propõe uma solução baseada em Modularização por Feature e Clean Architecture para destravar o desenvolvimento da Busca. Analisamos os pontos de atrito atuais e detalhamos como a nova abordagem cria uma base mais escalável, sustentável e com baixo acoplamento.

Conceitos-Chave para a Proposta

Para entender a solução, é essencial revisar os pilares arquiteturais que a sustentam:

  • Modularização por Feature: Organiza o código em módulos isolados por funcionalidade (Busca, Perfil, Pagamentos), garantindo que mudanças em uma “caixa” não afetem as outras. Isso acelera o desenvolvimento e o tempo de build.
  • Clean Architecture (Arquitetura Limpa): Uma filosofia que visa proteger as regras de negócio centrais do sistema de detalhes técnicos periféricos (como banco de dados ou UI). O core do sistema se torna independente e altamente testável.
  • Acoplamento: O nível de dependência entre as partes do código. O alto acoplamento é um problema, pois uma alteração em um lugar pode quebrar várias outras. A meta é o baixo acoplamento para componentes mais autônomos.
  • Princípio da Segregação de Interfaces (SOLID — ISP): Defende que um cliente (módulo) não deve ser forçado a depender de funcionalidades que não utiliza. A preferência é por vários “contratos” (interfaces) pequenos e específicos em vez de um único contrato genérico.

O Cenário Atual: Busca e seus Problemas

A feature de Busca é vital, permitindo que o usuário encontre pessoas, serviços, features, FAQs e produtos. Para garantir a relevância, o backend personaliza e ordena os resultados com base no contexto.

Apesar de a recomendação do PicPay ser a modularização por feature, a Busca ainda utiliza a modularização por camadas. Esta estrutura criou dois principais pontos de atrito:

1. Complexidade de Configuração Exposta

O fluxo de navegação da Busca exige o objeto SearchConfig, que deveria ser flexível e parametrizável:

interface SearchNavigation {
  fun navigate(context: Context, searchConfig: SearchConfig)
}

O Problema: O SearchConfig é um modelo complexo, com cerca de 10 propriedades (algumas descontinuadas e com nomes pouco sugestivos).

// Excesso de propriedades e alta carga cognitiva
@Parcelize  
data class SearchConfig(  
  val shouldUseLocation: Boolean,  
  val type: String,  
  val limit: Int,  
  ...  
): Parcelable

Essa alta carga cognitiva faz com que os times ignorem a configuração e simplesmente copiem padrões, anulando a flexibilidade pretendida.

2. Empacotamento “Relaxado” e Alto Acoplamento

A arquitetura atual por camadas expõe o SearchRepository na camada de domínio para que a camada de dados possa implementá-lo:

// Camada de Domínio expõe o repositório
interface SearchRepository {
    suspend fun search(searchRequest: SearchRequest): List<SearchResultSection>
}

Isso permite que outros módulos injetem o repositório diretamente, pulando a camada de Use Case. Segundo a Arquitetura Limpa, isso é chamado de empacotamento por camadas “relaxada”.

O Problema: O acesso direto ao repositório cria um acoplamento indesejado. Qualquer alteração no contrato do repositório ou em seus parâmetros afeta diretamente todos os módulos clientes. Além disso, o módulo acaba expondo mais funcionalidades do que o cliente realmente necessita.

Proposta de Solução: Um Novo Modelo de Arquitetura

Nossa solução aborda os problemas atuais em três frentes principais:

1. Modularização por Feature (O Novo Alicerce)

A mudança mais evidente é migrar da modularização por camada para a Modularização por Feature.

Esta estratégia alinha a arquitetura à recomendação do PicPay e garante o controle estrito sobre quais entidades e contratos são expostos publicamente. O módulo :app passará a depender apenas dos módulos :impl (implementação), auxiliando também na redução do tempo de build.

2. Princípio da Segregação de Interfaces e Empacotamento por Componente

Para resolver o problema do acoplamento e da exposição do repositório, aplicamos o Princípio da Segregação de Interfaces (ISP):

  • Contrato Mínimo: Criamos a interface Searchable, que define apenas o comportamento essencial: buscar por um termo em texto.
interface Searchable {
    // O cliente só precisa de um termo (query)
    suspend fun search(query: String): List<SearchResultSection>  
}
  • Ponto de Acesso Único: Adotamos o Empacotamento por Componente (Capítulo 34 da Arquitetura Limpa). O Searchable se torna o ponto único de acesso ao núcleo da Busca. O módulo público expõe apenas o Searchable (o contrato), sem revelar detalhes internos de implementação (repositório, use case, etc.).
  • Criação do Objeto: A SearcherFactory serve como um “balcão de atendimento”: o cliente informa o SearchContext (o que ele precisa), e a fábrica se encarrega de criar e configurar o objeto Searchable internamente. Isso simplifica o uso para quem a consome, exigindo apenas o contexto.
interface SearcherFactory {
    fun createSearcher(context: SearchContext): Searchable  
    // ...
}

3. Configuração Centralizada por Contexto (O Segredo Didático)

A complexidade da configuração da Busca é inevitável, mas pode ser internalizada para simplificar o uso por outras features.

  • Simplificação para o Cliente: Em vez de receber o objeto SearchConfig com várias propriedades, a SearcherFactory recebe apenas um enumerador: o SearchContext.
  • Centralização: Criamos as interfaces complexas, como SearchContextConfig e SearchOriginConfig, internas ao módulo de Busca, garantindo que novas configurações não gerem novas dependências externas.
  • O Papel da Fábrica: Uma fábrica interna (SearchContextConfigFactoryImpl) é responsável por mapear o SearchContext (simples, via Enum: FEATURE_A, FEATURE_B, etc.) para a configuração interna e complexa (SearchContextConfig).
// Uso simplificado pelo cliente
override fun createSearcher(context: SearchContext): Searchable {  
    val contextConfig = contextConfigFactory.fromContext(context)
    return Searcher(
        repository = searchRepository,
        //...
    )
}
  • Trade-off Controlado: Essa centralização intencional, apesar de violar o Princípio Aberto/Fechado (O/C) — novos contextos exigem modificar a fábrica, traz um benefício maior: protege a integridade da feature ao impedir que módulos externos injetem configurações inválidas.

Conclusão

A migração para Modularização por Feature e a aplicação de princípios da Clean Architecture (ISP e Empacotamento por Componente) resultam em uma solução robusta.

Com esta abordagem:

  • O core do negócio é protegido e a evolução do código se torna mais simples.
  • O acoplamento entre módulos é drasticamente reduzido.
  • A complexidade de configuração é internalizada (Configuração por Contexto), simplificando o uso para os times clientes.

O resultado final é um desenvolvimento mais ágil, seguro e escalável para a feature de Busca e para o aplicativo como um todo.

O código de exemplo desta proposta pode ser encontrado no repositório do GitHub.

[embed]GitHub - jonathangsilveira/proposal-clean-arch-search-feature-modularization-android: Proposta de… Proposta de solução em Clean Arch e modularização por feature para Busca no app PicPay …github.com

Sobre o autor:

Natural de Blumenau (SC), pós-graduado em Engenharia de Software pela PUC-Rio e atuando na PicPay desde 2022. Desenvolvedor Android a 10 anos e atualmente me aventurando no desenvolvimento iOS e backend. Sinta-se à vontade para entrar em contato comigo através do LinkedIn para falar sobre arquitetura de software e mais.

Referências:

  1. Martin, Robert C. Arquitetura Limpa: O Guia do Artesão Para Estrutura e Design de Software. Alta Books, 2019.
  2. Android Developers. Padrões comuns para modularização de apps.
  3. The Clean Code Blog. Solid Relevance.

메타데이터
post_id
535d4cd369cc
slug
desbloqueando-a-busca-do-picpay-535d4cd369cc
url
https://medium.com/inside-picpay/desbloqueando-a-busca-do-picpay-535d4cd369cc
canonical_url
https://medium.com/inside-picpay/desbloqueando-a-busca-do-picpay-535d4cd369cc
author_url
https://medium.com/@jonathangsilveira
status
ok
fetched_at
2026-06-12 07:40:50