C# 2021: mucha magia y grandes riesgos

Cuanto más veo las nuevas características que están introduciendo C# más «miedito voy sintiendo». Veo algunas características que se anuncian con un espíritu de «mucha funcionalidad con muy poco código«. Un ejemplo de esto es el tweet de ayer de David Fowler.

Cuando veo este tipo de anuncios no puedo evitar recordar los primeros años de .Net cuando ASP.NET WebForms generaba también ilusiones de simplicidad y productividad. En cierto modo la promesa sonaba como «podes hacer aplicaciones web como si fueran aplicaciones desktop y sin tener que aprender de tecnologías web«. Tiempo después descubrimos que el uso de WebForms tal como era promocionado (sin entender bien la web) tenía un conjunto de efectos colaterales que causaron estragos negativos en muchas aplicaciones y dolores de cabeza en muchos programadores.

Por otro lado, esta constante evolución de los lenguajes me resulta molesta y hasta inconveniente. En el caso de C# no bastaba con tener clases, enums, structs, interfaces, etc. que había que agregar records. Entiendo que la intención de gran parte de estos cambios es proveer mejores niveles de abstracción y simplificar el trabajo de programador. Si es así, estoy de acuerdo con la intención pero no comparto la estrategia. Yo personalmente me inclino más por la estrategia de Smalltalk, mantener el lenguaje al mínimo y agregar funcionalidades mediante el agregado de paquetes de clases.

Y ya que estamos, otra cuestión que no me gusta de .Net/C# es que el modelo de ejecución sync/async resulta extremadamente intrusivo, forzando a que las clases de dominio que contienen la lógica de negocio se vean «contaminadas» con elementos del modelo de ejecución (async, await, etc). Entiendo que esto es en favor de una mejor performance en mi opinión no vale la pena. Prefiero mantener el código más limpio y lidiar con el modelo de ejecución a nivel de infraestructura incluso cuando ello conlleve cierta penalidad de performance.

Es por todo esto que muchas veces mi código C# no hace uso de «las magias» recientes del lenguaje/plataforma y confío en que es mucho más claro que sí usara «esas magias».

En fin, C# como lenguaje me gustó mucho desde un comienzo así que solo espero que quienes trabajan en su evolución no lo choquen.

Taller: Tddeando microservicios a kubenertes

Ayer completé el dictado de la primera edición de mi taller «TDD your Microservice from Git to Kubernetes«. El título está en inglés porque efectivamente fue en inglés. Asimismo, si bien en el título dice TDD, el taller es mucho más amplio. Incluye también varias prácticas relacionadas como Configuration Management, Continuous Integration, Design Patterns, Architecture guidance, etc.

Hace un tiempo decidí no dictar más cursos de TDD porque la experiencia me demostró que luego del curso, el salto que debían hacer los participantes entre la «simpleza didáctica» de los ejercicios del curso y su código de trabajo cotidiano era muy difícil de realizar. Luego de analizar el origen de esas dificultades decidí armar este curso que apunta precisamente a trabajar con ejercicios más «de mundo real», lo cual implica lidiar con un proceso de desarrollo en equipo, versionado, integración con otros sistemas e infraestructura, entre otras cuestiones.

Obviamente cubrir todas estas cuestiones en un solo taller resulta muy desafiante, es por ello que el taller está estructurado en varios encuentros. Al mismo tiempo es un taller «avanzado», en el sentido de que requiere que los participantes tengan:

  • experiencia en desarrollo de software en un contexto de industria
  • conocimiento de TDD (al menos conceptualmente)
  • práctica en la automatización de pruebas (al menos de tipo unitario)

Al mismo tiempo, para achicar más el salto entre el taller y los proyectos diarios de los participantes, este taller está basado en tecnologías concretas incorporando también patrones de uso común en dichas tecnologías. Esta versión en particular la hice utilizando C# (netCore),NUnit, Moq, Gitlab y Kubernetes.

En los próximos meses estaré haciendo una edición en castellano. Los interesandos pueden contactarme aquí.

C#: new project, old discussion

Last week I started a new C# project with an existing team that was in charge of the maintenance of an existing application. One of the first things we did was defining the project structure in terms of development tools/frameworks. This is not a trivial discussion in C# because the are always 2 ways of doing things: the Microsoft way and the Community way.

Microsoft way is very straight forward for working with Visual Studio and writing quick (and usually dirty) code. But if you want to build testeable, robust and maintainable solutions, it could be better to stay with the community way.

The community way usually includes open source and community supported tools/frameworks like NUnit and OpenCover. One drawback of the community way is that you have to take care of integration the different tools/frameworks, a concern that is usually already solve when you go with the Microsoft way. As a consequence of this situation I implemented some time ago my BuildTools package.

Last week, when we started the new project I was thinking to use that BuildTools package, but I realized that Visual Studio 2017 has been released recently, so I decided to re-think the strategy in case something has changed.

I after some research I was able to create a MsBuild script to run tests with NUNit and measure coverage with OpenCover. But I was not able to find a nice solution for NuGet, it seems NuGet is now firs-class citizen inside Visual Studio, but the nuget.exe is not part of the Visual Studio, so we still have to install on by hand.

Here is the sample project I am using to document my approach, any feedback is welcomed.

In future articles I will write about the strategy to integrate React and its build stack into the C# solution.

projifm: Estadísticas del primer release

