Code Review en C#: no solo un trámite, sino un salvavidas para producción
\n\n¿Alguna vez has visto código que funciona, pero del que quieres cerrar los ojos? «Números mágicos», bucles dentro de bucles, async void y null donde no debería estar. El code review en C# no es un procedimiento burocrático, sino la última línea de defensa antes de que un bug llegue a producción. O, peor aún, antes de que tus colegas tengan que mantener el código maldiciendo al autor.
En este artículo analizaremos en qué fijarse realmente al revisar código C#. Sin rodeos: solo casos concretos, antipatrones y ejemplos. Si eres junior, esta es tu lista de verificación. Si eres senior, refresca la memoria. ¡Allá vamos!
\n\n1. Null: el mayor enemigo del desarrollador C#
\n\nEl famoso NullReferenceException es la causa de millones de noches sin dormir. Lo primero que revisamos en un code review: protección contra null.
¿Qué debería alertarte?
\n- \n
- Falta de verificación de
nullantes de acceder a propiedades. \n - Devolver
nulldesde métodos donde se espera una colección. \n - Ignorar contextos nullable (
#nullable enable). \n
Mal:
\npublic string GetUserName(User user)\n{\n return user.Name.ToUpper(); // ¡user puede ser null!\n}\n\nBien (C# 8+):
\npublic string GetUserName(User? user)\n{\n return user?.Name?.ToUpper() ?? "Unknown";\n}\n\nConsejo para code review: exige la activación de Nullable en proyectos nuevos. No solo está de moda, sino que evita errores tontos. Un code review C# sin verificar nullable es como conducir sin cinturón de seguridad.
2. Asincronía: async/await sin trampas
\n\nLa programación asíncrona en C# es una herramienta poderosa, pero si se usa incorrectamente se convierte en una bomba de tiempo. En la revisión verificamos tres pecados capitales.
\n\nPecado n.º 1: async void
\nLos métodos async void no se pueden rastrear: la excepción caerá en el hilo final y matará el proceso. Solo es aceptable para controladores de eventos (por ejemplo, botones en WinForms).
Mal:
\npublic async void LoadDataAsync()\n{\n var data = await _service.GetDataAsync(); // Un error matará el proceso\n}\n\nBien:
\npublic async Task LoadDataAsync()\n{\n var data = await _service.GetDataAsync();\n}\n\nPecado n.º 2: Bloquear código asíncrono
\n.Result o .Wait() en un contexto asíncrono es el camino directo al interbloqueo.
Mal:
\nvar result = _service.GetDataAsync().Result; // interbloqueo en aplicaciones UI\n\nBien:
\nvar result = await _service.GetDataAsync();\n\nPecado n.º 3: Ausencia de CancellationToken
\nLas operaciones largas deben ser cancelables. Si en la firma del método no hay CancellationToken, pregúntale al autor: «¿Qué pasará si el usuario cierra la pestaña?»
3. LINQ: ¿belleza o muerte lenta?
\n\nLINQ es elegante. Pero el code review a menudo revela que detrás de la elegancia se esconde un O(n²) o múltiples recorridos de la colección.
\n\nErrores típicos al revisar código C# con LINQ:
\n- \n
- Recorrido múltiple:
.Count() > 0+.First()— dos recorridos. Usa.Any()y.FirstOrDefault(). \n - ToList() olvidado: la carga diferida puede provocar que la consulta a la BD se ejecute después de que el contexto DataReader ya esté cerrado. \n
- Where + Select = redundancia: si se puede usar un solo
SelectMany, úsalo. \n
Ejemplo que debería encender una alarma roja:
\nvar result = l