Princípios SOLID em Swift: teoria e prática para desenvolvedores iOS avançados

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que SOLID é importante para o desenvolvedor Swift

No mundo do desenvolvimento iOS, criar código sustentável e escalável é uma tarefa fundamental. Os princípios SOLID, formulados por Robert Martin, continuam sendo o padrão ouro da arquitetura de software. Em nível avançado, dominar esses princípios em Swift permite não apenas escrever código limpo, mas também construir sistemas flexíveis e resistentes a mudanças de requisitos. Neste artigo, analisaremos cada princípio com exemplos em Swift, focando em problemas reais do desenvolvedor iOS/macOS.



1. Single Responsibility Principle (SRP) em Swift

Teoria: Cada classe ou estrutura deve ter apenas um motivo para ser alterada. Na prática, isso significa que o módulo é responsável por uma tarefa claramente definida.



Problema: ViewController sobrecarregado

No UIKit, é comum encontrar controladores que gerenciam a UI, processam requisições de rede e salvam dados simultaneamente. Isso viola o SRP.

// ❌ Violação do SRPclass UserViewController: UIViewController {    @IBOutlet weak var tableView: UITableView!    private var users: [User] = []

override func viewDidLoad() { super.viewDidLoad() fetchUsers() }

private func fetchUsers() { // Requisição de rede URLSession.shared.dataTask(with: URL(string: "https://api.example.com/users")!) { data, _, _ in // Parsing JSON // Salvamento em Core Data DispatchQueue.main.async { self.tableView.reloadData() } }.resume() }}


Solução: separação de responsabilidades

Extraímos o trabalho com dados e rede para serviços separados.

// ✅ SRP: serviço separado para trabalhar com usuáriosprotocol UserServiceProtocol {    func fetchUsers(completion: @escaping (Result<[User], Error>) -> Void)}

class UserService: UserServiceProtocol { func fetchUsers(completion: @escaping (Result<[User], Error>) -> Void) { // Lógica da requisição de rede }}

// ✅ SRP: gerenciador separado para Core Dataclass CoreDataManager { func saveUsers(_ users: [User]) { // Salvamento em Core Data }}

// ✅ SRP: ViewController gerencia apenas a UIclass UserViewController: UIViewController { private let userService: UserServiceProtocol private let coreDataManager: CoreDataManager

init(userService: UserServiceProtocol, coreDataManager: CoreDataManager) { self.userService = userService self.coreDataManager = coreDataManager super.init(nibName: nil, bundle: nil) }

override func viewDidLoad() { super.viewDidLoad() loadUsers() }

private func loadUsers() { userService.fetchUsers { [weak self] result in switch result { case .success(let users): self?.coreDataManager.saveUsers(users) self?.updateUI(with: users) case .failure(let error): self?.showError(error) } } }}


2. Open/Closed Principle (OCP) e protocolos Swift

Teoria: Entidades de software (classes, módulos) devem estar abertas para extensão, mas fechadas para modificação. Em Swift, isso é alcançado através de protocolos e herança.



Exemplo: sistema de notificações

// ❌ Violação do OCP: ao adicionar um novo tipo de notificação, é necessário alterar o switchclass NotificationSender {    func send(_ notification: Notification, type: String) {        switch type {        case "email":            // Envio de email        case "push":            // Envio de push        default:            break        }    }}

// ✅ OCP: usando protocoloprotocol NotificationChannel { func send(_ notification: Notification)}

class EmailChannel: NotificationChannel { func send(_ notification: Notification)

Blogs

Book Recommendations