---
title: Không hardcode cấu hình trong code - dùng xcconfig hoặc environment
impact: MEDIUM
impactDescription: Config hardcode làm khó switch giữa môi trường development/staging/production và dễ gây lỗi khi deploy.
tags: swift, ios, configuration, environment, xcconfig, code-quality
---

## Không hardcode cấu hình trong code - dùng xcconfig hoặc environment

URL của API, timeout, feature flags, và các thông số khác biệt giữa môi trường không được hardcode. Dùng `.xcconfig` file theo scheme, đọc qua `Info.plist`, hoặc dùng build setting `$(VAR_NAME)`.

**Incorrect (config hardcode):**

```swift
class APIClient {
    // !! Hardcode URL - phải sửa code khi switch môi trường
    private let baseURL = "https://api.example.com/v2"
    private let timeout: TimeInterval = 30

    init() {
        // !! Hardcode môi trường
        #if DEBUG
        let url = "https://dev-api.example.com/v2"
        #else
        let url = "https://api.example.com/v2"
        #endif
    }
}

struct Config {
    static let maxRetries = 3      // magic number
    static let sessionTimeout = 1800  // 30 phút? hardcode
}
```

**Correct (đọc từ xcconfig / Info.plist theo scheme):**

```swift
// Development.xcconfig
// API_BASE_URL = https://dev-api.example.com/v2
// REQUEST_TIMEOUT = 30
// MAX_RETRIES = 3

// Production.xcconfig
// API_BASE_URL = https://api.example.com/v2
// REQUEST_TIMEOUT = 15
// MAX_RETRIES = 2

// Info.plist
// <key>APIBaseURL</key><string>$(API_BASE_URL)</string>
// <key>RequestTimeout</key><string>$(REQUEST_TIMEOUT)</string>

struct AppConfiguration {
    static var apiBaseURL: URL {
        guard let urlString = Bundle.main.infoDictionary?["APIBaseURL"] as? String,
              let url = URL(string: urlString) else {
            fatalError("APIBaseURL configuration missing")
        }
        return url
    }

    static var requestTimeout: TimeInterval {
        let value = Bundle.main.infoDictionary?["RequestTimeout"] as? String
        return Double(value ?? "30") ?? 30
    }

    static var maxRetries: Int {
        let value = Bundle.main.infoDictionary?["MaxRetries"] as? String
        return Int(value ?? "3") ?? 3
    }
}

class APIClient {
    private let baseURL = AppConfiguration.apiBaseURL
    private let timeout = AppConfiguration.requestTimeout
}
```

**Tools:** Xcode Build Schemes + xcconfig, `Configuration.swift` helper

