SwiftQA Random

How do you structure modules in large iOS apps?

The core goals modularization is actually solving

  1. Parallel/incremental compilation
  2. Enforced boundaries
  3. Team ownership alignment
  4. Testability in isolation
  5. Reusability

Common structural approaches

1. Layered/horizontal modularization — Core, Networking, Persistence, DesignSystem, Features, App.

2. Feature-based/vertical modularization — FeatureProfile, FeatureCheckout, FeatureOnboarding, each with a narrow public interface.

3. Layered + feature-based combined (the realistic large-scale shape)

Critical rule: features depend on shared layers, never on each other.

Enforcing the boundary

  • SPM’s dependency graph — undeclared dependency edges mean compile errors.
  • Access control discipline.
  • Dependency graph linting tools.

Communication between feature modules without direct dependencies

  • Protocol-based interfaces owned by a shared module.
  • A routing/deep-link layer at the composition root.
  • Event/notification-based decoupling.

The composition root

The App target — depends on every feature module, wires up root navigation, performs DI, kept deliberately thin.

Practical granularity judgment

Modularize along boundaries that correspond to actual team ownership and actual independent release/iteration cadence.

One-liner if pressed: “At scale, I’d modularize along both axes — shared horizontal layers like Core, Networking, and DesignSystem that any feature can depend on, and vertical feature modules that depend downward on those layers but never on each other directly — enforced structurally through Swift Package Manager’s dependency graph rather than just convention, with a thin composition root at the top that’s the only place allowed to know about every feature at once.”