CodeGym /Cursos /C# SELF /Consejos sobre estilo y legibilidad de código OOP

Consejos sobre estilo y legibilidad de código OOP

C# SELF
Nivel 25 , Lección 4
Disponible

1. Introducción

"Clean code" no es ninguna vaca sagrada, sino una herramienta real de supervivencia para programadores. En cualquier proyecto OOP, incluso el más bonito, enseguida se acumulan un montón de clases, campos, métodos, conexiones raras... Si rompes la estética y la estructura, en una semana tu propio código se convierte en una quest imposible. Más sobre la "lucha por la supervivencia" lo puedes leer en Robert Martin, "Clean Code" — va justo de esas batallas.

El estilo en el código no va de "cada uno a su bola", sino de que todos vivan más tranquilos:

  • Un colega (o tú mismo) puede pillar rápido qué está pasando.
  • Los errores (sobre todo los arquitectónicos) se ven al toque.
  • El código es más fácil de mejorar, cometiendo menos fallos.

Vamos a ver cómo hacer que el código OOP sea tan bueno que lo amen los revisores, los compis y hasta los linters.

2. Los nombres: tu primera línea de defensa

Nombrando clases

Las clases en C# se suelen nombrar en PascalCase (cada parte de la palabra empieza en mayúscula, por ejemplo: MyNewClass) y el nombre debe responder claramente a "¿Qué es esto?". ¡Los nombres deben ser sustantivos!

public class CuentaEstudiante { /* ... */ }
public class GeneradorFactura { /* ... */ }

Mal:

class hazMagia { ... } // Mal: ¿Qué magia? PascalCase roto.

Nombrando métodos

Los métodos — también en PascalCase, pero aquí mejor usar verbo + objeto de la acción:

public void ImprimirInforme() { ... }
public string ObtenerNombreFormateado() { ... }

Los métodos deben reflejar la acción (Imprimir, Obtener, Guardar, Calcular, etc.), para que al leer quede claro qué va a pasar.

Nombrando campos y propiedades

Los campos suelen ser private, se nombran en minúscula usando camelCase, muchas veces con guión bajo:

private int _contador;
private Estudiante _propietario;

Las propiedadesPascalCase, ya que son parte de la interfaz pública de la clase:

public int Saldo { get; set; }

Variables

Las variables localescamelCase, lo más corto y claro para el contexto:

string nombreEntrada;
int cantidadEstudiantes;

Y porfa, variables tipo a1, resultado2, algo — solo si quieres montarte un escape room para el mes que viene.

3. Organización de la estructura de la clase

Colocar bien los miembros de la clase hace que navegar sea más fácil y ayuda a pillar rápido qué va después de qué.

Normalmente se pone así:

  1. Constructores
  2. Propiedades
  3. Métodos
  4. Tipos anidados (enum, class, etc.)

Ejemplo:


public class Estudiante
{
    // --- Campos ---
    private string _nombre;

    // --- Constructor ---
    public Estudiante(string nombre)
    {
        _nombre = nombre;
    }

    // --- Propiedades ---
    public string Nombre
    {
        get => _nombre;
        set => _nombre = value;
    }

    // --- Métodos ---
    public void ImprimirInfo()
    {
        Console.WriteLine($"Nombre: {_nombre}");
    }
}

