← Swift EspañolChapter 13 of 13

Mejores Practicas

## Objetivos de Aprendizaje - Seguir guias de estilo de Swift - Escribir codigo limpio y mantenible - Usar Xcode efectivamente - Dominar modismos de Swift ## Convenciones de Nomenclatura ### Tipos y Protocolos ```swift // Usar PascalCase para tipos y protocolos struct PerfilUsuario {} class GestorRed {} protocol FuenteDatos {} enum MetodoHTTP {} // Nombres de protocolos describen comportamiento protocol Lector {} protocol Escritor {} ``` ### Variables y Funciones ```swift // Usar camelCase para variables y funciones let nombreUsuario = "Alicia" var estaAutenticado = false func obtenerUsuario() {} func calcularTotal() {} ``` ### Constantes ```swift // Constantes a nivel de modulo usan camelCase let maximoReintentos = 3 let tiempoLimitePredeterminado: TimeInterval = 30 // Pero casos de enum usan camelCase enum Resultado { case exito case fracaso } ``` ### Detalles Privados ```swift class Usuario { // Publico var nombre: String // Privado - el prefijo underscore es opcional private var _datosCacheados: String? private var idInterno: UUID? } ``` ## Organizacion del Codigo ### Estructura de Archivos ```swift // 1. Imports import Foundation import UIKit // 2. Declaracion de Clase/Struct // 3. Propiedades // 4. Inicializacion // 5. Metodos // 6. Extensiones // 7. Ayudantes privados ``` ### Conformidad a Protocolos ```swift class MiControladorVista: UIViewController { // Poner conformidad a protocolo en extension } extension MiControladorVista: UITableViewDataSource { func tablaView(_ tablaView: UITableView, numeroDeFilasEnSeccion seccion: Int) -> Int { return 0 } } extension MiControladorVista: UITableViewDelegate { func tablaView(_ tablaView: UITableView, didSeleccionarFilaAt indicePath: IndexPath) { // Manejar } } ``` ## Modismos de Swift ### Preferir let sobre var ```swift // Bien let nombre = "Alicia" let conteo = elementos.conteo let filtrado = elementos.filter { $0 > 0 } // Cuando se necesita mutabilidad var mutable = [1, 2, 3] mutable.append(4) ``` ### Preferir guard sobre if let ```swift // Bien func procesar(nombre: String?) { guard let nombre = nombre else { return } // Usar nombre aqui } // Evitar anidamiento func procesar(nombre: String?) { if let nombre = nombre { if nombre.conteo > 0 { // Anidamiento profundo - evitar esto } } } ``` ### Usar Trailing Closures ```swift // Bien numeros.map { $0 * 2 } URLSession.shared.dataTask(with: url) { datos, _, _ in // Manejar }.resume() ``` ### Valores por Defecto ```swift // Usar nil coalescing let nombreMostrar = usuario.nombre ?? "Anonimo" // O parametro por defecto func saludar(_ nombre: String = "Mundo") { print("Hola, \(nombre)!") } ``` ## Manejo de Errores ### Preferir Throws sobre Opcionales ```swift // Bien - cuando el fallo tiene significado func parsearJSON(_ datos: Data) throws -> [String: Any] { guard let json = try JSONSerialization.jsonObject(with: datos) as? [String: Any] else { throw ErrorParseo.formatoInvalido } return json } // Usar try? cuando el fallo no necesita detalles if let _ = try? validar(email) { // Valido } ``` ### Tipo Result para Callbacks ```swift func obtenerUsuario(completacion: @escaping (Result) -> Void) { // Exito completacion(.exito(usuario)) // Fracaso completacion(.fracaso(ErrorRed.sinConexion)) } ``` ## Control de Acceso ### Minimizar Exposicion ```swift // Bien - exponer solo lo necesario public class ClienteAPI { private let urlBase: URL private var respuestasCacheadas: [URL: Data] = [:] } // Evitar class Persona { var nombre: String = "" // Publico por defecto var edad: Int = 0 // Deberia ser privado? var ssn: String = "" // Definitivamente privado } ``` ### Preferir private sobre fileprivate ```swift class MiClase { // private - solo accesible dentro de esta clase private var ayudante: Ayudante // fileprivate - solo dentro del mismo archivo fileprivate var estadoCompartido: String = "" } ``` ## Opcionales ### Desencapsulado Seguro ```swift // Bien if let valor = opcional { usar(valor) } // Mejor para salida anticipada func procesar() { guard let valor = opcional else { return } usar(valor) } // Nil coalescing para valores por defecto let nombreMostrar = usuario.nombre ?? "Anonimo" ``` ### Evitar Force Unwrap ```swift // Mal let nombre = opcional! // Alternativas buenas if let nombre = opcional { } guard let nombre = opcional else { } let nombre = opcional ?? "pordefecto" ``` ## Rendimiento ### Tipos Valor Cuando Corresponda ```swift // Usar struct para datos simples struct Punto { var x: Double var y: Double } // Usar class para identidad compartida class Persona { var nombre: String // Compartido en toda la app } ``` ### Propiedades Lazy ```swift class ImportadorDatos { // Operacion pesada solo cuando se necesita lazy var datos: Data = { return cargarDatosPesados() }() } ``` ### Evitar Ciclos de Retencion ```swift // Usar weak para delegates weak var delegate: MiDelegate? // Usar listas de captura en closures algunLlamado { [weak self] resultado in self?.manejar(resultado) } ``` ## Pruebas ### Inyeccion de Dependencias ```swift // Bien - testeable class ServicioRed { let sesion: URLSession init(sesion: URLSession = .shared) { self.sesion = sesion } } // Testeable con mock let sesionMock = MockURLSession() let servicio = ServicioRed(sesion: sesionMock) ``` ### Diseno Orientado a Protocolos ```swift protocol ProtocoloAlmacenamiento { func guardar(_ datos: Data) throws func cargar() throws -> Data } class AlmacenamientoArchivo: ProtocoloAlmacenamiento { } class AlmacenamientoUserDefaults: ProtocoloAlmacenamiento { } ``` ## Documentacion ### Comentarios ```swift // Linea unica para explicacion breve /* Multi-linea para explicacion mas larga o comentarios detallados */ /** Comentario de documentacion (usado por Xcode) */ ``` ### Comentarios MARK ```swift class MiClase { // MARK: - Propiedades var nombre: String // MARK: - Inicializacion init() { } // MARK: - Metodos Publicos func metodoPublico() { } // MARK: - Metodos Privados private func metodoPrivado() { } } ``` ## Consejos de Xcode ### Atajos de Teclado | Accion | Atajo | |--------|-------| | Ejecutar | Cmd+R | | Compilar | Cmd+B | | Limpiar | Cmd+Shift+K | | Buscar | Cmd+F | | Reemplazar | Cmd+Alt+F | | Ir a Definicion | Cmd+Clic | | Auto-indentar | Ctrl+I | | Comentar | Cmd+/ | ### Navegacion | Accion | Atajo | |--------|-------| | Abrir Rapidamente | Cmd+Shift+O | | Navegador | Cmd+0 | | Editor Asistente | Cmd+Alt+Enter | | Abrir en Pestana | Cmd+Enter | ### Refactorizacion - Cmd+Shift+E: Refactorizar - Extraer Metodo: Seleccionar codigo, clic derecho > Refactorizar - Renombrar: Ctrl+Cmd+E ## Patrones Comunes ### Singleton ```swift final class Singleton { static let compartido = Singleton() private init() { // Inicializacion privada } } ``` ### Metodo de Fabrica ```swift class Boton { func crearBoton(estilo: EstiloBoton) -> UIButton { let boton = UIButton(type: .system) boton.setTitle(estilo.titulo, for: .normal) return boton } } ``` ### Patron Builder ```swift class ConstructorUsuario { private var nombre: String = "" private var edad: Int = 0 func establecerNombre(_ nombre: String) -> ConstructorUsuario { self.nombre = nombre return self } func establecerEdad(_ edad: Int) -> ConstructorUsuario { self.edad = edad return self } func construir() -> Usuario { return Usuario(nombre: nombre, edad: edad) } } ``` ## Resumen - Usar PascalCase para tipos, camelCase para variables - Preferir `let` sobre `var`, `struct` sobre `class` cuando corresponda - Usar `guard` para salida anticipada y desencapsulado opcional - Minimizar exposicion con control de acceso apropiado - Evitar desencapsulado y conversion forzada - Usar protocolos para abstraccion y pruebas - Documentar con comentarios MARK y documentacion Swift - Aprender atajos de Xcode para productividad - Escribir codigo testeable con inyeccion de dependencias

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →