0

¿Que no deberíamos hacer en C#?

En cada lanzamiento de .NET, se dan a conocer novedades en los lenguajes, y en esta ocasión, nos centramos en C#, el lenguaje principal.

Desde la llegada de .NET 6 y la versión 10 de C# comenzaron a presentarse diversas mejoras, como rendimiento, hot reload, Minimal API y notables avances en la construcción de aplicaciones móviles. Aunque los lanzamientos suelen destacar las novedades más llamativas, a menudo otras quedan en segundo plano y pasan desapercibidas para la mayoría de los programadores.

Quizás las mejoras que observemos no sean revolucionarias ni cambien drásticamente nuestras vidas, pero sí pueden alterar nuestra perspectiva sobre cómo abordamos las tareas. En esta nueva versión, se incorporan numerosas funcionalidades, y una de las más destacadas es la capacidad de eliminar repeticiones, lo que contribuye a la creación de código de alta calidad.

Evitar cortar colecciones grandes de forma manual con LINQ

Cuando nos encontramos con extensas colecciones de datos, rara vez recurrimos al conjunto completo. En su lugar, nos enfocamos en fragmentos más reducidos de estos datos. Como hemos señalado anteriormente, la idea es dividir esta cantidad de registros mediante paginación, lo cual tiene sentido, aunque no siempre sea viable.

¿Cuál es la estrategia a seguir? Podemos emplear los métodos de Linq, como Take y SKIP, o podemos desarrollar una extensión en Linq para establecer una manera de fragmentar estos registros y paginarlos.

static class LinqExtensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
    {
        int i = 0;
        var splits = from item in list
                     group item by i++ % parts into part
                     select part.AsEnumerable();
        return splits;
    }
}

Esta práctica ya no es necesaria. En el contexto de Linq, ahora contamos con el método Chunk, que simplifica la división de una extensa colección en múltiples páginas. Únicamente es necesario especificar la cantidad de registros que se cortarán por página.

int pageSize = 10;
IEnumerable<Employee[]> employeeChunk = employees.Chunk(pageSize);

DateOnly

Cuando surge la necesidad de manipular fechas y horas, recorremos a menudo a la clase DateTime. Pero, ¿qué ocurre cuando solo queremos trabajar con la fecha? En la actualidad, contamos con la estructura DateOnly, y también está disponible TimeOnly para abordar la hora, minutos y segundos. Observemos cómo manejábamos esta situación en el pasado:

var _date = new DateTime(2022, 1, 24);
var _theDate = _date .ToShortDateString();

Console.WriteLine(_date ); //  24/01/2022 12:00:00 AM
Console.WriteLine(_theDate ); //  24/01/2022

Cómo usamos DateOnly:

var _date = new DateOnly(2022, 1, 24);
Console.WriteLine(_date); //  24/01/2022

Surgen nuevas opciones para trabajar con estas fechas, como la posibilidad de calcular la diferencia en días entre dos fechas o llevar a cabo operaciones de suma.

MiddleWare para registro de actividad

Hasta la versión .Net 6, la gestión de datos de una solicitud HTTP solía ser una tarea engorrosa y laboriosa. Se requería la creación de un filtro que se incorporaba al pipeline de mediciones y la correspondiente registración en nuestro archivo de inicio. No obstante, con la introducción de esta versión, todas estas tareas son cosa del pasado, gracias al nuevo middleware.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpLogging();
}

Podemos customizar lo que queramos registrar.

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpLogging(logging =>
    {
        logging.LoggingFields = HttpLoggingFields.All;
        logging.RequestHeaders.Add("X-Request-Header");
        logging.ResponseHeaders.Add("X-Response-Header");
        logging.RequestBodyLogLimit = 4096;
        logging.ResponseBodyLogLimit = 4096;
    });
}

Componente ErrorBoundary en Blazor

