Какие знаешь приемы рефакторинга?
Комментарии (3)
Ответ сгенерирован нейросетью и может содержать ошибки
Основные приемы рефакторинга в 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() {
// Логика обновления
}
}
Практические принципы применения
- Рефакторить маленькими шагами — каждый коммит должен содержать минимальные изменения
- Иметь полное покрытие тестами — без тестов рефакторинг опасен
- Использовать статический анализ — SwiftLint для автоматического поиска проблем
- Соблюдение Boy Scout Rule — оставлять код чище, чем нашел
- Рефакторинг перед добавлением новой функциональности — чистая кодовая база упрощает расширение
Инструменты для iOS-рефакторинга
- Встроенный рефакторинг Xcode (Rename, Extract Method, Add Parameter)
- SwiftLint с правилами типа
cyclomatic_complexity,function_body_length - Sourcery для метапрограммирования и устранения шаблонного кода
- Профилировщик кода (Code Climate, SonarQube) для метрик качества
Ключевой навык — отличать, когда рефакторинг необходим (высокая цикломатическая сложность, дублирование, нарушение SOLID), а когда это преждевременная оптимизация. Рефакторинг должен быть постоянной практикой, а не разовой акцией.