All skills

Comprehensive macOS development guidance including Swift 6+, SwiftUI, SwiftData, architecture patterns, AppKit bridging, and macOS 26 Tahoe APIs. Use for macOS code review, best practices, UI review, or platform-specific features.

  • 40 files
  • 300.9 KB
  • Updated 3 months ago
  • GitHub

Use this Skill: https://skilld.dev/gh/rshankras/claude-code-apple-skills/macos

This session only. Nothing lands on disk.

coding-best-practicescode-organization.md

≈3.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Code Organization Best Practices

Modular architecture, project structure, and separation of concerns for macOS development.

Project Structure

Feature-Based Organization (Recommended)

MyMacApp/
├── App/
│   ├── MyMacApp.swift
│   └── AppDelegate.swift
├── Features/
│   ├── Articles/
│   │   ├── Views/
│   │   │   ├── ArticleListView.swift
│   │   │   ├── ArticleDetailView.swift
│   │   │   └── ArticleEditorView.swift
│   │   ├── ViewModels/
│   │   │   ├── ArticleListViewModel.swift
│   │   │   └── ArticleEditorViewModel.swift
│   │   ├── Models/
│   │   │   └── Article.swift
│   │   └── Services/
│   │       └── ArticleRepository.swift
│   ├── Authors/
│   │   ├── Views/
│   │   ├── ViewModels/
│   │   ├── Models/
│   │   └── Services/
│   └── Settings/
│       ├── Views/
│       ├── ViewModels/
│       └── Models/
├── Core/
│   ├── Data/
│   │   ├── SwiftDataStack.swift
│   │   └── ModelContainer+Extensions.swift
│   ├── Networking/
│   │   ├── NetworkManager.swift
│   │   ├── APIEndpoint.swift
│   │   └── NetworkError.swift
│   ├── Extensions/
│   │   ├── Date+Extensions.swift
│   │   ├── String+Extensions.swift
│   │   └── View+Extensions.swift
│   └── Utilities/
│       ├── Logger.swift
│       └── Validator.swift
├── Resources/
│   ├── Assets.xcassets
│   ├── Localization/
│   └── Fonts/
└── Tests/
    ├── ArticlesTests/
    ├── AuthorsTests/
    └── CoreTests/

Layer-Based Organization (Alternative)

MyMacApp/
├── Presentation/
│   ├── SwiftUI/
│   │   ├── Articles/
│   │   └── Settings/
│   ├── AppKit/
│   │   └── CustomViews/
│   └── ViewModels/
├── Domain/
│   ├── Models/
│   ├── UseCases/
│   └── Interfaces/
├── Data/
│   ├── Repositories/
│   ├── DataSources/
│   └── SwiftData/
└── Infrastructure/
    ├── Networking/
    └── Utilities/

Swift Package Manager Organization

Multi-Module Architecture

// Package.swift
let package = Package(
    name: "MyMacApp",
    platforms: [.macOS(.v14)],
    products: [
        .library(name: "ArticleFeature", targets: ["ArticleFeature"]),
        .library(name: "CoreKit", targets: ["CoreKit"]),
        .library(name: "NetworkKit", targets: ["NetworkKit"]),
    ],
    dependencies: [
        // External dependencies
    ],
    targets: [
        // Feature modules
        .target(
            name: "ArticleFeature",
            dependencies: ["CoreKit", "NetworkKit"]
        ),
        .testTarget(
            name: "ArticleFeatureTests",
            dependencies: ["ArticleFeature"]
        ),

        // Core module
        .target(
            name: "CoreKit",
            dependencies: []
        ),

        // Network module
        .target(
            name: "NetworkKit",
            dependencies: ["CoreKit"]
        ),
    ]
)

Benefits of SPM Modules

// ✅ GOOD: Clear dependencies and boundaries
import ArticleFeature  // Only imports what's needed
import CoreKit

// Each module can be:
// - Built independently
// - Tested in isolation
// - Reused across targets
// - Versioned separately

Separation of Concerns

MVVM Pattern for SwiftUI

// ❌ BAD: View doing too much
struct ArticleListView: View {
    @State private var articles: [Article] = []

    var body: some View {
        List(articles) { article in
            Text(article.title)
        }
        .task {
            // Bad: Networking in view
            let url = URL(string: "https://api.example.com/articles")!
            let (data, _) = try! await URLSession.shared.data(from: url)
            articles = try! JSONDecoder().decode([Article].self, from: data)
        }
    }
}

// ✅ GOOD: Proper separation
@MainActor
class ArticleListViewModel: ObservableObject {
    @Published var articles: [Article] = []
    @Published var isLoading = false
    @Published var error: Error?

