Saltar al contenido

Blog técnico | .NET Core: Lo bueno, lo malo y lo feo

El verano pasado, convertimos uno de nuestros servicios web de producción de WebApi2 a .NET Core. Fue un proceso bastante complicado y terminó llevándonos unos meses. Como era la primera vez que creábamos una dependencia de producción en .NET Core, nos movimos muy deliberadamente, tomándonos un tiempo extra para asegurarnos de que teníamos muchas pruebas y monitorización en marcha. Como resultado de ese aprendizaje, cuando hicimos la transición de un segundo servicio web a .NET Core en enero, sólo nos llevó alrededor de una semana.ya que la diferencia entre esas dos líneas de tiempo es significativa, especialmente al tratar de vender el cambio a la gestión, decidimos escribir este post para ayudar a preservar y compartir lo que aprendimos.

En este primer post, resumiré nuestros hallazgos sobre la plataforma en sí misma, dónde brilla, dónde se cae y las pequeñas peculiaridades que le dan “carácter”. Seguiremos con posts que abordan algunos de los obstáculos técnicos por los que pasamos al convertir nuestra aplicación, así como algunas ideas que obtuvimos al pasar nuestra primera aplicación a producción.

Blog técnico | .NET Core: Lo bueno, lo malo y lo feo
Blog técnico | .NET Core: Lo bueno, lo malo y lo feo

El bueno

.NET Core tuvo una batalla cuesta arriba, teniendo que lidiar con competidores rápidos y adaptables como Node.JS por un lado, y 15 años de estabilidad y características en ASP.NET por el otro. Hizo un montón de promesas (¡plataforma cruzada! ¡ligero! ¡rápido!) para ayudar a convencer a los desarrolladores de que vinieran. En su mayor parte, ha cumplido esas promesas por nosotros. Hablemos de algunas de las mayores mejoras que hemos visto con .NET Core a medida que hemos desplegado y ejecutado varios sitios web.

Plataforma cruzada

En primer lugar, quiero dejar absolutamente claro que creo que la decisión de ejecutar un sitio web en Windows y IIS está bien .Sí, IIS es probablemente más pesado de lo que realmente necesitas, y ciertamente tiene un montón de características que no quieres. También es cierto que la licencia para ejecutar Windows es marginalmente mayor que el costo de ejecutar un servidor Linux equivalente, asumiendo que no necesita soporte técnico.por otro lado, la diferencia de costo es casi seguro menor que el costo de desarrollo de su software, y Microsoft tiene un excelente historial de soporte de productos durante años .

Sin embargo, en el sitio apoyamos una amplia variedad de soluciones tecnológicas diferentes, lo que permite a los diferentes equipos tomar decisiones de forma independiente. Dados los lenguajes y marcos que apoyamos, nuestro sistema operativo más común en producción es Linux, y la administración de Windows es lo suficientemente diferente como para que básicamente tengamos que construir dos conjuntos de herramientas diferentes. Por lo general estamos dispuestos a pagar ese costo, pero es emocionante cuando podemos obtener el beneficio de permitir que los desarrolladores utilicen herramientas con las que son eficientes, mientras que también estandarizamos el lado operativo de las cosas.ejecutar .NET en Linux significa que podemos utilizar nuestras herramientas estándar para administrar instancias, y aún así aprovechar un lenguaje moderno y estático con un fuerte soporte de librerías.

Este ha sido uno de los puntos fuertes de .NET Core en nuestra experiencia.Aunque nos hemos topado con un par de cosas que son específicas de la plataforma, básicamente todo nuestro código ha sido completamente compatible entre plataformas.Mientras estábamos en el proceso de migración, incluso compilamos en Windows y desplegamos los binarios a Linux (no es que lo recomendemos, pero funcionó!).

Probable

¿Recuerdas aquellos grandes tiempos tratando de probar cosas en ASP.NET, sólo para encontrar que tienes una dependencia de una implementación concreta que está también sellada… Tal vez, como yo, te quebraste y decidiste tratar de usar el objeto real, sólo para encontrar que no hay ni siquiera un constructor público… Estos desafíos y muchos más son cosa del pasado gracias a las decisiones de diseño de .NET Core!

