swift-architecture-audit
Audits an existing Swift/SwiftUI/UIKit codebase for MVVM compliance, testability issues, architectural violations, concurrency problems, and anti-patterns. Use when user says "audit the codebase", "review the architecture", "why is this hard to test", "onboard to this project", "analyze the code structure", "find issues in the code", or "what needs refactoring".
Swift Architecture Audit
Instructions
Step 1: Explore the Project Structure
Identify the UI framework in use (SwiftUI, UIKit, or Mixed) by scanning the project — look for @main, UIApplicationDelegate, or UIHostingController. Then load the matching structure reference from ../swift-project-setup/references/ and use it as the baseline when identifying structural deviations.
Use subagents to parallelize exploration of large codebases.
Scan for:
- All feature folders and their naming patterns
- Number of
UIViewControllersubclasses vsViewModeltypes - Number of SwiftUI
Viewtypes - Presence of protocol files in
Core/orProtocols/ - Existing test targets and approximate test count
Step 2: MVVM Compliance Check
Read representative files from 3-5 key features. Look for:
Red flags (report each with file:line):
- Business logic, network calls, or storage access directly inside SwiftUI
Viewbodies - Business logic inside
UIViewControllersubclasses URLSession.sharedorUserDefaults.standardcalled from Views or ViewControllers- Missing ViewModel for any screen with non-trivial state
@Stateor@StateObjectholding data that belongs in a ViewModel or service
Green flags (note these):
ObservableObjector@ObservableViewModels with clear state- Services and repositories injected via initializer or
@Environment - Thin View layer (only layout and presentation)
- Coordinator / navigation layer separate from ViewModels
Step 3: Testability Assessment
For each audited type, check:
- Are dependencies hardcoded (
let service = NetworkService()) instead of injected? - Do networking/storage types hide behind protocols?
- Are global singletons used without injection support?
- Is there any existing test coverage? How much?
- Are ViewModels testable in isolation (no UIKit/SwiftUI imports)?
Scoring:
- High testability: Protocols + DI everywhere, existing tests
- Medium testability: Some DI, some singletons, few tests
- Low testability: No protocols, no DI, no tests — refactoring needed before testing is possible
Step 4: Concurrency Review
Identify:
- Completion handler usage where
async/awaitshould be used (new code) DispatchQueue.main.asyncscattered in ViewModel or service layers (use@MainActor)@Publishedproperties updated from background threads without actor isolation- Non-
Sendabletypes crossing actor boundaries (potential data races) sleep()anywhere in the codebase
Step 5: Anti-Pattern Inventory
| Anti-Pattern | Impact | Action |
|---|---|---|
| Massive ViewController | Untestable, unmaintainable | Extract ViewModel + Services |
| No protocol for external deps | Can't mock in tests | Wrap in protocol |
| Singleton abuse | Hidden coupling | Inject via init |
| Completion handlers in new code | Fragile async | Migrate to async/await |
| Force unwrap in production | Crashes | Replace with guard/if let |
| Business logic in View | Untestable | Move to ViewModel |
Step 6: Generate Audit Report
# Architecture Audit: [ProjectName]
Date: [date]
## Health Summary
Overall: [Good / Needs Work / Critical Issues]
MVVM Compliance: [High / Medium / Low]
Testability: [High / Medium / Low]
Concurrency: [Modern / Mixed / Legacy]
## Critical Issues (Fix First)
- [issue] in `FileName.swift:line` — [impact and suggested fix]
## Architectural Violations
- [violation] — [file(s) affected] — [recommended refactoring]
## Testability Blockers
- [blocker] — [which types are affected] — [fix: add protocol / inject dependency]
## Concurrency Issues
- [issue] — [file:line] — [suggested migration]
## Refactoring Priority
1. [Most critical — blocks testing or causes crashes]
2. [High priority — causes maintainability issues]
3. [Medium priority — worth cleaning up]
4. [Low priority / nice to have]
## Strengths
- [what the codebase does well — acknowledge good patterns]
Examples
Example 1: Legacy UIKit project
User says: "Audit the architecture, I want to add tests but everything is hard to test"
Actions:
- Explore folder structure with subagent
- Read 3 ViewControllers — assess logic placement
- Check for protocol/DI usage across service layer
- Generate prioritized audit report with specific files and lines
Example 2: SwiftUI project onboarding
User says: "I just joined this project, give me an architecture overview"
Actions:
- Map all feature modules
- Identify patterns: which architecture style is in use (MVVM, MV, etc.)
- Note testing state
- Generate onboarding summary + list of known issues
References
../swift-project-setup/references/structure-swiftui.md— expected SwiftUI layout../swift-project-setup/references/structure-uikit.md— expected UIKit layout../swift-project-setup/references/structure-mixed.md— expected Mixed layout../swift-project-setup/references/file-naming.md— naming rules and "What Never Goes Where" table
Troubleshooting
Codebase is too large to read fully: Use subagents to parallelize exploration. Focus the audit on the 3-5 most critical or highest-risk features (main flows, payment, authentication). Note coverage limitations in the report.
No clear architecture pattern found: Document what exists honestly. Don't assume intent. Recommend a migration path to MVVM with concrete first steps.