    private let repository: ArticleRepository

    init(repository: ArticleRepository) {
        self.repository = repository
    }

    func loadArticles() async {
        isLoading = true
        defer { isLoading = false }

        do {
            articles = try await repository.fetchArticles()
        } catch {
            self.error = error
        }
    }
}

struct ArticleListView: View {
    @StateObject private var viewModel: ArticleListViewModel

    init(repository: ArticleRepository) {
        _viewModel = StateObject(
            wrappedValue: ArticleListViewModel(repository: repository)
        )
    }

    var body: some View {
        Group {
            if viewModel.isLoading {
                ProgressView()
            } else {
                List(viewModel.articles) { article in
                    Text(article.title)
                }
            }
        }
        .task {
            await viewModel.loadArticles()
        }
    }
}

Repository Pattern

// ✅ GOOD: Protocol defines contract
protocol ArticleRepository {
    func fetchArticles() async throws -> [Article]
    func fetchArticle(id: UUID) async throws -> Article?
    func save(_ article: Article) async throws
    func delete(id: UUID) async throws
}

// Implementation 1: SwiftData
class SwiftDataArticleRepository: ArticleRepository {
    private let modelContext: ModelContext

    init(modelContext: ModelContext) {
        self.modelContext = modelContext
    }

    func fetchArticles() async throws -> [Article] {
        let descriptor = FetchDescriptor<Article>(
            sortBy: [SortDescriptor(\.publishedDate, order: .reverse)]
        )
        return try modelContext.fetch(descriptor)
    }

    func save(_ article: Article) async throws {
        modelContext.insert(article)
        try modelContext.save()
    }

    // ... other methods
}

// Implementation 2: Network
class NetworkArticleRepository: ArticleRepository {
    private let networkManager: NetworkManager

    init(networkManager: NetworkManager) {
        self.networkManager = networkManager
    }

    func fetchArticles() async throws -> [Article] {
        try await networkManager.fetch(from: .articles)
    }

    // ... other methods
}

// Implementation 3: Mock for testing
class MockArticleRepository: ArticleRepository {
    var articles: [Article] = []

    func fetchArticles() async throws -> [Article] {
        articles
    }

    func save(_ article: Article) async throws {
        articles.append(article)
    }

    // ... other methods
}

File Organization Best Practices

Single Responsibility per File

// ✅ GOOD: One type per file
// Article.swift
struct Article: Identifiable {
    let id: UUID
    var title: String
    var content: String
}

// ArticleValidator.swift
struct ArticleValidator {
    static func validate(_ article: Article) throws {
        // Validation logic
    }
}

// ArticleFormatter.swift
struct ArticleFormatter {
    static func format(_ article: Article) -> String {
        // Formatting logic
    }
}

// ❌ BAD: Multiple unrelated types in one file
// ArticleHelpers.swift
struct Article { }
struct ArticleValidator { }
struct ArticleFormatter { }
class ArticleManager { }

Extension Organization

// Article.swift - Main definition
struct Article: Identifiable {
    let id: UUID
    var title: String
    var content: String
}

// Article+Validation.swift - Validation logic
extension Article {
    func validate() throws {
        guard !title.isEmpty else {
            throw ValidationError.emptyTitle
        }
    }
}

// Article+Formatting.swift - Formatting logic
extension Article {
    var formattedPublishDate: String {
        publishedDate.formatted(date: .long, time: .omitted)
    }
}

// Article+Codable.swift - Codable conformance
extension Article: Codable { }

Dependency Management

Composition Root

// ✅ GOOD: Single place for dependency setup
@main
struct MyMacApp: App {
    let dependencyContainer: DependencyContainer

    init() {
        dependencyContainer = DependencyContainer()
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.articleRepository, dependencyContainer.articleRepository)
                .environment(\.networkManager, dependencyContainer.networkManager)
        }
    }
}

class DependencyContainer {
    // Singletons
    lazy var networkManager: NetworkManager = {
        NetworkManager()
    }()

    lazy var modelContainer: ModelContainer = {
        try! ModelContainer(for: Article.self, Author.self)
    }()

    // Factories
    var articleRepository: ArticleRepository {
        SwiftDataArticleRepository(
            modelContext: modelContainer.mainContext
        )
    }

    var articleListViewModel: ArticleListViewModel {
        ArticleListViewModel(repository: articleRepository)
    }
}

Environment for SwiftUI

// Define environment keys
private struct ArticleRepositoryKey: EnvironmentKey {
    static let defaultValue: ArticleRepository = MockArticleRepository()
}

private struct NetworkManagerKey: EnvironmentKey {
    static let defaultValue: NetworkManager = NetworkManager()
}