También hay una integración mucho más sencilla con las bibliotecas de pruebas unitarias de terceros con dotnet.tanto NUnit 3 como XUnit están soportadas “out of the box” (las plantillas para crear proyectos se incluyen con la instalación básica de la dotnet sdk).aún mejor, desde .NET Core 2.1, dotnet watch también se incluye con la instalación por defecto, permitiéndote configurar tus pruebas para que se vuelvan a ejecutar automáticamente cada vez que hagas un cambio.si no has probado esto antes, te sorprenderá lo suave que es el ciclo rojo-verde-refactor.

Compuesta

Uno de los principales objetivos del equipo del núcleo de .NET era hacer posible que usted decidiera qué es lo que necesita, y que sólo lo incluyera en su código. También entendieron el deseo de sustituir los componentes que proporcionan por implementaciones alternativas que proporcionen diferentes capacidades. Las interfaces en todas partes y una tubería de solicitud personalizable significan que usted puede incluir sólo lo que necesita, construyendo una tubería de procesamiento rápido y eficiente.

Limpia el equipaje

15 años de mejoras significan que el código que entra en una aplicación moderna de ASP.NET MVC es significativamente diferente del código que entró en una aplicación clásica de ASP.NET. En otros, como muchos de los manejadores de eventos, seguimos atascados en la forma en que funcionaba el C# 1.0.Al descartar algunos de los inevitables falsos inicios que se han producido en la última década y media, el núcleo del .NET permite construir aplicaciones modernas con el conjunto de herramientas completo del C# 7.

El Malo

Programa de liberación

Los ciclos de lanzamiento rápido están muy de moda en este momento.La entrega continua es un objetivo que muchos, incluido el equipo de , aspiran a alcanzar.Al lanzar pronto y a menudo, podemos entregar software de mayor calidad que de otra manera, al tiempo que reducimos el tiempo que se tarda en resolver los problemas de los clientes.Sin embargo, cuando esta misma estrategia se aplica a los marcos, pueden surgir una serie de problemas.

Una de las cosas que tendemos a infravalorar como desarrolladores de software es el código de trabajo.en cada base de código de tamaño incluso moderado, hay código que se ignora.código que permanece durante años, sin ser tocado, haciendo tranquilamente su trabajo.con demasiada frecuencia, nos burlamos de ese código como “legado”, sin entender que es de hecho uno de los más productivos, mejor código para el retorno de la inversión.código que hace lo que necesita sin ninguna interferencia por parte de las personas que “saben mejor”.

Cuando los marcos pasan por las versiones principales cada pocos meses, sin embargo, este tipo de código productivo se convierte en un reto para el soporte. La complejidad involucrada en los marcos hace que las vulnerabilidades sean inevitables, por lo que permanecer en una versión que recibe actualizaciones de seguridad es vital para cualquier aplicación consciente de Internet. Mientras que la promesa del núcleo LTS de al menos 3 años de soporte es mayormente aceptable, se siente como un paso atrás de . NET, que generalmente recibía 5+ años de soporte.La rama actual, con su promesa de sólo 3 meses de soporte, no cumple ni siquiera el mínimo tiempo requerido para que yo lo recomiende para el código de producción.Aunque me encantaría ver que más frameworks adopten ventanas de soporte más largas, parece que lo mejor que podemos hacer es recordar que el Framework no es tu amigo, y mantenerlo detrás de los límites arquitectónicos.

Una de las grandes ventajas de utilizar un lenguaje y un marco de trabajo maduros es el rico conjunto de herramientas que están disponibles para ayudarle a desarrollar y monitorizar aplicaciones. Con el núcleo .NET, aunque no hemos terminado con un conjunto de herramientas de sólo 3 años, hemos perdido un montón de comodidades que están disponibles para . NET Framework.Por ejemplo, usamos NewRelic para monitorear nuestras aplicaciones y servidores de producción.Afortunadamente, NewRelic tiene soporte para .NET Core, incluso mientras se ejecuta en Linux.Desafortunadamente, las herramientas para .NET Core ya no reportan la memoria consumida o el CPU usado por el proceso.

Esa historia, de herramientas que todavía en su mayoría funcionan, pero no tan bien, se ha repetido varias veces a través de nuestra experiencia con el .NET Core. La buena noticia es que las cosas están mejorando, incluso si hay ocasionales errores. Sólo tomará tiempo para que el ecosistema crezca tan robusto y diverso como lo hace actualmente con el .NET Framework.