Finalmente la semana pasada salimos a producción. El evento en cierto modo fue muy tranquilo ya que nuestra aplicación estaba instalada y funcionando en el ambiente productivo desde hacía varias semanas.
Comparto aquí algunas estadísticas:
Estadísticas de proceso
  • 7 iteraciones (2 semanas cada una) con un equipo de 5 ingenieros
  • 6 semanas de trabajo «on-demand» de un ingeniero monitoreando y realizando ajustes menores
  • 313 items de Jira resueltos
Estadísticas de código
(esto números son específicos del nuestra aplicación, pero el equipo también trabajó sobre componentes compartidos con otras aplicaciones que no está considerados aquí)
  • 138 test automatizados
  • 83.5% de cobertura
  • 67 clases (sin contar las clases de tests)
  • 7329 líneas totales de código
  • 4211 líneas de  código productivo (57%)
  • 3118 líneas de código de tests (43%)

Deuda técnica
Al momento de este primer release registramos los siguientes items de deuda técnica:

  • Código duplicado en los tests
  • Dependencias externas desactualizadas
  • Falta de monitoreo más granular de ciertos componentes

.Net: infraestructura de desarrollo & test

Quiero compartir la infraestructura que estamos usando en el proyecto que estoy trabajando en este momento.

Como repositorio de código estamos usando Git, más específicamente GitLab (aunque a pedido del cliente en breve migraremos a BitBucket).  Dado que estamos usando una arquitectura «micro-servicios-like» tenemos un repositorio por cada micro-servicio, más un repositorio general para configuración, más un conjunto de repositorios adicionales para algunas librerías de uso común y finalmente un repositorio para los scripts de operaciones.

Estamos usando Nexus como repositorio de binarios NuGet y Maven, ya que tenemos componentes .Net y Java.

El servidor de integración continua y orquestador de deployments es Jenkins 2. El proceso de Build lo tenemos armado con MSBuild de manera que Jenkins simplemente obtiene el código de Git, dispara MSBuild y genera reportes y notificaciones basados en el resultado del proceso.

Los deployments los hacemos con MSDeploy y los disparamos desde Jenkins.

De esta forma, los componentes comunes compartidos entre distintos micro-servicios están publicados en nuestro NuGet/Nexus y quien necesita utilizarlos simplemente agrega una referencia a nivel binario usando NuGet. Esto nos permite evitar almacenar binarios en Git y al mismo tiempo que nos habilita a que cada parte de la arquitectura pueda ser versionada en forma independiente.

Para la gestión del backlog utilizamos Jira que a su vez lo tenemos integrado con Hiptest para el manejo de los casos de prueba. Personalmente nunca antes había trabajado con Hiptest y algo que me gusta mucho es que se integra con SpecFlow para la definición de los casos de prueba y el registro centralizado del resultado de la ejecución de las pruebas reportado por SpecFlow.

Para comunicarnos tenemos una lista de correo, un Slack y Skype/Hangout para las video conferencias.

pipeline_net

.Net Core: un primer vistazo

El último fin de semana estuve haciendo un par de Katas para familiarizarme con el nuevo stack de herramienta de .Net Core. Lo que aprendí me gustó mucho y para compartirlo hice este breve video introductorio. Espero resulte de utilidad.

Nota: en el video también hice uso de algunas herramientas «extra .net», más concretamente utilicé un generador de código, un Yeoman.

.Net Core: el renacimiento

Hace un par de semanas decidí instalar .Net Core, la más reciente versión de .Net publicada por Microsoft. Me sorprendí muy positivamente. Si bien había leído algunos artículos sobre la idea de este .Net Core, muchas veces la idea y la implementación tienen un delta enorme.

En primer lugar hay que aclarar que .Net Core marca un hito en la evolución de la plataforma .Net por una serie de cuestiones:

  • Es de código abierto (licencia MIT)
  • Es multiplataforma por iniciativa propia de Microsoft en Windows, Linux y MacOS (otras versiones de .Net también corrían en Linux, pero era por el trabajo realizado por la gente de Mono)
  • .Net Core no es el sucesor de .Net 4.5, sino que es una redefinición de la plataforma .Net y por ello su número versión se ha reseteado: .Net Core 1.0

Uno de los cambios que trae .Net Core es una experiencia de usuario totalmente distinta para el programador. Tradicionalmente el programador .Net ha estado «esclavizado» al Visual Studio, un entorno de desarrollo extremadamente pesado y en mi opinión no tan potente (al menos que uno le instale la extensión ReSharper) .Net Core brinda una experiencia de usuario muy parecida a la que típicamente se tiene trabajando con lenguajes de tipado dinámico del tipo Ruby, Python. Esto es: trabajo desde una terminal y codificación con un IDE liviano tipo Sublime, Atom, etc. Sin embargo aquellos que prefieran seguir trabajando con el pesado Visual Studio, también puedo hacerlo.

Al mismo tiempo Microsoft también ha generado un nuevo IDE (muy parecido funcionalmente a Atom y Sublime) que se llama Visual Studio Code. Personalmente la elección del nombre me parece desafortunada pues genera confusión ya que esta herramienta no tiene nada que ver con el famoso Visual Studio. Por ello yo habría optado por un nombre nuevo totalmente desligado de Visual Studio.

Para aquellos que quieran una explicación bastante completa de cómo calza .Net Core en el mundo .Net existente y de la visión de Microsoft a futuro para .Net, les recomiendo leer este excelente artículo de Rick Strahl.

En las próximas semanas iré compartiendo mis experiencias con estas nuevas herramientas.