1. A Micro-Economia dos Grafos de Construção do Gradle
Com cinco desenvolvedores, seu sistema de construção é invisível. Com mais de 50 desenvolvedores distribuídos em 10 squads diferentes, o grafo de construção do Gradle pode ser um acelerador ou a maior parte da sua folha de pagamento.
A maioria das equipes Android reage à dor de escalabilidade criando mais módulos. Elas dividem um monolito em 30 módulos de recursos, conectam-nos via dependências api e se surpreendem quando os tempos de build incremental permanecem acima de 3 minutos.
O problema não é o número de módulos; é a exposição da ABI (Application Binary Interface) em bytecode.
Classpath de Compilação vs. Classpath de Tempo de Execução
Para entender a economia da construção, devemos diferenciar entre dois classpaths gerenciados pelo Gradle:
- Classpath de Compilação (
compileClasspath): O conjunto de classes visíveis ao compilador quando processa o código-fonte no módulo M. Alterações nas dependências desse classpath acionam a recompilação do M. - Classpath de Tempo de Execução (
runtimeClasspath): O conjunto completo de classes embaladas no final DEX/APK. Alterações em dependências apenas para tempo de execução não exigem recompilação do módulo M durante as fases intermediárias de build.
+-------------------+
| :app |
+-------------------+
/ \
(impl) / \ (impl)
v v
+-----------------------+ +----------------------+
| :feature:checkout-impl| | :feature:profile-impl|
+-----------------------+ +----------------------+
| | (api) (impl)
(impl) | | (api)
v | (api)
+-----------------------+ | (api)
| :feature:profile-api | <=============+ (runtime)
+-----------------------+
| (api) (api)
(api) | | (api)
v (api)
+-----------------------+
| :core:model |
+-----------------------+ (api)
[ Legenda ]
| ---> Dependência de Tempo de Compilação (compileClasspath)
| ===> Montagem do Assembly em Tempo de Execução via :app (runtimeClasspath)Observe a fronteira arquitetônica-chave: :feature:checkout-impl compila somente contra :feature:profile-api. Ele tem zero visibilidade de tempo de compilação em :feature:profile-impl. O módulo raiz :app costura a implementação no gráfico de runtime.
Modelo Matemático de Invalidação do Gráfico de Construção
Quando um desenvolvedor modifica o código-fonte no módulo M, o Gradle avalia o conjunto de módulos downstream D(M) que dependem transitivamente do compile classpath exposto de M.
O tempo total de compilação incremental é modelado como:
Tempo Total de Compilação = T(M) + Σ T(d) [para todos d ∈ D(M)]Onde:
- T(M): custo de compilação do próprio módulo modificado M.
- D(M): conjunto de módulos downstream invalidados por mudanças no ABI em M.
- T(d): custo de compilação para cada consumidor downstream invalidado d.
Nota: Este modelo de primeira ordem isola a invalidação do classpath. O desempenho real é ainda influenciado pela saturação da memória do Gradle Daemon, paralelismo de threads de trabalho, I/O de disco e taxas de acerto em caches de build remotos.
1. Gráfico Monolítico api
Em um gráfico multi-módulo conectado via api, modificar um detalhe de implementação interna em :feature:profile altera sua assinatura pública ABI, expandindo o conjunto de invalidações para toda a árvore da feature:
D(M_monolith) = { :feature:checkout, :feature:search, :feature:cart, ... }
Tempo Total de Compilação = T(profile) + T(checkout) + T(search) + T(cart) + ...2. Gráfico de Fronteira Decoupled API/Impl
Ao encapsular a lógica privada dentro de :feature:profile-impl e expor apenas interfaces estáveis em :feature:profile-api, uma mudança interna em :feature:profile-impl reduz o conjunto de invalidações downstream para zero módulos irmãos:
D(M_impl) = Ø (Conjunto Vazio)
Tempo Total de Compilação = T(profile-impl) + 0
