CODESAMPLE

SOA - Swift

Share on:

The Service-Oriented Architecture (SOA) pattern structures an application as a collection of loosely coupled, reusable services. Each service encapsulates a specific business function and communicates with others through well-defined interfaces (often network calls). This promotes modularity, maintainability, and scalability.

The Swift example demonstrates a simplified SOA with two services: UserService and ProductService. They each have a protocol defining their interface, and concrete classes implementing that protocol. A Client class orchestrates calls to these services. Using protocols allows for easy dependency injection and mocking for testing. The structure favors composition over inheritance, a core tenet of modern Swift development, and the use of classes aligns with the typical approach for encapsulating state and behavior in a service context. Error handling is done via throws and try/catch for robustness.

// UserService.swift
protocol UserServiceProtocol {
    func getUser(id: Int) throws -> String
}

class UserService: UserServiceProtocol {
    func getUser(id: Int) throws -> String {
        // Simulate fetching user data
        if id == 1 {
            return "John Doe"
        } else {
            throw NSError(domain: "UserServiceError", code: 404, userInfo: [NSLocalizedDescriptionKey: "User not found"])
        }
    }
}

// ProductService.swift
protocol ProductServiceProtocol {
    func getProductDetails(productId: Int) throws -> String
}

class ProductService: ProductServiceProtocol {
    func getProductDetails(productId: Int) throws -> String {
        // Simulate fetching product details
        if productId == 101 {
            return "Awesome Product - Price: $99"
        } else {
            throw NSError(domain: "ProductServiceError", code: 404, userInfo: [NSLocalizedDescriptionKey: "Product not found"])
        }
    }
}

// Client.swift
class Client {
    private let userService: UserServiceProtocol
    private let productService: ProductServiceProtocol

    init(userService: UserServiceProtocol, productService: ProductServiceProtocol) {
        self.userService = userService
        self.productService = productService
    }

    func processOrder(userId: Int, productId: Int) {
        do {
            let userName = try userService.getUser(id: userId)
            let productDetails = try productService.getProductDetails(productId: productId)
            print("Processing order for \(userName): \(productDetails)")
        } catch {
            print("Error processing order: \(error.localizedDescription)")
        }
    }
}

// Usage
let userService = UserService()
let productService = ProductService()
let client = Client(userService: userService, productService: productService)

client.processOrder(userId: 1, productId: 101)
client.processOrder(userId: 2, productId: 101)
client.processOrder(userId: 1, productId: 102)