15.9 · Binary breaks from innocent changes, and what an import exposes
API evolution is more than deprecation: some harmless-looking source changes break binaries, and an ordinary import can leak more than you meant.
Mental model. A public API is a promise at three levels: the source callers write, the symbols already linked, and the modules a client can see.
Promises that break quietly
Default arguments versus binaries, and import visibility.
- Why does adding a defaulted parameter break clients that were already built, and how do you keep the old symbol?
Adding timeout: Int = 30 to fetch(id:) looks source compatible: every call site fetch(id: 7) still compiles. But a function’s binary symbol includes its full… - What do internal imports and MemberImportVisibility change, and how do you stop a dependency leaking through your module?
A plain import Core in a Swift 6-mode file is, by default, a public import: declarations of Core may appear in your public API, and your client can use them.… - How do you keep an architecture from eroding: dependency rules as executable checks, and what belongs in a decision record?
Diagrams and wiki pages do not stop a Friday-evening import. An architecture survives year three when its rules are executable and fail the build. State the…
More in Architecture & API design
- 15.1 · MVC, MVVM, MVP, VIPER, RIBs, TCA and Clean, and unidirectional data flow
- 15.2 · Coordinators, routers and dependency injection
- 15.3 · Feature modules and boundaries, and strangling a legacy codebase
- 15.4 · throws, Result, typed throws and mapping errors at boundaries
- 15.5 · Designing a Swift API: naming, ownership, documentation and evolution
- 15.6 · SOLID without dogma, and building a platform for many apps
- 15.7 · Effects and cancellation, modelling state, composing reducers
- 15.8 · Closure-based clients, dependency lifetimes, generic repositories and building the graph lazily
- 15.10 · Types that prevent misuse, error types for libraries, one-shot values and when to trap