Refactorización de código legacy en Swift: de la A a la Z

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué la refactorización de código legacy en Swift es una necesidad

Cada desarrollador de iOS/macOS se encuentra tarde o temprano con código legacy. Puede ser un proyecto escrito en Objective-C y parcialmente traducido a Swift, o una aplicación creada en la era de Swift 2.0 utilizando Massive View Controller. Este código a menudo funciona, pero su mantenimiento se convierte en un infierno: cualquier cambio requiere horas de pruebas, y agregar una nueva funcionalidad rompe la anterior.

La refactorización de código legacy en Swift no es solo "peinar" el código. Es un proceso estratégico que hace que la aplicación sea más testeable, extensible y eficiente. En este artículo, analizaremos cómo abordar la refactorización correctamente, con ejemplos en Swift, para no romper la producción y obtener un resultado funcional.



1. Diagnóstico: cómo saber si el código legacy necesita refactorización

Antes de cambiar el código, debe comprender qué es exactamente lo que necesita cambios. Los principales signos de código legacy en Swift son:

  • Massive View Controller (anti-patrón MVC) — archivos con más de 500 líneas donde la lógica, la interfaz de usuario y las solicitudes de red están mezcladas en una sola clase.
  • Alto acoplamiento (tight coupling) — las clases dependen directamente unas de otras, no hay protocolos ni dependency injection.
  • Falta de pruebas — si tiene miedo de cambiar una línea de código porque no sabe qué se romperá.
  • Variables globales y singletons — uso de UserDefaults.standard o NotificationCenter.default en todo el proyecto.
  • Force unwrapping — uso generalizado de ! en lugar de la extracción segura de opcionales.


1.1. Herramientas para analizar código legacy en Swift

Para una evaluación objetiva del estado del código, utilice herramientas:

  • SwiftLint — analizador estático que detecta violaciones del code style.
  • Xcode Instruments — para buscar fugas de memoria y problemas de rendimiento.
  • Code coverage — mostrará cuánto código está cubierto por pruebas (generalmente 0-10% en proyectos legacy).

Ejemplo de código legacy típico que requiere refactorización:

class LegacyViewController: UIViewController {        @IBOutlet weak var label: UILabel!    var data: [String] = []        override func viewDidLoad() {        super.viewDidLoad()        // Mezcla de lógica y UI        let url = URL(string: "https://api.example.com/data")!        let data = try! Data(contentsOf: url)        let json = try! JSONSerialization.jsonObject(with: data) as! [[String: Any]]        for item in json {            data.append(item["name"] as! String)        }        label.text = data.first    }}

Aquí hay varios problemas: force unwrapping, solicitud de red síncrona en el hilo principal, mezcla de lógica y presentación.



2. Estrategia de refactorización de código legacy en Swift: plan paso a paso

La refactorización sin estrategia es un camino hacia el desastre. Utilice el enfoque del "zapador de combate": primero asegure el territorio, luego cambie el código.



2.1. Paso 1: Cree una "red de seguridad" de pruebas

Antes de cambiar algo, escriba pruebas para el código existente. Utilice Characterization Tests — pruebas que registran el comportamiento actual del sistema. Incluso si el código se ve horrible, las pruebas mostrarán que no ha roto la lógica.

import XCTest@testable import LegacyApp

class LegacyViewControllerTests: XCTestCase { func testViewDidLoad_SetsLabelText() { let sut = LegacyViewController() sut.loadViewIfNeeded() // Verificamos que label no sea nil y contenga texto XCTAssertNotNil(sut.label.text) }}

Esta prueba puede no ser ideal, pero registrará el estado actual. Después de la refactorización, la prueba debe pasar.



2.2. Paso

Blogs

Book Recommendations