El Feo

Los paquetes

La componibilidad es un beneficio importante del núcleo de .NET. Desafortunadamente, hay un lado oscuro que está unido a este beneficio – en un intento de dejarte elegir qué cosas incluyes, los paquetes se han vuelto mucho más pequeños.

¿Cuánto más pequeño?

En el metapaquete Microsoft.AspNetCore.App (una herramienta diseñada para ahorrarle la complejidad que conlleva el hecho de que los paquetes sean mucho más pequeños), hay 144 dependencias, sin contar las dependencias transitorias que puedan existir (literalmente. No tengo tiempo de mirar las dependencias transitivas de los 144 paquetes de nuget para ver si están todas contabilizadas).Este tipo de fragmentación introduce dos grandes problemas.

En primer lugar, se hace muy difícil entender de qué depende realmente . Muy poca gente (si es que alguien lo hace) va a utilizar los 144 paquetes incluidos en el metapaquete Microsoft.AspNetCore.App. Su código sólo dependerá de un subconjunto (cuántos de ustedes van a utilizar realmente Microsoft. AspNetCore.Authentication.Twitter, después de todo?).Descubrir lo que realmente necesita de esa lista gigante es casi imposible. Lo que significa que tienes que estar atento a las vulnerabilidades de seguridad y los problemas de rendimiento que aparecen en cualquiera de ese código.

En segundo lugar, los paquetes tan pequeños presentan un problema de descubribilidad real y significativo. Si no puedes encontrar el código que resolvería tu problema, no importa lo bueno que pueda ser ese código. El equipo de .NET Core ha hecho un par de cosas para intentar resolver el problema de descubribilidad. La creación del paquete Microsoft.AspNetCore.App fue parte de ello, reduciendo drásticamente el número de paquetes que realmente necesitas conocer. La otra cosa que han hecho es incluir una riqueza de métodos de extensión, escritos en el espacio de nombres de la clase base.Mientras que esto facilita la descubribilidad si ya has incluido el paquete, descubrir donde se define IApplicationBuilder.UseDeveloperExceptionPage requiere fortaleza, determinación y una buena cantidad de suerte.

Camino de “actualización”

Tirar el equipaje de 15 años de desarrollo ha significado una interfaz más fina y limpia para el .NET Core. La desventaja de esa decisión es que cambiar de ASP.NET a .NET Core requiere efectivamente reescribir las aplicaciones. Efectivamente, cada componente que interactúa con el framework ha cambiado, y necesita ser reemplazado.

Algunos podrían sugerir que .NET Core no es una ruta de actualización de ASP.NET.Es cierto que Microsoft está actualmente soportando tanto ASP.NET como .NET Core, y continúa lanzando nuevas versiones de ambos.Por otra parte, parece poco probable que la situación actual continúe indefinidamente.Especialmente con el anuncio de que .NET Core 3.0 proporcionará soporte para aplicaciones de escritorio, la única suposición razonable es que todo el código de .NET Framework necesitará migrar a .NET Core en algún momento.

Afortunadamente, por .NET Core 2.x, la mayoría de las APIs que es probable que utilices están soportadas bajo .NET Core. Esto significa que el código que no está directamente ligado a ASP (o cualquier marco de trabajo que utilices) es probable que funcione sin una reescritura importante. Hay bastantes cambios que todavía hay que tener cuidado, pero no mucho más que cualquier otra actualización importante.En una próxima entrada hablaré más sobre cómo hemos diseñado nuestro código para aislar los cambios del framework de la lógica de negocio (y por qué es una buena idea, incluso si no vas a cambiar a .NET Core).

Conclusión

En general, hemos estado bastante contentos con el cambio a .NET Core.La promesa de una plataforma cruzada sin problemas C# se ha cumplido en gran medida, y el rendimiento y las herramientas han sido suficientes para nuestras necesidades.Es importante recordar que todas las decisiones vienen con consecuencias, y no todas ellas son beneficios. Esperemos que esta mirada a lo bueno y lo malo de .NET Core pueda ayudarle a entender si ahora es el momento adecuado para migrar para su organización.

Esta es la primera parte de una serie en curso sobre nuestra transición al .NET Core. Se puede encontrar más información en la parte 2 y en la parte 3.

Categorías: técnica