Estos "bloques" es cómodo separarlos con comentarios (// --- Métodos ---), sobre todo en clases grandes. JetBrains Rider, Visual Studio y otros IDE te dejan plegar/desplegar secciones rápido.

4. Comentarios y documentación

Los comentarios están bien. Pero mal si abusas o escribes "explicaciones para código raro" cuando podrías simplemente cambiar el propio código.

Un buen comentario — es el que explica el "por qué", no el "qué".

// Usamos Guid como identificador único porque el sistema es distribuido
public Guid Id { get; set; }

Documentación de métodos, clases y propiedades

Usa documentación xml para clases y métodos públicos. El IDE te muestra esas descripciones al pasar el ratón.


/// <summary>
/// Representa un estudiante de la universidad.
/// </summary>
public class Estudiante
{
    /// <summary>
    /// Nombre del estudiante.
    /// </summary>
    public string Nombre { get; set; }
}

Qué NO comentar

  • Cosas simples (i++ // incrementa i en 1).
  • Variables mal nombradas ("// aquí pasa algo" — sí, pero ¿qué?).

5. Divide y vencerás

Clases y métodos pequeños

Regla de oro: una clase — una responsabilidad (ver Single Responsibility Principle). Si la clase Estudiante lleva notas, gestiona emails y controla el horario — algo va mal.

  • Clases de hasta 300-400 líneas — bien. Más — piénsalo.
  • Métodos de hasta 15-20 líneas — legible. Hay excepciones si es un handler de un caso grande.

Ejemplo de método "inflado":


public void Procesar()
{
    // Notificar cliente
    // Guardar cambios
    // Enviar email
    // Escribir logs
    // ... (15 pasos)
}

Mejor:


public void Procesar()
{
    NotificarCliente();
    GuardarCambios();
    EnviarEmail();
    RegistrarActividad();
}

Cada paso es un método privado aparte, el código queda más compacto y fácil de testear.

6. Consejos útiles

Estructura visual: formato, sangrías, líneas en blanco

El IDE te formatea el código bonito solo (Ctrl+K, D en Visual Studio, Ctrl+Alt+L en Rider), pero los principios hay que saberlos igual.

  • SANGRÍAS — 4 espacios. Ni tabs, ni 2 espacios.
  • LÍNEAS EN BLANCO — separa métodos entre sí, campos de propiedades, propiedades de métodos.
  • LLAVES siempre en línea nueva para clases y métodos (estilo Allman):

public class Prueba
{
    public void Imprimir()
    {
        Console.WriteLine("Hola");
    }
}

Miembros "fuertes" y "débiles" de la clase: modificadores de acceso

Intenta siempre dejar todo lo más cerrado posible: abre solo lo que de verdad deba ser accesible desde fuera. Si un campo o método solo se usa dentro de la clase — hazlo private. Solo si lo necesitan los hijos — protected. public — solo para contratos.

Mal:

public string CadenaConexion; // ¡Cualquiera puede cambiarlo!

Mejor:


private string _cadenaConexion;
public string CadenaConexion
{
    get => _cadenaConexion;
    private set => _cadenaConexion = value;
}

Uso de propiedades automáticas

Con las propiedades automáticas y los setters init-only ya no tiene sentido escribir propiedades "a mano".

Ejemplo:


public string Nombre { get; set; } // ¡Perfecto!
public int Edad { get; init; }    // Solo para inicialización, más seguro.

Y si necesitas propiedades calculadas:


public string NombreCompleto => $"{Nombre} {Apellido}";

Encapsulación y getters/setters

Si una propiedad tiene lógica de negocio para cambiarla o controlarla, usa un campo privado + getter/setter público con lógica.


private int _nota;
public int Nota
{
    get => _nota;
    set
    {
        if (value < 0) _nota = 0;
        else if (value > 100) _nota = 100;
        else _nota = value;
    }
}

Así no te cargas el objeto sin querer.

7. Más consejos útiles

No temas a interfaces y abstracciones

Las interfaces sirven para contratos cómodos, testeo y ampliar la app.

Mal:

  • interfaz con un solo método que nadie usa;
  • interfaz que solo implementa una clase.
Bien:
  • interfaz que usan 2+ clases;
  • interfaz para abstraer sistemas externos (por ejemplo, para logging, almacenamiento de datos).

Escribe código fácil de testear

Una señal de buen código OOP — que sea testeable.

  • No hagas métodos que dependan de variables globales o campos estáticos.
  • No temas a la inyección de dependencias — pásalas por el constructor (Dependency Injection).
  • Separa la lógica (cálculos) de la interacción con el usuario (input/output). Así será más fácil testear y mejorar la app.

Trucos y anti-patrones para principiantes

  • No escribas "clases Dios" (God Object) que hacen de todo.
  • No pongas "números mágicos" sin explicación (if (estado == 42) — ¿por qué 42?).
  • No abuses de la herencia solo por heredar — a veces mejor composición (clase con campos de otras clases, no herencia).
  • No escribas métodos tochos de 100 líneas — no hay quien los testee ni entienda.
  • Deja siempre sitio para ampliar (open/closed principle).

8. Cómo se ve el código malo y el bueno

Ejemplo malo:


class e // Mal: nombre de clase en minúscula.
{
    public int b; // no tiene sentido, mal nombre
    public void n() // Mal: método con nombre de una letra.
    {
        Console.WriteLine(b);
        // Mal: no se entiende qué hace el método.
    }
}

Ejemplo bueno:


// Representa un estudiante.
public class Estudiante
{
    // Edad del estudiante.    
    private int _edad;
    public int Edad
    {
        get => _edad;
        set => _edad = value < 0 ? 0 : value;
    }

    // Imprime información del estudiante.
    public void ImprimirInfo()
    {
        Console.WriteLine($"Edad del estudiante: {Edad}");
    }
}
1
Cuestionario/control
Errores al heredar, nivel 25, lección 4
No disponible
Errores al heredar
Errores comunes al declarar clases y objetos
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION