Quando SDKs Opcionais Agem como Infraestrutura Core
Uma falha comum de lançamento em apps mobile feitas com vibe coding é inicializar analytics, attribution ou crash reporting junto com serviços realmente críticos. Se um desses SDKs opcionais se comporta mal em um dispositivo específico ou sob uma condição de rede específica, o app inteiro pode morrer antes de a primeira tela aparecer.
Isso acontece porque código de setup gerado por IA tende a tratar toda dependência como se tivesse a mesma importância. Sem um sistema de tiers explícito, não existe distinção arquitetural entre infraestrutura obrigatória e observadores nice-to-have. Tudo vira obrigatório por acidente.
Três Tiers de Dependência
Toda dependência da sua app cai em um de três grupos. Desenhar essas linhas explicitamente é a diferença entre um app que sobrevive ao crescimento e um que morre em mil crashes de produção:
- Hard dependencies: Se elas falham, sua app não consegue renderizar. Parsing de config. Criação de storage. Construção dos services centrais. Essa é a fundação.
- Soft dependencies: Elas podem falhar com degradação elegante. Auth. Recursos dependentes de rede. Fluxos dependentes de permissão. O shell da app ainda renderiza; o usuário vê uma experiência degradada, não um crash.
- Optional dependencies: Elas podem falhar em silêncio. Analytics. Crash reporting. Testes A/B. Nunca bloqueiam a app. São observadores, não participantes.
O erro que a maioria das apps feitas com vibe coding comete é tratar tudo como hard dependency. Todo SDK inicializa na partida. Toda falha vira crash de startup. Mas o seu SDK de analytics não merece o mesmo status da sua camada de storage.
A Fronteira das Hard Dependencies
A fronteira hard valida a config e constrói os services. Se ela falha, a app mostra uma tela de erro com botão de retry, não um vazio branco que os usuários vão punir com uma estrela na App Store.
// src/context/hard-dependency-boundary.tsx
// This is the gatekeeper. If it fails, nothing else renders.
import * as SplashScreen from 'expo-splash-screen'
void SplashScreen.preventAutoHideAsync()
export function HardDependencyBoundary({
children,
}: {
children: (services: Services) => ReactNode
}) {
const { services, ready, error, retry } =
useHardDependencies()
useEffect(() => {
if (ready || error) void SplashScreen.hideAsync()
}, [ready, error])
if (error) {
return (
<ErrorScreen
title='Startup failed'
message={error.message}
onRetry={retry}
/>
)
}
if (!ready || !services) return null
return <>{children(services)}</>
}
Repare no padrão de render prop. A fronteira passa os services inicializados para os filhos. Os filhos não constroem services; eles os recebem. A construção acontece exatamente uma vez, e qualquer falha é capturada na fronteira, não vazada para um crash report em produção.
A Fronteira Opcional
Compare isso com dependências opcionais. Elas nunca deveriam derrubar sua app. Se o Mixpanel cair, sua app nem soluça:
// src/context/optional-dependency-boundary.tsx
// If analytics fails, we log a warning and keep going.
export function OptionalDependencyBoundary({
children,
}: PropsWithChildren) {
const { analytics, crashReporting } = useServices()
useEffect(() => {
try {
analytics.track('app_started')
} catch (error) {
if (__DEV__) console.warn('Analytics failed:', error)
}
try {
crashReporting.setContext('app', { started: true })
} catch (error) {
if (__DEV__) console.warn('Crash reporting failed:', error)
}
}, [analytics, crashReporting])
return <>{children}</>
}
A diferença de postura é gritante. Fronteira hard: se falhar, mostre uma tela de erro. Fronteira opcional: se falhar, registre um warning e siga em frente. As duas são explícitas. Nenhuma finge ser a outra.
A maioria dos crashes em produção em apps feitos com vibe coding vem do mesmo erro: tratar dependências soft ou opcionais como se fossem hard. O Autotomy Expo Starter Pack traça essas linhas desde o primeiro dia para que você nunca aprenda essa lição às 2 da manhã.