La vacante pide inglés fluido y en CoFa se trabaja con equipos en Alemania. Aunque la entrevista sea en español, pueden cambiar de idioma en cualquier momento para comprobar tu nivel. Aquí tienes las 20 preguntas ⭐ de docs/ASSESSMENT.md respondidas como se dicen en voz alta: frases cortas, sin jerga de documento.
Cómo practicarlo: lee la pregunta, responde en inglés sin mirar, grábate y compara. No memorices palabra por palabra; memoriza las palabras clave en negrita.
1. Frases para la entrevista oral
| Situación | Frase |
|---|---|
| Ganar tiempo | "Good question — let me think about that for a second." |
| Estructurar | "There are two parts to this. First… Second…" |
| No lo sabes | "I haven't used that in production, but my understanding is… / I'd approach it like this…" |
| Razonar en voz alta | "I'm torn between A and B. I'd lean towards A, because…" |
| Pedir aclaración | "Just to make sure I understand: do you mean… or…?" |
| Asumir algo | "I'll assume X. If that's not the case, this part would change." |
| Trade-off | "The trade-off here is… The cost is… If the requirement changed, I'd…" |
| Defender tu respuesta | "I'd still go with X, because… but I see your point about Y." |
| Corregirte | "Actually, let me correct myself — …" |
| Hablar de Kontor | "In my demo project, Kontor, I did X. In production I'd change it to Y, because…" |
| Cerrar una respuesta | "So, in short: …" |
2. Las 20 ⭐
5. lateinit or by lazy?
"
lateinitis for a non-nullvarthat I initialise later — for example field injection with Hilt, or a test's@Before.by lazyis for avalcomputed on first access, and it's thread-safe by default.lateinitdoesn't work with primitive types."
6. value class or typealias?
"A
value classcreates a new type at compile time with no runtime cost in most cases, so I can't pass anAccountIdwhere aUserIdis expected. Atypealiasis just another name —CentsandLongare interchangeable, so it gives no type safety."
17. How do you make Kotlin code nice to call from Java?
"
@JvmStaticfor companion members,@JvmOverloadsto generate overloads for default parameters,@JvmFieldto expose fields and@Throwsfor checked exceptions. And I'd annotate nullability at the boundary, because Java gives Kotlin platform types."
19. What is structured concurrency? Why avoid GlobalScope?
"Every coroutine lives in a scope with a lifecycle — like
viewModelScope. If the scope is cancelled, all its children are cancelled, and failures propagate to the parent.GlobalScopehas no owner, so nothing cancels it: you get leaks and orphaned work."
23. What's wrong with runCatching inside a coroutine?
"It catches every
Throwable, includingCancellationException. So a cancellation becomes aResult.failureand the code after it keeps running. You need to rethrowCancellationException— for example with a smallrunSuspendCatchinghelper."
26. StateFlow, SharedFlow or Channel for one-off events?
"
StateFlowis for state: it always has a value and it conflates, so events can be lost or not re-fired. AChannelwithreceiveAsFlow()delivers each event once, and it buffers it if nobody is collecting — for example during a rotation. Google also recommends modelling events as state that the UI consumes and then clears."
27. What does stateIn do, and why WhileSubscribed(5_000)?
"It turns a cold Flow into a hot
StateFlowwith an initial value. WithWhileSubscribed(5_000)the upstream stays alive for five seconds after the last collector leaves. A rotation takes less than that, so it doesn't restart the work — but if the app goes to the background, it stops."
31. What happens to your state on rotation? And on process death?
"On rotation, the Activity is destroyed and recreated — it's a configuration change. The ViewModel survives,
rememberdoesn't. On process death, the system kills the app in the background; when the user comes back, Android recreates the same screen, but the ViewModel is new and empty. OnlyrememberSaveable,SavedStateHandleand whatever is on disk survive."
32. Why not keep an Activity Context in a ViewModel?
"Because the ViewModel outlives the Activity. After a rotation it would hold a reference to a destroyed Activity, which is a memory leak. If I need resources, I map them in the UI, or use the application context in the data layer."
33. What is an ANR and how do you avoid it?
"Application Not Responding: the main thread is blocked for about five seconds and Android offers to close the app. I avoid it by moving disk, network and heavy CPU work off the main thread with
withContext, and I catch it with StrictMode in debug and Android Vitals in production."
35. What makes a composable skip recomposition?
"Its parameters are stable and haven't changed. A plain
Listis unstable for the compiler, so you'd use an immutable collection or@Immutable— although with strong skipping, which is now the default, unstable parameters are compared by reference. I'd check it with the Layout Inspector's recomposition counts."
39. LaunchedEffect or rememberCoroutineScope?
"
LaunchedEffectis for effects driven by state: it runs when the composable enters the composition or when its key changes.rememberCoroutineScopeis for launching coroutines from user callbacks, like anonClickthat opens a bottom sheet."
42. When would you add a UseCase, and when not?
"When the logic is reused across ViewModels or combines several repositories. If it only forwards a call to a repository, it's just noise — the official guide treats the domain layer as optional."
43. How would you build an offline-first screen?
"The UI observes Room, and the network only updates Room. So there's a single source of truth, it works offline and queries are reactive. If the refresh fails, I keep showing the cached data with a non-blocking message. For a bank, writes like a transfer are never applied as final offline."
44. What does Hilt give you over manual DI?
"The graph is validated at compile time, it manages scopes and lifecycles like
@Singletonand@ViewModelScoped, it integrates with ViewModels and navigation, and in instrumented tests I can swap modules. Manual DI works for a small app, but it doesn't scale well."
49. Fakes or mocks?
"Fakes by default, like Google recommends: a fake repository backed by a
MutableStateFlowbehaves like the real one, so tests check behaviour and survive refactoring. I'd use mocks only to verify a specific interaction, like an analytics event."
50. implementation vs api in Gradle?
"
implementationhides the dependency from modules that depend on mine, so builds are faster and implementation details don't leak.apiexposes it — I only use it when that dependency is part of my public API."
51. Why would something crash only in release?
"Most likely R8: it obfuscated or removed a class used through reflection — serialization or Retrofit — because there was no keep rule. I'd deobfuscate the stack trace with the mapping file and reproduce it with a minified build locally."
52. How would you ship a risky release?
"Behind a feature flag, so I can turn it off without a new release. Internal track first, then a staged rollout — 5, 20, 100 percent — watching the crash rate, ANRs and business errors like failed transfers. If something goes wrong, I halt the rollout and switch the flag off."
53. KMP or Flutter? Why move to native?
"Flutter shares UI and logic through its own rendering engine. KMP shares domain and data and keeps the UI native. For a bank with strong native teams and platform requirements — biometrics, accessibility, security — I think KMP fits better. Flutter makes sense for a small team that needs speed. I'm moving to native because I kept needing the platform: in Flutter that meant platform channels; in native it's first-class. And a lot carries over: immutable state and unidirectional data flow from Bloc map directly to Compose and MVVM."
3. Bonus: la transferencia en 60 segundos
Es casi seguro que te pidan explicar un flujo. Ensaya este en voz alta:
"When the user confirms a transfer, the ViewModel already has an idempotency key — a UUID I generate when the user enters the review step, and I keep it in the
SavedStateHandleso it survives process death. I send the request from an application-level scope, notviewModelScope, because the transfer must not be cancelled if the user leaves the screen. If I get a timeout, I don't show it as a failure — the server may have executed it. The state becomes 'unknown' and a retry sends the same key, so the server never pays twice. Business errors like insufficient funds come back typed, and I show them on the review step."
4. Vocabulario que debe salirte sin pensar
| Español | Inglés |
|---|---|
| girar el móvil / cambio de configuración | rotation / configuration change |
| se destruye y se recrea | it's destroyed and recreated |
| muerte del proceso | process death |
| se cancela | it gets cancelled |
| fuente de verdad | single source of truth |
| hilo principal | main thread / UI thread |
| fuga de memoria | memory leak |
| despliegue gradual | staged rollout |
| reintento | retry |
| caché | cache (pronunciado /kæʃ/, como "cash") |
| inyección de dependencias | dependency injection |
| estado inmutable | immutable state |
| flujo unidireccional | unidirectional data flow |
| contrapartida | trade-off |
| compilación minificada | minified (release) build |