Frankenstein architecture
Next Launch · Deliberate counterexample · Review guide
Open
Open NextLaunchFrankenstein.xcodeproj. Select the NextLaunchFrankenstein scheme and an iPhone or iPad simulator, then Run. Xcode 26.2 was used for validation. iOS 17 minimum; Swift 6 language mode; complete concurrency checking; nonisolated default actor isolation, with explicit MainActor types. App ID: com.3DaysOfSwiftConcurrency.NextLaunchFrankenstein Test ID: com.3DaysOfSwiftConcurrency.NextLaunchFrankenstein.NextLaunchFrankensteinTests No external packages, network access, signing team or credentials are supplied. Simulator execution requires a working local Simulator runtime. Physical devices require selecting your own signing team.
What This Is
An isolated Next Launch-inspired review lab, not a damaged copy of the course app. It preserves the Next Launch icon, but has a separate bundle ID and product name. The deliberate defects live in Core/LegacyLaunchManager.swift and Core/LaunchViewModel.swift. Core/ScenarioTransport.swift and LabJournal.swift are classroom controls: synthetic data, explicit response delivery and observation. They are not real production providers or recommended production architecture. The old GCD design is represented by a callback API and retained queue hop; this is not a historical before/after migration of a real production repository.
Frankenstein Architecture
A company teaching term for incompatible or unexamined design assumptions stitched together without coherent ownership, lifetime and behaviour. Mixing technologies alone is not the diagnosis. The missing contracts and their effects are.
Reproduce
1. Start the app. Press Refresh twice. No network request will be made. 2. The status already says Refresh complete while two responses remain pending. 3. Deliver response 2. Model current launch becomes response 2; screen snapshot remains empty because its completion callback ran before the response arrived. 4. Copy model snapshot. Now the screen temporarily agrees with the model. 5. Deliver response 1. The old result overwrites model state. The screen still shows response 2. Two authorities now disagree about the same launch. 6. Press Refresh again. Press Stop. Deliver the pending response. The model changes even though the screen says Stopped. 7. Copy model snapshot, press Refresh, then Fail that response. The model erases the useful launch; the screen retains an old snapshot and says Refresh complete.
Restart the app for a clean experiment. Deliver or fail pending responses to
finish them. Nothing persists across launches. There is intentionally no fake
Reset that claims to cancel work whose handles have already been discarded.
Defect Map
FA-01: LegacyLaunchManager.refresh — completion fires when work is queued, not when it completes; the old main-queue hop surrounds a new Task. FA-02: LegacyLaunchManager.refresh / LaunchViewModel.stop — Task handle discarded; repeated refreshes create duplicate work; Stop changes presentation only. FA-03: LegacyLaunchManager.refresh — publication has no request relevance check. FA-04: LegacyLaunchManager.refresh catch — failure silently clears useful data. FA-05: LaunchViewModel.displayedLaunch — writable snapshot has no update contract.
Tests
The four Swift Testing tests PASS when the known bugs are reproduced. They are characterization evidence, not production acceptance tests. Command-U runs the unit-test target in Xcode. No UI-test target was added. The same core and tests can run on macOS with `swift test --disable-sandbox`. They use explicit continuation gates, not sleeps or network timing. When repairing a defect, change its test to express the intended correct outcome. Keep the counterexample unchanged; copy it into a separate repair project first.
Repair Brief
State the product rule before changing code. Decide whether an operation should be awaited in the current task, become structured child work, or have a separate longer-lived owner. Repeated equivalent refreshes might share one operation; changed inputs need an explicit policy. A ViewModel owns a screen workflow; a Feature owns shared rules. Handle retention alone does not prevent stale writes. Do not move all Tasks into Views or create an actor for every method. Use the CFA AI Toolkit for iOS to guide the review and proposed repair.