Skip to content

Latest commit

 

History

History
266 lines (207 loc) · 6.31 KB

02_System_Design_Mobile.md

File metadata and controls

266 lines (207 loc) · 6.31 KB

System Design for Mobile Development (iOS)

📱 Mobile vs Backend System Design

Backend Focus:

  • Server scaling
  • Database sharding
  • Microservices

Mobile Focus:

  • App architecture
  • State management
  • Network layer
  • Local storage
  • UI performance
  • Offline-first approach

Architecture Layers

┌─────────────────────────────────────────┐
│         PRESENTATION LAYER               │
│  ┌──────────────┐  ┌──────────────┐  │
│  │   Views       │  │  ViewModels  │  │
│  │ (SwiftUI)     │  │ (Observable)  │  │
│  └──────────────┘  └──────────────┘  │
└─────────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────┐
│              DOMAIN LAYER                │
│  ┌──────────────┐  ┌──────────────┐  │
│  │  Use Cases   │  │   Entities   │  │
│  │ (Business     │  │  (Models)     │  │
│  │  Logic)      │  │               │  │
│  └──────────────┘  └──────────────┘  │
└─────────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────┐
│              DATA LAYER                  │
│  ┌──────────────┐  ┌──────────────┐  │
│  │ Repositories │  │   Services    │  │
│  │              │  │  (Network,    │  │
│  │              │  │   Auth, etc.) │  │
│  └──────────────┘  └──────────────┘  │
└─────────────────────────────────────────┘

MVVM Pattern

Structure:

View → ViewModel → Model

Example:

// View
struct HomeView: View {
    @ObservedObject var viewModel: HomeViewModel
    
    var body: some View {
        List(viewModel.items) { item in
            Text(item.title)
        }
    }
}

// ViewModel
@MainActor
class HomeViewModel: ObservableObject {
    @Published var items: [Item] = []
    
    func loadItems() {
        // Business logic
    }
}

// Model
struct Item: Identifiable {
    let id: String
    let title: String
}

Repository Pattern

Purpose:

  • Abstract data source
  • Single source of truth
  • Easy to test

Example:

protocol ItemRepositoryProtocol {
    func fetchItems() async throws -> [Item]
}

class ItemRepository: ItemRepositoryProtocol {
    private let networkService: NetworkServiceProtocol
    private let cacheService: CacheServiceProtocol
    
    func fetchItems() async throws -> [Item] {
        // 1. Check cache
        if let cached = cacheService.getItems() {
            return cached
        }
        
        // 2. Fetch from network
        let items = try await networkService.fetchItems()
        
        // 3. Cache result
        cacheService.saveItems(items)
        
        return items
    }
}

Use Cases (Business Logic)

Example:

class FetchItemsUseCase {
    private let repository: ItemRepositoryProtocol
    
    init(repository: ItemRepositoryProtocol) {
        self.repository = repository
    }
    
    func execute() async throws -> [Item] {
        return try await repository.fetchItems()
    }
}

Dependency Injection

Example:

class ViewModel {
    private let useCase: FetchItemsUseCase
    
    init(useCase: FetchItemsUseCase) {
        self.useCase = useCase
    }
}

// Setup
let networkService = NetworkService()
let repository = ItemRepository(networkService: networkService)
let useCase = FetchItemsUseCase(repository: repository)
let viewModel = ViewModel(useCase: useCase)

Network Layer

Service Protocol:

protocol NetworkServiceProtocol {
    func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T
}

Endpoint Protocol:

protocol Endpoint {
    var path: String { get }
    var method: HTTPMethod { get }
    var body: Encodable? { get }
}

Caching Strategy

Memory Cache:

private let memoryCache = NSCache<NSString, UIImage>()

Disk Cache:

let cacheDir = FileManager.default.urls(
    for: .cachesDirectory,
    in: .userDomainMask
)[0]

Offline-First Architecture

Strategy:

  1. Always return cached data first
  2. Fetch fresh data in background
  3. Update cache when fresh data arrives
  4. Queue writes for sync

Performance Optimizations

  1. Lazy Loading: Load data as needed
  2. Image Caching: Cache images in memory and disk
  3. Pagination: Load data in chunks
  4. Background Tasks: Use background queues
  5. Debouncing: Prevent excessive API calls

Common Mobile System Design Questions

1. Design Instagram Feed

  • Architecture: MVVM
  • Components: FeedView, FeedViewModel, FeedRepository
  • Optimizations: Pagination, image caching, lazy loading

2. Design Offline-First App

  • Local storage first
  • Background sync
  • Conflict resolution

3. Design Image Caching System

  • Memory cache (NSCache)
  • Disk cache (FileManager)
  • Image resizing
  • Prefetching

Checklist for Mobile System Design

  • Architecture pattern chosen (MVVM, VIPER, etc.)
  • Layers separated (Presentation, Domain, Data)
  • Dependency Injection configured
  • Protocols for abstraction
  • State management implemented
  • Error handling added
  • Caching strategy defined
  • Offline support considered
  • Performance optimizations applied
  • Testing strategy planned

Resources

  • Clean Architecture by Robert C. Martin
  • iOS Architecture Patterns
  • Ray Wenderlich Architecture Tutorials