Copilot, Claude, Cursor, and others all read from ~/.agents/. The npx skills CLI handles fan-out to tool-specific directories.
144 lines
4.8 KiB
Markdown
144 lines
4.8 KiB
Markdown
---
|
|
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`
|