Lifecycle Patterns
Objects that are born together, live together, and die together form a natural unit. Lifecycle patterns reveal ownership hierarchies — which object is responsible for creating and destroying which other objects — and resource management strategies — how connections, sessions, and acquired capabilities are released. This lens identifies clusters of objects that share a common lifecycle, because those clusters cannot be independently deployed or tested without bringing their lifecycle peers along.
Signals and Indicators
Construction and initialization:
- Custom
init/ constructor with dependency parameters — the set of parameters reveals what the object owns vs borrows - Factory methods —
SomeClass.make(),SomeClass.create(with:), static constructors — note what the factory assembles - Builder patterns —
SomeBuilder().withX().withY().build()— the builder collects all initialization dependencies; the built object's lifecycle starts atbuild() - Two-phase initialization —
init()followed by explicitsetup()/configure()/start()— note what state exists between phases @objc func awakeFromNib()/viewDidLoad()— lifecycle initialization in the view layer tied to the host view controller's own lifecycle
Teardown and cleanup:
deinit(Swift),finalize()(Java), destructor~ClassName()(C++),Dispose()/IDisposable(C#),close()/Closeable(Java/Kotlin) — note what resources are releasedonDestroy(),onStop(),viewWillDisappear(),componentWillUnmount()— framework-managed teardown hooks; note what cleanup is performed- Explicit
cancel(),invalidate(),stop(),shutdown()calls — active teardown beyond simple deallocation deferblocks (Swift/Go) — resource cleanup guaranteed at scope exitusing(C#),try-with-resources(Java),withstatement (Python) — automatic resource management scope
Retain and memory management:
weak/unownedreferences in Swift — indicates shared ownership or prevents cycles; theweakend does not participate in the lifecycle of thestrongendWeakReference<T>in Kotlin/Java/C# — same semantics- Reference counting in C++ (
shared_ptr/weak_ptr) — ownership semantics explicit in type @autoreleasepoolblocks — scope-limited memory management- Capture lists in closures —
[weak self]vs[unowned self]vs strong capture — strong capture extends lifetime
Connection and session management:
- Database connection pools —
ConnectionPool,DBQueue(GRDB),Core Datapersistent container — connections acquired and returned - Network session objects —
URLSession,OkHttpClient,HttpClient— note whether sessions are per-request or long-lived - WebSocket connections — establish, maintain, reconnect, close — a distinct lifecycle unit
- Bluetooth peripheral connections —
CBCentralManagerconnect/disconnect cycle - Authentication sessions — login → token refresh → logout; the token's validity window IS the session lifecycle
State machines:
- Explicit state enums with associated values —
enum State { case idle, loading, loaded(Data), error(Error) }— the state machine is a lifecycle in data - State transition methods —
func transitionTo(_ state: State)— note valid transitions - Reactive state sequences —
@Published var state: State(Combine),StateFlow(Kotlin),BehaviorSubject(RxSwift/RxKotlin) — the stream IS the state machine
Resource ownership and disposal:
- Subscription storage —
var cancellables = Set<AnyCancellable>()(Combine),disposeBag: DisposeBag(RxSwift),compositeDisposable(RxJava) — the object that holds the storage bag owns the subscription lifecycle - Timer lifecycle —
Timer.scheduledTimer()must be invalidated; note where invalidation happens relative to the owning object's teardown NotificationCenterobserver registration — note whether removal is explicit (removeObserver) or managed by token disposal
Pooling and reuse:
- Object pools —
ReusablePool, cell reuse inUITableView/RecyclerView— objects are not destroyed but returned; their lifecycle is the pool's lifecycle, not the consumer's - View recycling —
prepareForReuse()— an intermediate lifecycle event between allocation and consumer use
Boundary Detection
- Shared init/deinit = same scope group. If object A creates object B in its
initand destroys it in itsdeinit, A owns B and they belong together. - Subscription ownership defines lifecycle coupling. If object A stores a
Cancellable/DisposeBagsubscription to object B's stream, A's lifecycle bounds the subscription — A and B are lifecycle-coupled. - State machines are atomic. An explicit state machine — all states, transitions, and the object that executes them — is a single unit. Do not split state machines across scope groups.
- Session objects define natural scope group boundaries. A session — authentication session, network session, user session — and all objects that exist only for the duration of that session form one scope group.
- Weak references mark scope group edges. A
weakreference from A to B means B does not own A. If A's lifecycle is independent of B's, they may belong in separate scope groups communicating through a narrow interface. - Disposal chain = lifecycle chain. Follow
Dispose()/cancel()/close()calls — each object that disposes another is part of the same lifecycle chain.
Findings Format
LIFECYCLE PATTERNS FINDINGS
============================
Object Creation Hierarchies:
- <OwnerObject> creates: <list of owned objects>
Created in: <init | factory | two-phase setup>
Destroyed in: <deinit | explicit teardown | disposal>
Session/Connection Lifecycles:
- <SessionType> — start: <trigger>, end: <trigger>, managed in: <file>
Duration: <e.g., "per request" | "per user session" | "app lifetime">
State Machines:
- <StateMachine> — states: <list>, file(s): <list>
Transitions driven by: <e.g., "user action" | "network response" | "timer">
Subscription Ownership:
- <File> owns subscriptions to: <list of publishers/observables>
Storage mechanism: <e.g., "AnyCancellable Set", "DisposeBag">
Resource Management Patterns:
- <Pattern> — used in: <file list>, resource managed: <description>
Lifecycle Anomalies:
- <description — e.g., "Timer created in viewDidLoad never invalidated — potential leak">
- <description — e.g., "Two-phase init with no clear invariants between phases">
Recommended Scope Group Candidates:
- <Name> — <lifecycle anchor object>, <one-line rationale>