Section 6/71 menit

6. Real Use Cases

6. Real Use Cases

Use Case 1: SDK Multi-Modul — Networking + Analytics

swift
NetworkSDK (Package.swift)
├── NetworkCore/     — request, response, auth
├── Caching/         — response cache
├── Analytics/       — telemetry dan logging
└── NetworkUI/       — loading indicators, retry UI
swift
// NetworkCore/Authentication.swift
// package: dibutuhkan oleh Analytics untuk attach auth info ke events
package struct AuthContext {
    package let userID: String?
    package let sessionID: String
    package let deviceID: String
    
    package static var current: AuthContext {
        AuthContext(
            userID: AuthStore.shared.currentUserID,
            sessionID: SessionManager.shared.sessionID,
            deviceID: DeviceIdentifier.current
        )
    }
}

// NetworkCore/RequestPipeline.swift
// package: Analytics perlu hook ke pipeline untuk record timing
package protocol RequestMiddleware {
    package func process(_ request: URLRequest) async throws -> URLRequest
    package func process(_ response: HTTPURLResponse, data: Data) async throws -> Data
}

package class RequestPipeline {
    package var middlewares: [any RequestMiddleware] = []
    
    package func execute(_ request: URLRequest) async throws -> (Data, HTTPURLResponse) {
        var mutableRequest = request
        for middleware in middlewares {
            mutableRequest = try await middleware.process(mutableRequest)
        }
        // ... execute request
        return (Data(), HTTPURLResponse())
    }
}

// Analytics/NetworkAnalyticsMiddleware.swift
import NetworkCore

// Analytics bisa inject middleware ke dalam pipeline — tanpa end-user tahu cara ini
package class NetworkAnalyticsMiddleware: RequestMiddleware {
    package init() {}
    
    package func process(_ request: URLRequest) async throws -> URLRequest {
        let auth = AuthContext.current  // ✅ package access — sama paket
        recordRequestStart(url: request.url, userID: auth.userID)
        return request
    }
    
    package func process(_ response: HTTPURLResponse, data: Data) async throws -> Data {
        recordRequestEnd(statusCode: response.statusCode, size: data.count)
        return data
    }
    
    private func recordRequestStart(url: URL?, userID: String?) {
        print("Request started: \(url?.absoluteString ?? "unknown")")
    }
    
    private func recordRequestEnd(statusCode: Int, size: Int) {
        print("Request ended: \(statusCode), \(size) bytes")
    }
}

// NetworkSDK/Setup.swift — entry point yang public
import NetworkCore
import Analytics

public class NetworkSDK {
    public static let shared = NetworkSDK()
    
    private let pipeline = RequestPipeline()
    
    private init() {
        // Setup internal — end-user tidak perlu tahu ini
        pipeline.middlewares.append(NetworkAnalyticsMiddleware())
    }
    
    // Ini yang public — clean API untuk end-user
    public func fetch(url: URL) async throws -> Data {
        let request = URLRequest(url: url)
        let (data, _) = try await pipeline.execute(request)
        return data
    }
}

Use Case 2: Shared Test Infrastructure

swift
AppTests (Test Targets dalam satu Package)
├── CoreTests/
├── FeatureTests/
└── TestHelpers/     — shared test utilities
swift
// TestHelpers/MockFactory.swift
package class MockFactory {
    package static func makeUser(
        id: String = "test_user",
        name: String = "Test User",
        role: UserRole = .basic
    ) -> User {
        User(id: id, name: name, role: role)
    }
    
    package static func makeOrder(
        id: String = "test_order",
        items: [OrderItem] = [makeOrderItem()]
    ) -> Order {
        Order(id: id, items: items, createdAt: Date())
    }
    
    package static func makeOrderItem(
        productID: String = "prod_1",
        quantity: Int = 1,
        price: Decimal = 10.0
    ) -> OrderItem {
        OrderItem(productID: productID, quantity: quantity, price: price)
    }
}

// TestHelpers/AssertionHelpers.swift
import Testing

// Custom assertion helpers yang di-share semua test targets
package func assertUserEquals(
    _ actual: User,
    _ expected: User,
    sourceLocation: SourceLocation = #_sourceLocation
) {
    #expect(actual.id == expected.id, sourceLocation: sourceLocation)
    #expect(actual.name == expected.name, sourceLocation: sourceLocation)
    #expect(actual.role == expected.role, sourceLocation: sourceLocation)
}

// CoreTests/UserServiceTests.swift
import TestHelpers
import Testing

@Suite("UserService")
struct UserServiceTests {
    @Test
    func createUser() async throws {
        let input = MockFactory.makeUser(name: "Ari")  // ✅ package access
        let created = try await UserService().create(input)
        assertUserEquals(created, input)  // ✅ package access
    }
}

// FeatureTests/CheckoutTests.swift
import TestHelpers
import Testing

@Suite("Checkout")
struct CheckoutTests {
    @Test
    func checkout() async throws {
        let user = MockFactory.makeUser(role: .premium)  // ✅ re-use mock factory
        let order = MockFactory.makeOrder()
        // ...
    }
}

Use Case 3: Feature Flags System

swift
// FeatureFlags module (dalam SDK package)
package class FeatureFlagRegistry {
    package static let shared = FeatureFlagRegistry()
    
    private var flags: [String: Bool] = [:]
    
    package func register(flag: String, defaultValue: Bool) {
        flags[flag] = defaultValue
    }
    
    package func isEnabled(_ flag: String) -> Bool {
        flags[flag] ?? false
    }
    
    // Internal ke SDK — tidak untuk end-user
    package func override(flag: String, value: Bool) {
        flags[flag] = value
    }
}

// Feature modules — register flags saat init
// FeatureA module
import FeatureFlags

package enum FeatureAFlags {
    package static let newOnboarding = "feature_a.new_onboarding"
    package static let betaCheckout = "feature_a.beta_checkout"
}

package func setupFeatureA() {
    FeatureFlagRegistry.shared.register(flag: FeatureAFlags.newOnboarding, defaultValue: false)
    FeatureFlagRegistry.shared.register(flag: FeatureAFlags.betaCheckout, defaultValue: false)
}

// Public entry point — end-user hanya perlu ini
public class AppSDK {
    public static func initialize() {
        setupFeatureA()      // package — end-user tidak bisa panggil langsung
        setupFeatureB()
        setupFeatureC()
    }
    
    // End-user API: hanya bisa cek flag via nama yang di-expose
    public func isFeatureEnabled(_ name: PublicFeatureFlag) -> Bool {
        FeatureFlagRegistry.shared.isEnabled(name.rawValue)
    }
}

public enum PublicFeatureFlag: String {
    case newOnboarding = "feature_a.new_onboarding"
    // Hanya expose flag yang memang boleh dikontrol end-user
}