← Назад к вопросам

Какие знаешь приемы рефакторинга?

2.0 Middle🔥 123 комментариев
#Soft Skills и карьера#Архитектура и паттерны

Комментарии (3)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основные приемы рефакторинга в iOS-разработке

Рефакторинг — это систематический процесс улучшения кода без изменения его внешнего поведения. В iOS-разработке я применяю следующие ключевые приемы:

1. Выделение метода (Extract Method)

Один из самых часто используемых приемов. Когда метод становится слишком длинным или выполняет несколько задач, я выделяю логические блоки в отдельные методы.

// До рефакторинга
func processUserData() {
    // Загрузка данных
    let data = loadDataFromNetwork()
    
    // Обработка
    var processedData: [String] = []
    for item in data {
        if item.isValid {
            processedData.append(item.formattedValue)
        }
    }
    
    // Сохранение
    saveToDatabase(processedData)
}

// После рефакторинга
func processUserData() {
    let data = loadData()
    let processedData = process(data: data)
    save(data: processedData)
}

private func loadData() -> [DataItem] {
    return loadDataFromNetwork()
}

private func process(data: [DataItem]) -> [String] {
    return data
        .filter { $0.isValid }
        .map { $0.formattedValue }
}

private func save(data: [String]) {
    saveToDatabase(data)
}

2. Замена примитива объектом (Replace Primitive with Object)

Когда примитивные типы (String, Int) начинают нести дополнительную семантику, я заменяю их на объекты-значения.

// До рефакторинга
struct User {
    let email: String // Строка без валидации
}

// После рефакторинга
struct Email {
    let value: String
    
    init(_ value: String) throws {
        guard isValidEmail(value) else {
            throw ValidationError.invalidEmail
        }
        self.value = value
    }
    
    private func isValidEmail(_ email: String) -> Bool {
        // Реализация проверки email
        return email.contains("@")
    }
}

struct User {
    let email: Email // Теперь типобезопасно
}

3. Внедрение зависимости (Dependency Injection)

Замена жестких зависимостей на абстракции для улучшения тестируемости и гибкости.

// До рефакторинга
class DataService {
    private let networkManager = NetworkManager() // Жесткая зависимость
    
    func fetchData() {
        networkManager.request(...)
    }
}

// После рефакторинга
protocol NetworkService {
    func request(_ endpoint: Endpoint) -> AnyPublisher<Data, Error>
}

class DataService {
    private let networkService: NetworkService
    
    init(networkService: NetworkService = NetworkManager()) {
        self.networkService = networkService // DI через инициализатор
    }
    
    func fetchData() {
        networkService.request(...)
    }
}

4. Замена условного оператора полиморфизмом (Replace Conditional with Polymorphism)

Устранение сложных switch-case или if-else цепочек через полиморфное поведение.

// До рефакторинга
func calculatePrice(type: ProductType, quantity: Int) -> Double {
    switch type {
    case .book:
        return Double(quantity) * 10.0
    case .electronic:
        return Double(quantity) * 100.0 * 0.9
    case .food:
        return Double(quantity) * 5.0 * 1.1
    }
}

// После рефакторинга
protocol Product {
    func calculatePrice(quantity: Int) -> Double
}

struct Book: Product {
    func calculatePrice(quantity: Int) -> Double {
        return Double(quantity) * 10.0
    }
}

struct Electronic: Product {
    func calculatePrice(quantity: Int) -> Double {
        return Double(quantity) * 100.0 * 0.9
    }
}

5. Консолидация дублирующего кода (Consolidate Duplicate Code)

Объединение одинаковой логики, разбросанной по разным местам.

6. Переименование (Rename)

Качественные имена — основа читаемости кода. Я всегда переименовываю:

  • Неинформативные имена переменных (temp, data)
  • Методы, не отражающие свои побочные эффекты
  • Bool-переменные без префикса is, has, should

7. Инкапсуляция поля (Encapsulate Field)

Скрытие внутреннего состояния и предоставление контролируемого доступа.

// До рефакторинга
class ShoppingCart {
    var items: [Item] = [] // Публичное изменение
}

// После рефакторинга
class ShoppingCart {
    private(set) var items: [Item] = [] // Только для чтения извне
    
    func addItem(_ item: Item) {
        items.append(item)
        updateTotal()
    }
    
    private func updateTotal() {
        // Логика обновления
    }
}

Практические принципы применения

  1. Рефакторить маленькими шагами — каждый коммит должен содержать минимальные изменения
  2. Иметь полное покрытие тестами — без тестов рефакторинг опасен
  3. Использовать статический анализ — SwiftLint для автоматического поиска проблем
  4. Соблюдение Boy Scout Rule — оставлять код чище, чем нашел
  5. Рефакторинг перед добавлением новой функциональности — чистая кодовая база упрощает расширение

Инструменты для iOS-рефакторинга

  • Встроенный рефакторинг Xcode (Rename, Extract Method, Add Parameter)
  • SwiftLint с правилами типа cyclomatic_complexity, function_body_length
  • Sourcery для метапрограммирования и устранения шаблонного кода
  • Профилировщик кода (Code Climate, SonarQube) для метрик качества

Ключевой навык — отличать, когда рефакторинг необходим (высокая цикломатическая сложность, дублирование, нарушение SOLID), а когда это преждевременная оптимизация. Рефакторинг должен быть постоянной практикой, а не разовой акцией.