Clean Code 在 Swift 中的实践:面向初学者的原则与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么SOLID原则对Swift开发者如此重要

在iOS开发领域,创建可维护且可扩展的代码是一项关键任务。由Robert Martin提出的SOLID原则,至今仍是软件架构的金标准。在高级层面上,掌握这些原则在Swift中的应用,不仅能让你编写出整洁的代码,还能构建出灵活且能应对需求变化的系统。在本文中,我们将通过Swift示例逐一解析每个原则,重点关注iOS/macOS开发者的实际任务。



1. Swift中的单一职责原则(SRP)

理论:每个类或结构体应仅有一个变更原因。实践中,这意味着一个模块应负责一项明确定义的任务。



问题:过载的ViewController

在UIKit中,你经常会遇到同时管理UI、处理网络请求和保存数据的控制器。这违反了SRP原则。

// ❌ SRP 违规示例class UserViewController: UIViewController {    @IBOutlet weak var tableView: UITableView!    private var users: [User] = []

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

private func fetchUsers() { // 网络请求 URLSession.shared.dataTask(with: URL(string: "https://api.example.com/users")!) { data, _, _ in // JSON 解析 // 保存到 Core Data DispatchQueue.main.async { self.tableView.reloadData() } }.resume() }}


解决方案:职责分离

将数据和网络工作转移到独立的服务中。

// ✅ SRP:用于处理用户的独立服务protocol UserServiceProtocol {    func fetchUsers(completion: @escaping (Result<[User], Error>) -> Void)}

class UserService: UserServiceProtocol { func fetchUsers(completion: @escaping (Result<[User], Error>) -> Void) { // 网络请求逻辑 }}

// ✅ SRP:独立的 Core Data 管理器class CoreDataManager { func saveUsers(_ users: [User]) { // 保存到 Core Data }}

// ✅ SRP:ViewController 仅负责管理 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. 开闭原则(OCP)与Swift协议

理论:软件实体(类、模块)应对扩展开放,对修改关闭。在Swift中,这通过协议和继承来实现。



示例:通知系统

// ❌ OCP 违规:添加新通知类型需要修改 switch 语句class NotificationSender {    func send(_ notification: Notification, type: String) {        switch type {        case "email":            // 发送邮件        case "push":            // 发送推送        default:            break        }    }}

// ✅ OCP:使用协议protocol NotificationChannel { func send(_ notification: Notification)}

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

博客

书籍推荐