extension EnvironmentValues {
    var articleRepository: ArticleRepository {
        get { self[ArticleRepositoryKey.self] }
        set { self[ArticleRepositoryKey.self] = newValue }
    }

    var networkManager: NetworkManager {
        get { self[NetworkManagerKey.self] }
        set { self[NetworkManagerKey.self] = newValue }
    }
}

// Usage in views
struct ArticleListView: View {
    @Environment(\.articleRepository) var repository

    var body: some View {
        // Use repository
    }
}

Code Reusability (DRY)

Extracting Common UI Components

// ✅ GOOD: Reusable components
struct PrimaryButton: View {
    let title: String
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .frame(maxWidth: .infinity)
                .padding()
                .background(Color.accentColor)
                .foregroundColor(.white)
                .cornerRadius(8)
        }
    }
}

struct SecondaryButton: View {
    let title: String
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .frame(maxWidth: .infinity)
                .padding()
                .background(Color.secondary.opacity(0.2))
                .foregroundColor(.primary)
                .cornerRadius(8)
        }
    }
}

// Usage
VStack {
    PrimaryButton(title: "Save") { save() }
    SecondaryButton(title: "Cancel") { cancel() }
}

View Modifiers for Common Styles

// ✅ GOOD: Custom view modifiers
struct CardStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.secondary.opacity(0.1))
            .cornerRadius(12)
            .shadow(radius: 2)
    }
}

extension View {
    func cardStyle() -> some View {
        modifier(CardStyle())
    }
}

// Usage
Text("Content")
    .cardStyle()

Testing Organization

// Tests mirror source structure
MyMacAppTests/
├── Features/
│   ├── Articles/
│   │   ├── ArticleListViewModelTests.swift
│   │   ├── ArticleRepositoryTests.swift
│   │   └── ArticleValidatorTests.swift
│   └── Settings/
│       └── SettingsViewModelTests.swift
└── Core/
    ├── NetworkManagerTests.swift
    └── ValidationTests.swift

// ✅ GOOD: Test structure
import XCTest
@testable import MyMacApp

final class ArticleListViewModelTests: XCTestCase {
    var sut: ArticleListViewModel!
    var mockRepository: MockArticleRepository!

    override func setUp() {
        super.setUp()
        mockRepository = MockArticleRepository()
        sut = ArticleListViewModel(repository: mockRepository)
    }

    override func tearDown() {
        sut = nil
        mockRepository = nil
        super.tearDown()
    }

    func testLoadArticles_Success() async {
        // Given
        let expectedArticles = [
            Article(title: "Test 1", content: "Content 1"),
            Article(title: "Test 2", content: "Content 2")
        ]
        mockRepository.articles = expectedArticles

        // When
        await sut.loadArticles()

        // Then
        XCTAssertEqual(sut.articles.count, 2)
        XCTAssertEqual(sut.articles[0].title, "Test 1")
    }
}

Configuration Management

// ✅ GOOD: Environment-based configuration
enum Environment {
    case development
    case staging
    case production

    static var current: Environment {
        #if DEBUG
        return .development
        #else
        return .production
        #endif
    }
}

struct Configuration {
    let apiBaseURL: String
    let apiKey: String
    let enableLogging: Bool

    static var current: Configuration {
        switch Environment.current {
        case .development:
            return Configuration(
                apiBaseURL: "https://dev-api.example.com",
                apiKey: "dev-key",
                enableLogging: true
            )
        case .staging:
            return Configuration(
                apiBaseURL: "https://staging-api.example.com",
                apiKey: "staging-key",
                enableLogging: true
            )
        case .production:
            return Configuration(
                apiBaseURL: "https://api.example.com",
                apiKey: "prod-key",
                enableLogging: false
            )
        }
    }
}

Code Organization Checklist

  • Clear project structure (feature or layer-based)
  • One type per file (with exceptions for tiny related types)
  • Logical grouping of related files
  • Consistent naming conventions
  • Use of Swift Package Manager for modularity
  • Proper separation of concerns (MVVM/VIPER/etc.)
  • Repository pattern for data access
  • Dependency injection at composition root
  • Reusable UI components
  • Tests mirror source structure
  • Configuration management per environment

Resources

Source: SKILL.md on GitHub

No third-party reports yet.

Signed by skilld at 32566aa. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 3 months ago
What it can do
Reads files Network
last_verified
2026-07-16
review_by
2027-06-22
os_version
iOS 27 / macOS 27
All 4 allowed tools
ReadGlobGrepWebFetch

README badge

README badge for rshankras/claude-code-apple-skills/macos