Generación segura de reportes en sistemas de información

Clase 25 de 35Curso de C# con .Net Core 2.1

Resumen

Un generador de reportes sólido parte de una idea clave: separar la extracción de datos de su presentación. Así, el reporteador se enfoca en obtener la información de las fuentes, mientras la forma de mostrarla puede variar sin afectar la lógica. Además, conviene acceder a los diccionarios de forma segura, manejar valores por defecto y usar System.Linq para hacer cast correcto de colecciones IEnumerable.

¿Por qué separar extracción y presentación en un reporteador?

La extracción y la presentación son responsabilidades distintas. El reporteador obtiene datos complejos que no siempre salen de una consulta directa a una tabla, y la presentación los muestra en el formato que convenga.

  • La presentación debe ser intercambiable sin tocar la extracción.
  • El reporte puede mostrarse en distintos medios sin reescribir la lógica.
  • La fuente de datos se mantiene única y consistente.

¿Qué formatos de salida puede tener un reporte?

  • Consola para prototipos o pruebas rápidas.
  • Página web para consumo interactivo.
  • Archivo de texto para compartir o archivar.

¿Cómo obtener listas con seguridad desde un diccionario?

Usar directamente GetValueOrDefault puede retornar el valor por defecto y llevar a errores silenciosos. Por ejemplo, si la clave no existe, una lista será nula y el flujo continúa como si todo estuviera bien.

  • Lista por defecto: nulo.
  • String por defecto: cadena vacía.
  • Entero por defecto: 0.
  • Booleano por defecto: false.

Ejemplo con GetValueOrDefault (retorna nulo si no encuentra la clave):

// lista tendrá null si la clave no existe
var lista = diccionario.GetValueOrDefault(llaves.Diccionario.Escuela);

En cambio, TryGetValue permite decidir qué hacer según el resultado: retorna un booleano y entrega la lista por parámetro de salida out.

using System.Linq; // necesario para .Cast<>()

IEnumerable<object> listaBase; // el diccionario guarda objetos del tipo base
bool rta = diccionario.TryGetValue(llaves.Diccionario.Escuela, out listaBase);

IEnumerable<escuela> respuesta = null;
if (rta)
{
    // convierte IEnumerable<object> a IEnumerable<escuela>
    respuesta = listaBase.Cast<escuela>();
}

return respuesta; // puede ser null si no se encontró la lista
  • Si rta es true: tienes la lista y puedes hacer cast al tipo esperado.
  • Si rta es false: puedes retornar nulo, registrar en el log o decidir otra acción.

¿Cuándo usar getValueOrDefault y cuándo tryGetValue?

  • GetValueOrDefault: cuando el valor por defecto sea aceptable y evidente.
  • TryGetValue: cuando necesitas confirmar la existencia y actuar según el resultado.

¿Cómo manejar nulos y auditoría?

  • Si la lista de escuelas es nula y proviene de una base de datos, es un posible incidente.
  • Registra el evento en el log de auditoría y define si el flujo debe continuar o detenerse.

¿Por qué usar System.Linq y cast con IEnumerable?

Las operaciones de colecciones en IEnumerable se potencian con System.Linq. Sin este namespace, muchos métodos de extensión —incluido Cast<>()— no aparecen, limitando el trabajo con colecciones y arreglos.

using System.Linq;

// ejemplo de cast tipado
IEnumerable<object> origen = ObtenerColeccionBase();
IEnumerable<escuela> escuelas = origen.Cast<escuela>();
  • Agrega siempre System.Linq cuando trabajes con IEnumerable.
  • Evitas errores de tipo al convertir colecciones base al tipo requerido.
  • La depuración con puntos de interrupción ayuda a validar si la lista es nula o si el cast se ejecuta como se espera.

¿Te gustaría comentar cómo manejarías los nulos en tu flujo o qué estrategias de auditoría agregarías?