Explain the difference between `require`, `prefer`, and `strictly` inside a `version { }` block, and how `reject` interacts with them.
answer
- require = min (default)
- prefer = soft tie-breaker
- strictly = hard, downgrades, can fail
- strictly resets require
- reject = blacklist, picks highest survivor
basics
~20 srequire is the minimum acceptable (default); higher is fine. prefer is a soft tie-breaker used only when nothing else decides. strictly is a hard requirement that can downgrade and fail. reject blacklists versions that otherwise qualify.
solid answer
~40 sGradle's rich version model has three positive notions and one negative: - **`require(v)`** — the *lowest acceptable* version. Writing `implementation("g:a:1.0")` is sugar for `require("1.0")`; conflict resolution may still pick something higher. - **`prefer(v)`** — a *soft* preference, used only as a tie-breaker when `require` leaves a choice open. It never forces a downgrade and is ignored if a higher version is otherwise selected. - **`strictly(v)`** — a *hard* requirement: the resolved version must satisfy it. It can downgrade and can cause resolution to fail when incompatible with another strict requirement. Setting `strictly` clears any previously set `require`. - **`reject(...)`** — blacklists specific versions/ranges; Gradle then picks the highest *non-rejected* version satisfying the other rules. You often combine them, e.g. `strictly("[1.0, 2.0["); prefer("1.5")` — within the strict range, prefer 1.5 unless forced otherwise.
code
kotlin · 7 linesimplementation("com.squareup.okhttp3:okhttp") {
version {
strictly("[4.9, 5.0[")
prefer("4.12.0")
reject("4.11.0")
}
}go deeper
Know require is the default minimum and strictly is the hard pin.
Cleanly distinguish all four and know strictly resets require and can downgrade.
Combine strictly+prefer+reject with because() for precise, documented policies.
Standardise rich-version idioms across a platform and explain the trade-offs to other teams.
## The rich version constraint model Gradle treats a version as a small set of rules, not a single string. Inside a declaration or constraint you can open a `version { }` block: ```kotlin implementation("org.example:lib") { version { strictly("[1.2, 1.5]") prefer("1.4") reject("1.3.1") } } ``` ### `require` — the default lower bound `require("1.0")` means "1.0 or anything the graph reasonably resolves to that is >= 1.0". It is the *minimum*. Highest-version-wins conflict resolution operates on top of requires. Plain `"g:a:1.0"` desugars to a require. ### `prefer` — soft tie-breaker `prefer` only matters when, after applying all requires and rejects, more than one version is still acceptable and nothing else decides. It is the gentlest signal: it will not pull a version *down* and it loses to any concrete require/strictly that selects a higher version. Use it to express "if it's a free choice, lean this way". ### `strictly` — hard bound that downgrades `strictly` is the only positive notion that acts as an *upper* bound and can force a **downgrade**. Two incompatible stricts ⇒ resolution failure. Importantly, calling `strictly` **resets** `require` (they're mutually exclusive lower-bound semantics), though you may still pair it with `prefer` inside the strict range. ### `reject` — the negative filter `reject` removes versions (a list or range) from consideration — e.g. a known-bad patch. Gradle then chooses the highest surviving version. `reject` composes with all the above; it doesn't pick a version, it only forbids some. ## Putting it together ```kotlin constraints { implementation("com.squareup.okhttp3:okhttp") { version { strictly("[4.9, 5.0[") // stay on 4.x prefer("4.12.0") // but lean to 4.12 if free reject("4.11.0") // known regression } because("4.x line; avoid 4.11 regression; not ready for 5.x") } } ``` This says: must be a 4.x (≥4.9, <5.0), avoid 4.11.0, and when otherwise free choose 4.12.0.
- If I set both `require("1.0")` then `strictly("1.3")`, what is the effective constraint?Just strictly 1.3 — setting strictly clears the previously set require, since they express incompatible lower-bound semantics.
- Does `prefer` ever cause a downgrade?No. prefer is a soft tie-breaker; it only chooses among otherwise-acceptable versions and never lowers a version that a require/strictly already selected higher.
saying these in an interview costs you the question
- Claiming prefer can force a downgrade.
- Thinking require is an exact pin rather than a minimum.
- Saying reject selects a version (it only forbids).