Что такое рефакторинг кода и когда вы его применяли?

Ответ

Рефакторинг — это процесс улучшения внутренней структуры кода без изменения его внешнего поведения. Основные цели: повышение читаемости, упрощение поддержки, устранение дублирования и улучшение архитектуры.

Типичные случаи применения:

  1. Выделение повторяющегося кода в отдельные методы, классы или утилиты.
  2. Упрощение сложных методов (разделение на части, замена условных конструкций полиморфизмом).
  3. Улучшение именования переменных, функций и классов для ясности.
  4. Замена небезопасных паттернов (например, force unwrap в Swift на guard let или if let).
  5. Внедрение протоколов/интерфейсов для уменьшения связанности.

Пример рефакторинга сетевого запроса в Swift:

До (проблемы: force unwrap, отсутствие обработки ошибок):

func fetchData() {
    if let url = URL(string: "https://api.example.com/data") {
        URLSession.shared.dataTask(with: url) { data, _, _ in
            if let data = data {
                print(String(data: data, encoding: .utf8)!)
            }
        }.resume()
    }
}

После (использование Result, безопасные unwrap, обработка ошибок):

func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
    guard let url = URL(string: "https://api.example.com/data") else {
        completion(.failure(URLError(.badURL)))
        return
    }

    URLSession.shared.dataTask(with: url) { data, _, error in
        if let error = error {
            completion(.failure(error))
            return
        }
        guard let data = data,
              let string = String(data: data, encoding: .utf8) else {
            completion(.failure(URLError(.cannotDecodeContentData)))
            return
        }
        completion(.success(string))
    }.resume()
}

Для поддержания качества кода также полезно использовать статические анализаторы (например, SwiftLint).

Ответ 18+ 🔞

О, рефакторинг, говоришь? Ну это, блядь, святое дело! Это когда ты смотришь на свой код, который месяц назад писал, и думаешь: «Ёпта, кто этот пидарас шерстяной тут нагородил? А, это же я...»

Смысл-то в чём, а? В том, чтобы код снаружи делал всё то же самое, но внутри его перетряхнуть, как старый диван, вытрясти из него все эти кривые костыли, дубликаты и хуйню нечитаемую. Чтобы потом, через полгода, открыв этот файл, не орать «в рот меня чих-пых, что это за манда с ушами?», а спокойно разобраться.

Вот смотри, классика жанра — сетевой запрос. Берёт чувак и пишет, как бог на душу положит:

func fetchData() {
    if let url = URL(string: "https://api.example.com/data") {
        URLSession.shared.dataTask(with: url) { data, _, _ in
            if let data = data {
                print(String(data: data, encoding: .utf8)!)
            }
        }.resume()
    }
}

С виду вроде работает, да? Но это же, блядь, минное поле! Во-первых, этот восклицательный знак в encoding: .utf8)! — это force unwrap, ёпта! Он как хуй с горы: может сто раз прокатить, а на сто первый — пиздец, краш. Сервер кривую кодировку прислал, и привет. Во-вторых, ошибки-то кто обрабатывать будет? Этот _ в клоуре — это же просто выкинуть всё, что не нравится, в помойку. А если сеть легла? А если таймаут? Волнение ебать, терпения ноль!

Нормальный рефакторинг — это когда ты берёшь эту хрень и делаешь из неё предсказуемую, безопасную машину. Вот, смотри, как должно быть:

func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
    guard let url = URL(string: "https://api.example.com/data") else {
        completion(.failure(URLError(.badURL)))
        return
    }

    URLSession.shared.dataTask(with: url) { data, _, error in
        if let error = error {
            completion(.failure(error))
            return
        }
        guard let data = data,
              let string = String(data: data, encoding: .utf8) else {
            completion(.failure(URLError(.cannotDecodeContentData)))
            return
        }
        completion(.success(string))
    }.resume()
}

Видишь разницу? Теперь всё по полочкам. URL не собрался? Сразу говорим — «чувак, хуйня у тебя с адресом, вот ошибка». Пришла ошибка от сессии? Передаём наверх, пусть там разбираются. Данные не декодировались в строку? Опять чёткий факап вместо тихого краша. И главное — никаких внезапных «!», которые тебе в проде ебальник разнесут.

А ещё, чтобы такой код не писать изначально, есть штука SwiftLint. Он как занудный старший брат: будет ходить за тобой и орать «Э, сабака сука, э бошка думай! Нельзя force unwrap! Имена переменных слишком короткие!». Удобно, хоть иногда и бесит, как хитрая жопа.

Короче, рефактори — не потому что тебе делать нехуй, а потому что завтра тебе же самому этот код читать и допиливать. И лучше это делать с умом, а не через жопу.