The Reuse/Release Equivalence Principle (REP) states that "the granule of reuse is the granule of release". What does that demand in practice, and what concretely goes wrong when a team publishes a component without release discipline?
answer
- Granule of reuse == granule of release
- Version + changelog + compat policy + support window
- Release note must tell ONE story
- No versions → forks, drift, unpatchable CVEs
- Weakest principle; violations are obvious
basics
~20 sREP means anything you want reused must be released as a versioned, documented unit with release notes, so consumers can tell what changed and choose when to upgrade. Its contents must form one coherent, explainable theme.
solid answer
~60 sREP demands two things. **Process:** the reusable unit must be *released* — a version number, a published artifact in a repository, release notes stating what changed, a compatibility/deprecation policy, and continued support for older versions long enough for consumers to migrate. Without this a consumer cannot judge whether upgrading is safe, so they either never upgrade or break unpredictably. **Content:** everything in the released unit must be explainable as one coherent story — a single overarching purpose and audience. A release note that mixes unrelated themes ("added retry policy and a matrix solver") proves the component is incoherent, because consumers cannot take a sensible subset: they get all of it or none of it. When REP is ignored: consumers copy-paste or fork instead of depending; "just build from main" upgrades break silently; nobody can reason about compatibility; security patches can't be back-ported to a known baseline; and coordinating multiple consumers becomes a manual negotiation. REP is weakly-defined but its violations are obvious. Semantic versioning is the usual concrete implementation of the compatibility signal.
code
text · 13 linesIncoherent release note (REP violation)
payments-lib 3.4.0
- added exponential-backoff HTTP retry helper
- fixed CSV column escaping
- new matrix determinant utility
- support for SEPA direct debit
→ four unrelated audiences; consumers can take none of it selectively
Coherent release note (REP satisfied)
payments-lib 3.4.0
- added SEPA direct debit instrument
- deprecated LegacyMandate (removal in 4.0, ~2 releases' notice)
- fixed rounding on multi-currency refundsgo deeper
Say reusable code needs a version number and release notes so users know what they're getting and when it changed.
Add the content requirement — one coherent theme per release — and name the failure modes: forking, build-from-main breakage, upgrade paralysis.
Cover the full release contract (public-API declaration, compatibility policy, deprecation notice, support window), and explain when a single-consumer internal module can legitimately skip it.
Frame REP as the platform/consumer contract: versioning and deprecation policy, support windows, SBOM/vulnerability response, bill-of-materials to restore a coherent story over fine-grained artifacts, and the organisational cost of getting it wrong.
## Statement > **Reuse/Release Equivalence Principle (REP):** *The granule of reuse is the granule of release.* You cannot reuse anything that is not also released. And since a release is atomic — consumers take the whole artifact at a version — the unit of reuse is forced to equal the unit of release. --- ## What "released" actually requires REP is often dismissed as bureaucracy. It isn't; each element exists to answer a consumer question. | Element | Consumer question it answers | |---|---| | **Version number** | "Which exact thing am I using?" | | **Published, immutable artifact** | "Can I reproduce my build tomorrow?" | | **Release notes / changelog** | "What changed since my version?" | | **Compatibility policy** (e.g. semantic versioning) | "Will upgrading break me?" | | **Deprecation policy + notice period** | "How long do I have to migrate?" | | **Support window for older versions** | "Can I get a security fix without a big upgrade?" | | **Documented public API surface** | "What am I allowed to depend on?" | A useful sharpening: REP implicitly requires you to declare **what is public API and what is internal**. If consumers can reach into internals, every internal change becomes a breaking change, and version numbers lie. --- ## The content half of REP Beyond process, REP constrains **what goes in**. Because the release is atomic, the classes inside must: - serve a **single overarching purpose** — the release must be describable in one sentence; - be **releasable together** — it must make sense to version them as one; if half the contents changes weekly and half hasn't changed in three years, the stable half is being dragged through releases it doesn't need (a joint REP/CRP smell); - target **one audience** — a component whose consumers are two disjoint groups is two components. The practical test: *write the release note.* If it reads as a list of unrelated themes, the component fails REP. --- ## Concrete failure modes when REP is ignored 1. **Fork/copy-paste reuse.** With no versions, teams copy the code to get stability. Now bug fixes and security patches must be applied N times, and the copies diverge. 2. **"Build from main" upgrades.** Consumers get whatever HEAD happens to be. Breakage arrives at random times, unattributable to a decision. 3. **Unreproducible builds.** No immutable versioned artifact means the same source can produce different results over time. 4. **Impossible security response.** You cannot say "versions 2.3.0–2.4.1 are affected; upgrade to 2.4.2" if there are no versions. Vulnerability scanners key off exactly this metadata, as do SBOMs. 5. **Upgrade paralysis.** Without change information, the safe move is never to upgrade — so consumers accumulate years of drift and eventually face a big-bang migration. 6. **No deprecation path.** You cannot remove anything, because you cannot warn anybody, so the API accretes forever. 7. **Coordination cost.** Every upgrade becomes a conversation instead of a document. --- ## Nuances and edge cases - **Internal-only code may legitimately skip REP.** If the component has exactly one consumer, deployed together from one repository, REP buys little — this is the CCP–CRP edge of the tension triangle, and it is a valid position early on. The obligation appears the moment a second, independently-released consumer exists. - **Semantic versioning is a convention, not the principle.** SemVer (MAJOR.MINOR.PATCH, where MAJOR signals incompatible changes) is the most common way to express the compatibility promise, but calendar versioning or an explicit compatibility matrix can serve. What REP requires is *a legible compatibility signal*, however encoded. - **REP conflicts with CRP under over-splitting.** Slicing into many micro-packages honours CRP but makes the release story incoherent for consumers, who must now reason about many interacting version constraints. Some ecosystems ship a coordinated *bill of materials* / platform version precisely to restore a REP-level story over fine-grained artifacts. - **Monorepos don't exempt you** if you publish externally: the published artifact still needs versions and notes, even if internal consumers build from source. - **REP is deliberately the weakest of the three.** Martin notes it says more about what goes wrong than about what to do; treat it as a constraint that eliminates obviously bad partitions rather than as a constructive algorithm.
- Is semantic versioning required by REP?No. REP requires a legible compatibility signal and a change record; SemVer is the most common encoding of that, but calendar versioning plus an explicit compatibility matrix, or a documented support-window policy, can satisfy the same need. What is not acceptable is having no signal at all.
- We have one internal library with a single consumer, both built and deployed from the same repository. Do we still need full REP ceremony?Largely no. With one co-deployed consumer, versions and changelogs buy little, and sitting on the CCP–CRP edge is a reasonable position. Introduce release discipline when a second independently released consumer appears, or when someone outside the team needs to depend on it — that is exactly when the REP costs start paying for themselves.
- How does REP interact with security response?Directly. Advisories, SBOMs and scanners all operate on 'which versions are affected'. Without released, versioned artifacts you cannot enumerate affected consumers, cannot ship a patch release on an old line, and cannot prove remediation — so a vulnerability forces every consumer into an unplanned upgrade of whatever HEAD currently is.
A pharmaceutical batch: you can only responsibly use a medicine that arrives with a batch number, a leaflet listing what changed, and a recall path. Code without version, changelog and support window is an unlabelled pill — someone will still swallow it, and nobody can trace what happened.
saying these in an interview costs you the question
- Treating REP as documentation busywork rather than a prerequisite for safe reuse
- Assuming publishing an artifact is enough without a changelog or compatibility policy
- Believing SemVer alone satisfies REP even when the component's contents are an incoherent grab-bag
- Ignoring that consumers can only take the whole release, so partial adoption is impossible
- Claiming REP always applies, even to a single-consumer internal module deployed in lock-step