Cuando surge una excepción no controlada en Blazor Server, se administra como un error fatal que alerta sobre «el circuito quedando en un estado indefinido que podría ocasionar problemas de estabilidad o seguridad en Blazor Server». Podríamos encontrarnos tentados a saturar nuestro código con bloques try/catch como medida preventiva o a encapsular la lógica en JavaScript, dado que no estamos tratando con código C#.

Para enfrentar estas complicaciones, contamos con la introducción del revolucionario componente ErrorBoundary. Aunque no asume el papel de un controlador de excepciones global, contribuye de manera significativa a gestionar el comportamiento impredecible, especialmente en componentes que no puede o no controla.

<div class="main">
    <div class="content px-4">
        <ErrorBoundary>
            @Body
        </ErrorBoundary>
    </div>
</div>

Es posible usarlos en cualquier lugar y customizar el error.

<tbody>
    @foreach (var employee in Employees)
    {
        <ErrorBoundary @key="@board">
            <ChildContent>
                <tr>
                    <td>@employee.Id</td>
                    <td>@employee.FirstName</td>
                    <td>@employee.LastName</td>
                 </tr>
            </ChildContent>
            <ErrorContent>
                Sorry, I can't show @employee.Id because of an internal error.
            </ErrorContent>
        </ErrorBoundary>
    }
</tbody>

Subcategorías para Server.Kestrel

Si nos proponemos activar el registro detallado para Kestrel, en el pasado, se requería el uso de Microsoft.AspNetCore.Server.Kestrel. Aunque esta opción permanece disponible, ha sido enriquecida con nuevas subcategorías que buscan hacer más accesible el proceso.

Lo clásico es:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.Server.Kestrel": "Debug"
    }
  }
}

Mejor hacerlo con la subcategoría:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.Server.Kestrel.BadRequests": "Debug"
    }
  }
}

Definitivamente esto hará que trabajar con el registro detallado de Kestrel sea mucho más sencillo.

Namespaces de archivo

Desde la versión de c# 10.0 es una nueva funcionalidad que personalmente utilizo mucho. Hasta ahora el namespace debía usar llaves, algo así:

namespace ConsoleApp.Models
{
   public class Customer
   {
      public string? FirstName { get; set; }
      public string? LastName { get; set; }
   }
}

Hoy no es necesarios, podemos usar namespaces a nivel de archivo:

namespace SuperheroApp.Models;

public class Customer
{
   public string? FirstName { get; set; }
   public string? LastName { get; set; }
}

Por otro lado, si es un objeto poco, podríamos usar directamente récord para hacer nuestra clase:

namespace Customer.Models;

public record Customer(string? FirstName, string? LastName);

Exceso de brackets

En la sección previa, examinamos las ventajas de prescindir de algunos elementos; no obstante, es importante destacar que también existe la posibilidad de abusar de los mismos. Veamos un ejemplo:

public static int CalculateShirt(Customer customer) =>

        customers witch
        {
            { Shirt: { Color: "Blue" } } => 100,
            { Shirt: { Color: "Yellow" } } => 200,
            { Shirt: { Color: "Red" } } => 300
            _ => 0
        };

Mejora:

public static int CalculateShirt(Customer customer) =>

        Customer switch
        {
            { Shirt.Color: "Blue" } => 100,
            { Shirt.Color: "Yellow" } => 200,
            { Shirt.Color: "Red" } => 300
            _ => 0
        };

Conclusiones

Se destacan avances clave en .Net y C# que a menudo pasan desapercibidos. La integración de inteligencia artificial y aprendizaje automático en C# amplía las posibilidades de desarrollo, permitiendo aplicaciones más inteligentes. Además, mejoras en rendimiento, escalabilidad y soporte para contenedores están redefiniendo la eficiencia del desarrollo. Estas innovaciones, centradas en la optimización y flexibilidad, impactan directamente en la experiencia diaria de los desarrolladores. En próximas publicaciones, exploraremos a fondo cómo estas tendencias están marcando el rumbo del desarrollo de software y mejorando las capacidades de .Net y C#.

Fernando Sonego

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *