← Rust EspañolChapter 13 of 13

Mejores Practicas

## Objetivos de Aprendizaje - Escribir Rust limpio e idiomático - Seguir convenciones de nomenclatura - Dominar el flujo de trabajo con cargo - Aplicar pruebas efectivas - Recordar las reglas de prestamo ## Estilo de Codigo ### Convenciones de Nomenclatura ```rust // Modulos: snake_case mod network_module { } // Structs, Enums, Traits: PascalCase struct UserAccount { } enum Color { Red, Green, Blue } trait Summary { } // Funciones y Metodos: snake_case fn calculate_total() { } fn process_data() { } // Variables y Parametros: snake_case let user_name = "Alice"; fn print_message(message: &str) { } // Constantes: SCREAMING_SNAKE_CASE const MAX_RETRIES: u32 = 3; const PI: f64 = 3.14159; // Parametros de Tipo: PascalCase fn largest(list: &[T]) -> &T { } // Variantes de Enum: PascalCase (como structs) enum Message { Quit, Move { x: i32, y: i32 }, Write(String), } ``` ### Formateo ```rust // Usar rustfmt // Ejecutar: rustfmt your_file.rs // Longitud de linea: ~100 caracteres // Una sentencia por linea let name = "Alice"; let age = 30; // Llaves if condition { do_something(); } else { do_other(); } // Brazos de match match x { 1 => println!("one"), 2 => { let y = 2; println!("{}", y); } _ => println!("other"), } ``` ## Flujo de Trabajo con Cargo ### Nuevo Proyecto ```bash cargo new project_name cd project_name cargo run ``` ### Dependencias Agregar a Cargo.toml: ```toml [package] name = "my_project" version = "0.1.0" edition = "2021" [dependencies] rand = "0.8" # Restriccion de version serde = { version = "1.0", features = ["derive"] } # Con features ``` ### Comandos Comunes | Comando | Descripcion | |---------|-------------| | cargo build | Compilar proyecto | | cargo run | Compilar y ejecutar | | cargo test | Ejecutar pruebas | | cargo doc | Generar documentacion | | cargo check | Verificar sin compilar | | cargo build --release | Compilacion de lanzamiento | | cargo update | Actualizar dependencias | ### Cargo.lock ```bash # Commit Cargo.lock para builds reproducibles # No editarlo manualmente cargo update -p crate_name # Actualizar un solo crate ``` ## Mejores Practicas de Propiedad ### No Pelear con el Borrow Checker ```rust // Mal: complejidad innecesaria fn main() { let mut data = vec![1, 2, 3]; let first = &data[0]; data.push(4); // Error: no se puede mutar mientras hay prestamo println!("{}", first); } // Bien: orden apropiado fn main() { let mut data = vec![1, 2, 3]; println!("{}", data[0]); // Usar directamente data.push(4); // Luego mutar } ``` ### Usar Referencias para Lectura ```rust // Mal fn print_sum(data: Vec) -> i32 { let sum = data.iter().sum(); println!("{:?}", data); sum } // Bien: pedir prestado fn print_sum(data: &Vec) -> i32 { let sum = data.iter().sum(); println!("{:?}", data); sum } ``` ### Clone Cuando sea Necesario ```rust // No clonar innecesariamente fn bad_function(data: String) -> usize { data.len() } fn good_function(data: &str) -> usize { data.len() } // Cuando necesitas la propiedad fn needs_owned(data: String) -> String { // modificar data data } let s = String::from("hello"); let len = needs_owned(s.clone()); // Clonar cuando sea necesario let len = needs_owned(s); // O mover, dependiendo del uso ``` ## Mejores Practicas de Manejo de Errores ### No Usar unwrap en Produccion ```rust // Mal fn read_config() -> Config { Config::from_file("config.toml").unwrap() } // Bien: propagar error fn read_config() -> Result { Config::from_file("config.toml") } // Bien: proporcionar valor por defecto fn read_config() -> Config { Config::from_file("config.toml").unwrap_or_default() } ``` ### Usar expect para Pruebas ```rust #[cfg(test)] mod tests { #[test] fn test_calculation() { assert_eq!(calculate(2, 3), 5); } #[test] #[should_panic(expected = "division by zero")] fn test_division_by_zero() { divide(1, 0); } } ``` ## Pruebas ### Pruebas Unitarias ```rust fn add(a: i32, b: i32) -> i32 { a + b } #[cfg(test)] mod tests { use super::*; #[test] fn test_add_positive() { assert_eq!(add(2, 3), 5); } #[test] fn test_add_negative() { assert_eq!(add(-1, -1), -2); } #[test] #[should_panic(expected = "attempt to add with overflow")] fn test_add_overflow() { add(i32::MAX, 1); } } ``` ### Pruebas de Integracion Crear pruebas en directorio tests/: ```rust // tests/integration_test.rs use my_crate; #[test] fn test_integration() { assert_eq!(my_crate::add(1, 2), 3); } ``` ### Pruebas de Documentacion ```rust /// Suma dos numeros. /// /// # Ejemplos /// /// ``` /// assert_eq!(add(2, 3), 5); /// ``` pub fn add(a: i32, b: i32) -> i32 { a + b } ``` ## Documentacion ### Documentar Modulos ```rust //! Modulo de red //! //! Proporciona funcionalidad para comunicacion de red. pub mod client; pub mod server; ``` ### Documentar Funciones ```rust /// Calcula la suma de dos numeros. /// /// # Argumentos /// /// * `a` - Primer numero /// * `b` - Segundo numero /// /// # Devuelve /// /// La suma de a y b /// /// # Ejemplos /// /// ``` /// assert_eq!(add(2, 3), 5); /// ``` pub fn add(a: i32, b: i32) -> i32 { a + b } ``` ### Documentar Structs y Enums ```rust /// Representa un usuario en el sistema pub struct User { /// Identificador unico del usuario pub id: u64, /// Nombre para mostrar del usuario pub name: String, } /// Representa un tipo de mensaje pub enum Message { /// Salir de la aplicacion Quit, /// Moverse a una posicion Move { x: i32, y: i32 }, } ``` ## Consejos de Rendimiento ### Evitar Asignaciones Innecesarias ```rust // Mal: multiples asignaciones let mut s = String::new(); for word in &words { s.push_str(word); s.push(' '); } // Bien: pre-alojar o usar join let s = words.join(" "); // O let mut s = String::with_capacity(total_len); for word in &words { s.push_str(word); s.push(' '); } ``` ### Usar Referencias en Bucles ```rust // Mal: copias en cada iteracion for word in words.clone() { } // Bien: pedir prestado for word in &words { } ``` ### Preferir Asignacion en Pila ```rust // Mal: asignacion en heap let arr = Box::new([1, 2, 3]); // Bien: asignacion en pila let arr = [1, 2, 3]; ``` ## Iteradores ### Usar Iteradores en Lugar de Bucles ```rust let numbers = vec![1, 2, 3, 4, 5]; // En lugar de let mut sum = 0; for n in &numbers { sum += n; } // Preferir let sum: i32 = numbers.iter().sum(); // En lugar de let mut doubled = Vec::new(); for n in &numbers { doubled.push(n * 2); } // Preferir let doubled: Vec = numbers.iter().map(|n| n * 2).collect(); ``` ## Punteros Inteligentes ### Cuando Usar Box ```rust // Tipos recursivos enum List { Cons(T, Box>), Nil, } // Objetos trait fn print_debug(item: &dyn Debug) { println!("{:?}", item); } ``` ## Resumen - Seguir convenciones de nomenclatura de Rust (snake_case, PascalCase) - Usar `cargo fmt` y `clippy` para estilo - No usar `unwrap()` en codigo de produccion - Propagar errores con `?` o devolver Result - Escribir pruebas: pruebas unitarias, de integracion, de documentacion - Documentar APIs publicas - Preferir iteradores sobre bucles cuando sea apropiado - Clonar intencionalmente, no por accidente - Usar `Box` para tipos recursivos y objetos trait

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →