Give a realistic use case where provideDelegate is the right tool, and explain why moving validation into it beats validating inside getValue.
answer
- fail fast at construction vs lazy on first read
- name-bound delegate built once
- config key / DB column / view binding
- wrong tool when you WANT laziness
- error message names the exact property
basics
~20 sUse it when you must check something about the property at setup time, like its name, and want to fail fast when the object is built rather than later on first use. Checking in getValue only fails when the property is first read, which may be much later or never.
solid answer
~40 sA classic case: a framework where a property's name must match a convention, or where you build a delegate that depends on the name (a config key, a DB column, a view binding). provideDelegate receives the KProperty before binding, so you can require(prop.name == ...) or construct a name-derived delegate eagerly. Moving validation here gives fail-fast semantics at construction time and a precise error tied to the offending property, instead of a lazy failure surfacing only when (and if) getValue is first called — possibly in production, far from the declaration. It also avoids re-checking on every read. Real-world: Square's KotlinPoet-style builders, Android view-binding-like helpers, and ORM/DSL column declarations use this pattern.
go deeper
States that it lets you check the property name and fail early.
Contrasts eager construction-time validation with lazy getValue checks and gives a concrete framework example.
Weighs fail-fast vs laziness trade-offs and identifies when NOT to reach for it.
Frames it as an API-design choice (eager invariants, ergonomic errors) and ties it to real library patterns and testability.
## The problem provideDelegate solves Many delegates need the **property name** to do their job — a config key, a database column, a resource id, a serialized field name. Without `provideDelegate`, the only place you receive the `KProperty` is inside `getValue`/`setValue`, which run **lazily on access**. That has two drawbacks: 1. **Late failure.** If the name is invalid or the resource is missing, you only find out when the property is first read — which might be deep in production, or never during a test. 2. **Repeated work.** Any per-name setup re-runs (or must be cached) on every access. ## What provideDelegate gives you Because it runs **once at creation time** and receives the `KProperty<*>`, you can: - **Validate eagerly** — `require(prop.name.matches(...))` throws when the owning object is constructed, with a message naming the exact property. - **Build a name-bound delegate once** — compute the config key/column/id from `prop.name` and store it in the returned delegate, so accesses are cheap. ```kotlin class ConfigSource(private val map: Map<String, String>) { operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, String> { val key = prop.name require(map.containsKey(key)) { "Missing config key '$key'" } // fail fast at construction val value = map.getValue(key) return ReadOnlyProperty { _, _ -> value } // cheap, no per-read lookup } } class Settings(src: ConfigSource) { val timeout: String by src // throws here if 'timeout' is absent val retries: String by src } ``` ## When it is the *wrong* tool - If you genuinely want **lazy** behavior (don't touch the resource until first read), keep the logic in `getValue` or use `by lazy`. - If you don't need the property name at all, a plain delegate or a simple `ReadWriteProperty` is simpler — don't add `provideDelegate` ceremony. ## Trade-off summary | Concern | Validate in provideDelegate | Validate in getValue | |---|---|---| | When errors surface | At construction (fail fast) | On first read (lazy) | | Cost per access | One-time | Potentially repeated | | Needs property name early | Yes, available | Only at access | | Best when | name-bound/eager setup | truly lazy/optional |
- If you actually want lazy resolution, should you still use provideDelegate?No — provideDelegate runs eagerly at creation. For laziness keep logic in getValue or use by lazy.
- How does provideDelegate improve error messages over a getValue check?It throws at object construction with the property name in hand, pointing at the declaration site rather than a distant first-read.
saying these in an interview costs you the question
- Recommending provideDelegate when lazy behavior is desired
- Claiming it is the only way to get the property name (getValue/setValue also receive it)
- Ignoring that validation here runs at construction, not access
- Adding provideDelegate when the name is never needed