--- name: Swift Clean Architecture description: File organization, layer separation, folder structures, and proactive refactoring globs: ["**/*.swift"] --- # Clean Architecture for Swift **Separation of concerns is mandatory.** Code should be organized into distinct layers with clear responsibilities and dependencies flowing inward. ## File Organization Rules ### One Public Type Per File Each file should contain exactly one public struct, class, or enum. Private supporting types may be included only if they are small and used exclusively by the main type. ### Keep Files Lean (300 Line Limit) Aim for files under 300 lines. If a file exceeds this: - Extract reusable sub-views into `Components/` folder - Extract sheets/modals into `Sheets/` folder - Extract complex logic into dedicated types - Split private view structs into their own files ### No Duplicate Code Before writing new code: 1. Search for existing implementations 2. Extract common patterns into reusable components 3. Consider protocol extraction for shared behavior ## Layer Responsibilities | Layer | Contains | Depends On | |-------|----------|------------| | **Views** | SwiftUI views, UI components | State, Models | | **State** | `@Observable` stores, view models | Models, Services | | **Services** | Business logic, networking, persistence | Models | | **Models** | Data types, entities, DTOs | Nothing | | **Protocols** | Interfaces for services and stores | Models | ### Layer Rules 1. **Views are dumb renderers** - No business logic. Read state and call methods. 2. **State holds business logic** - Computations, validations, data transformations. 3. **Services are stateless** - Pure functions where possible. Injected via protocols. 4. **Models are simple** - Plain data types. No dependencies on UI or services. ## Folder Structures Choose based on project size and team structure: ### Feature-First (Large Apps / Teams) Best for: Multiple developers, features that could become SPM packages, complex apps. ``` App/ ├── Shared/ │ ├── Design/ # Colors, typography, constants │ ├── Protocols/ # Shared protocol definitions │ ├── Services/ # Shared services (networking, auth) │ └── Components/ # Shared UI components └── Features/ ├── Home/ │ ├── Views/ │ │ ├── HomeView.swift │ │ ├── Components/ │ │ │ ├── HomeHeaderView.swift │ │ │ └── HomeCardView.swift │ │ └── Sheets/ │ │ └── HomeFilterSheet.swift │ ├── Models/ │ │ └── HomeItem.swift │ └── State/ │ └── HomeStore.swift └── Profile/ ├── Views/ ├── Models/ └── State/ ``` ### Layer-First (Small/Medium Apps / Solo) Best for: Solo developers, simpler apps, faster navigation. ``` App/ ├── Design/ # Colors, typography, constants ├── Models/ # All data models ├── Protocols/ # All protocol definitions ├── Services/ # All services ├── State/ # All observable stores └── Views/ ├── Components/ # Shared reusable components ├── Sheets/ # Shared modal presentations ├── Home/ # Home feature views └── Profile/ # Profile feature views ``` ## Proactive Refactoring **The agent will actively identify and suggest fixes for these violations:** ### File Size Violations When a file exceeds 300 lines, suggest specific extractions: - "This file is 450 lines. Consider extracting `SomePrivateView` (lines 200-280) to `Components/SomePrivateView.swift`" ### Duplicate Code Detection When similar code patterns appear: - "This filtering logic also exists in `OtherStore.swift`. Consider extracting to a shared protocol or utility." ### View Struct Proliferation When a view file contains multiple private struct definitions: - "This view has 5 private structs. Extract `HeaderView`, `RowView`, and `FooterView` to the `Components/` folder." ### Misplaced Business Logic When business logic appears in views: - "This validation logic belongs in the Store, not the View. Move `isValid` computed property to `FeatureStore`." ### Protocol Extraction Opportunities When similar interfaces appear across types: - "Both `UserService` and `TeamService` have similar fetch/save patterns. Consider a `Persistable` protocol." ## Naming Conventions - **Views**: `FeatureNameView.swift`, `FeatureNameRowView.swift` - **Stores**: `FeatureNameStore.swift` - **Models**: `FeatureName.swift` or `FeatureNameModel.swift` - **Services**: `FeatureNameService.swift` - **Protocols**: `FeatureNameProviding.swift` or `Persistable.swift`