Чистый код на Swift: принципы и практические примеры

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Clean Code на Swift: принципы и примеры

Чистый код (Clean Code) — это не просто модный термин, а философия разработки, которая напрямую влияет на скорость создания фич, количество багов и удовольствие от работы. Для Swift-разработчиков, работающих над iOS и macOS приложениями, особенно важно писать код, который легко читать и поддерживать, ведь проекты живут годами, а команды меняются. В этой статье мы разберём основные принципы Clean Code применительно к Swift и рассмотрим конкретные примеры.

1. Именование: говорите на языке предметной области

Правильное именование — основа читаемого кода. Имена переменных, функций и классов должны отвечать на вопросы "что?" и "зачем?". Избегайте сокращений и однобуквенных имён (кроме i в коротких циклах).

Плохой пример:

func calc(a: Int, b: Int) -> Int {
    return a * b + 10
}

Хороший пример:

func calculateTotalPriceWithShipping(itemPrice: Int, shippingCost: Int) -> Int {
    return itemPrice + shippingCost
}

Для булевых переменных используйте префиксы is, has, should:

var isUserLoggedIn: Bool = false
var hasCompletedOnboarding: Bool = true

Имена классов должны быть существительными ( UserManager, NetworkService ), а функции — глаголами или глагольными фразами ( fetchData(), validateEmail() ).

2. Функции: маленькие и с одной ответственностью

Каждая функция должна делать ровно одну вещь и делать её хорошо. Идеальная длина функции — 10-20 строк. Если функция превышает 30 строк — разбивайте её на более мелкие.

Плохой пример: функция, которая и валидирует, и сохраняет, и отправляет уведомление.

func processUser(_ user: User) {
    // Валидация
    guard !user.name.isEmpty else { return }
    guard user.age > 18 else { return }
    
    // Сохранение
    CoreDataManager.shared.save(user)
    
    // Уведомление
    NotificationCenter.default.post(name: .userDidRegister, object: nil)
}

Хороший пример: разделение на три отдельные функции.

func processUser(_ user: User) {
    guard isValid(user) else { return }
    saveUser(user)
    notifyUserRegistration()
}

private func isValid(_ user: User) -> Bool {
    return !user.name.isEmpty && user.age > 18
}

private func saveUser(_ user: User) {
    CoreDataManager.shared.save(user)
}

private func notifyUserRegistration() {
    NotificationCenter.default.post(name: .userDidRegister, object: nil)
}

Также избегайте большого количества параметров. Если их больше трёх — объедините в структуру.

struct SearchConfig {
    let query: String
    let category: String?
    let page: Int
    let pageSize: Int
}

func search(with config: SearchConfig) -> [Result] { ... }

3. SOLID в Swift: практические примеры

Принципы SOLID — краеугольный камень чистого кода в объектно-ориентированных языках. Рассмотрим два ключевых принципа на примерах Swift.

Принцип единственной ответственности (SRP)

Класс должен иметь только одну причину для изменения. Не смешивайте логику сети и UI.

// Нарушение SRP
class UserViewController: UIViewController {
    func fetchUser() {
        URLSession.shared.dataTask(with: URL(string: "...")!) { ... }
    }
    func updateUI() { ... }
}

// Исправление
class UserNetworkService {
    func fetchUser(completion: (User) -> Void) { ... }
}

class UserViewController: UIViewController {
    let networkService = UserNetworkService()
    
    func loadUser() {
        networkService.fetchUser { [weak self] user in
            DispatchQueue.main.async { self?.updateUI(with: user) }
        }
    }
}

Принцип подстановки Лисков (LSP)

Объекты подклассов должны быть взаимозаменяемы с объектами базового класса без нарушения логики.

class Bird {
    func fly() { print("Flying") }
}

class Penguin: Bird {
    override func fly() {
        fatalError("Penguins can't fly!") // Нарушение LSP!
    }
}

// Правильный подход: протокол Flyable
protocol Flyable {
    func fly()
}

class Bird { }
class Sparrow: Bird, Flyable {
    func fly() { print("Sparrow flying") }
}
class Penguin: Bird { } // Не реализует Flyable

4. Обработка ошибок и опционалы

Swift — язык с мощной системой типов, и чистый код должен использовать это преимущество. Избегайте force unwrapping (!) и голых try!.

Плохой пример:

let url = URL(string: "https://api.example.com")!
let data = try! Data(contentsOf: url)
let json = try! JSONSerialization.jsonObject(with: data)

Хороший пример:

enum AppError: Error {
    case invalidURL
    case networkError(Error)
    case parsingError
}

func fetchData(from urlString: String) -> Result<Any, AppError> {
    guard let url = URL(string: urlString) else {
        return .failure(.invalidURL)
    }
    
    do {
        let data = try Data(contentsOf: url)
        let json = try JSONSerialization.jsonObject(with: data)
        return .success(json)
    } catch {
        return .failure(.networkError(error))
    }
}

Для опционалов используйте guard let или if let, а не !. Это делает код безопаснее и явно показывает намерения.

// Плохо
let name = optionalName!

// Хорошо
guard let name = optionalName else { return }
// или
if let name = optionalName {
    print(name)
}

Заключение

Clean Code на Swift — это не набор жёстких правил, а набор практик, которые делают ваш код более предсказуемым, тестируемым и удобным для совместной работы. Начните с малого: переименуйте пару нечитаемых переменных, разбейте большую функцию на несколько маленьких, замените force unwrapping на безопасную обработку. Со временем эти привычки станут автоматическими, и качество вашего кода вырастет в разы. Помните: код пишется для людей, а не для компьютера. Чистый код — это проявление уважения к себе и своим коллегам.

Блоги

Рекомендаций по книгам