.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: abuso de AppSettings

Toda aplicación .Net cuenta con un archivo xml de configuración. Dicho archivo tiene un conjunto de secciones predefinidas entre las que se encuentra la sección AppSettings que permite definir parámetros de configuración del tipo clave-valor.

Considero que este mecanismo resulta muy útil y apropiado para cuando uno tiene que manejar un set reducido de entradas en esta sección. Sin embargo me he cruzado con aplicaciones con más de 10 entradas en appsettings. Más aún, en alguna ocasión que me cruzado con aplicaciones con ¡más de 50 appSettings!. El problema que veo con esto es que cuando uno cuenta con tal cantidad de parámetros de configuración, es muy posible que dichos parámetros tengan cierta relación/estructura, la cual no es posible reflejar usando el mecanismo de AppSettings. Para estos casos resulta mucho más conveniente en mi opinión utilizar el mecanismo de extensión de configuración que ofrece .Net definiendo secciones personalizadas.

Este breve artículo de MSDN explica de forma muy concreta cómo hacer uso de este mecanismo. Personalmente no suelo usarlo porque en mis proyectos generalmente uso algún inyector de dependencias y hago uso de las funcionalidades del inyector para precisamente inyectar los parámetros de configuración.

.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.

Nuevo proyecto: de regreso a .Net

Nuevo proyecto: de regreso a .Net

Hace un par de semanas comencé un nuevo proyecto, esta vez con tecnología .Net y con un contexto interesante:

  • El proyecto es de desarrollo y mantenimiento evolutivo de un sistema existente
  • El sistema está compuesto por un conjunto de aplicaciones de distinto tipo
  • El sistema lleva varios años en producción y no tiene ningún tipo de pruebas automatizadas
  • La documentación funcional y técnica es escasa (prácticamente nula)
  • Varias de las bases de datos no tienen claves foráneas
  • El sistema escala en forma vertical y no horizontal

En este contexto voy estar colaborando en cuestiones de arquitectura, operaciones y prácticas técnicas de desarrollo.

Continuará…

Setting up a .net build server without Visual Studio

Usually setting up a build server is a very straight forward task but not always. In case you want to build .Net applications it could be a non-trivial task because of the tight coupling of the different build tools with Visual Studio. A simplified way of dealing with this complexity is to install Visual Studio in the build server. I took that approach in the past and I didn’t want to go that way again. I don’t want Visual Studio in the build server.

In a previous post I described the approach I took to simplified the setup of the different build tools I want to integration in my build process. But that approach does not work if you don’t have Visual Studio, FxCop will not work and at the same time you will get lot of warning messages because of missing dependencies. So here is what I have to do:

  1. Get a machine with Windows Server 2012 R2
  2. Install .Net SDK 4.5.2
  3. Install Microsoft Build Tools 2015
  4. Install Windows 7 SDK and .Net 4 SDK (not the whole package but only Reference Assemblies)
  5. Install .Net 3 assemblies (it can be installed by using the Add feature option in windows, so you don’t need any additional download)

With all this stuff installed in your server, then you can use the approach I described previously and just use your build server to trigger MSBuild to take care of running all your build tasks.

Integrating .Net Build tools: MSBuild, NuGet, FxCop, StyleCop and NUnit

These days it is very common to have a continuous build process that includes: compilation, code analysis and automated tests. The way of implementing this kind of process varies depending on the technology of the project.

I have worked with Ruby, Python, Java, JavaScript, Smalltalk and some other languages and in all cases you just need to install 3 tools:

  • the runtime/sdk (like ruby, jdk, cog)
  • a package manager (like bundle, maven, pip, metacello)
  • a build tool (like rake, maven, fabric)

Any other thing you may need (linter, testing framework, etc), you can get it using the package manager and make it run as part of your build script.

But in .Net the situation is more complex. First of all everything seems to be very tight to Visual Studio (the IDE). Because of this, many people just install the Visual Studio in the build server.

Additionally to this the .Net SDK does not provide a test framework. You can use NUnit (which you will have to install manually) or you can use MSTest but to use it you need to install Visual Studio.

FxCop (the linter) comes with Visual Studio but if you don’t want Visual Studio, then you have to install it manually.

So, in order to avoid several manual tasks when setting up a new dev box and also to minimize any possible difference between dev boxes and the build server box I did the following:

  • I downloaded all the tools I wanted to use in my build process and placed them into the same directory (c:\BuildTools).
  • I wrote a build script (using MSBuild and defining my own targets). This script «glues» the invocation to all of these tools: NuGet, FxCop, StyleCop and NUnit.
  • Finally I package all these stuff in a self-extracting .zip file so all the team members can easily replicate my setup.

In order to have the build process to run continuously I also installed this package in the Jenkins build server.

buildtools-v4buildtools-layout

Visual Studio 2013, esas cosas tan típicas de Microsoft

La semana pasada empecé a trabajar en un nuevo proyecto. Algo en teoría simple, un sitio web de tipo «informativo», en el sentido que tiene mucha información y muy poca lógica de negocio. El líder técnico del cliente decidió que lo hicieramos con ASP.NET MVC 4, corriendo sobre .Net 4.5 y utilizando Visual Studio 2013 como entorno de desarrollo.

Cómo era de esperar a la hora de instalar Visual Studio 2013 me encontré con varias cuestiones que podrían resultar difíciles de creer para muchos desarrolladores, pero que no sorprenden a nadie que haya trabajado con tecnología Microsoft por un par de años.

La primera cuestión llamativa fue que apenas ejecuté el instalador, me encontré con un mensaje indicando que la aplicación a instalar (VS2013) no era compatible con mi sistema operativo (Windows 7). Me ví obligado a instalar el Service Pack 1 de Windows 7.

Una vez instalado el SP1, volví a ejecutar el instalador y me encontré con un mensaje que me indicaba que la instalación requeriría ~9 GB, si si, NUEVE GIGABYTES. Lo curioso es que yo estaba intentando instalar esta aplicación en una máquina virtual cuyo peso en ese momento era de unos 8 GB.
Como me costaba resignarme a que mi máquina virtual creciera tanto, hice una instalación personalizada en la que removí ciertos componentes que no eran de mi interés y logré bajar de 9 GB a 7 GB.

Continuando con la instalación, me encontré con otro mensaje que me indicaba que mi máquina no contaba con Internet Explorer 10 y que ello podría ocasionar que algunas funcionalidades de Visual Studio no estuvieran disponibles. Así que suspendí la instalación de Visual Studio e instalé la nueva versión de Internet Explorer.

Finalmente pude completar la instalación de Visual Studio 2013.

Crónicas de mi regreso a .net

Como mencioné hace un tiempo, he vuelto a desarrollar código con tecnología .net después de casi 2 años.

El proyecto en cuestión consiste principalmente en mantenimiento evolutivo de una aplicación desarrollada inicialmente en 2009 con Visual Studio 2008 y varios complementos como: AjaxControlToolkit, Web Service Enhancements 3.0, Crystal Reports y Enterprise Library 3 entre otros.  Un detalle no menor es que la aplicación ha estado congelada funcional y técnicamente desde 2010, por lo que los mencionados componentes siguen aún en uso.

La aplicación consiste en un producto ofrecido como servicio y que se encuentra actualmente en funcionamiento. La empresa que desarrolló este producto/servicio fue adquirida por otro empresa más grande y a partir de esto el nuevo dueño de producto ha decidido potenciar este producto/servicio, lo cual requiere el desarrollo algunas nuevas funcionalidades y la modificación de algunas otras ya existentes.

Como parte de mi backlog de trabajo estan como puntos más prioritarios:

  1. Armar la infraestructura de integración continua y despliegue automático, de cara poder liberar funcionalidad de forma frecuente.
  2. Implementar una nueva funcionalidad estratégica para el negocio.
  3. Actualizar la solución a net 4.5 y refactorizar algunos componentes.

Respecto a (1) he logrado interesantes avances que compartí hace un tiempo en un screencast.

Respecto a (2), la funcionalidad está aún en desarrollo y me resultó muy interesante pues tuve la chance de experimentar con algunas técnicas y herramientas para trabajo con código legacy (ah, si me olvidé de mencionarlo, la solución casi no tiene test automatizados).

Sin duda una de las cosas que más interesante me resultó fue el uso de Dapper para facilitar el acceso a la base de datos. Resulta que el acceso a la base de datos estaba hecho de manera cuasi ad-hoc utilizando Ado.net, datasets y store procedures, artefactos que no me resultan para nada felices. Sumado al hecho de que la última vez que escribí SQL a mano fue en 2005, desde entonces siempre he utilizado algún tipo de ORM para todas las operaciones tipo CRUD. Esta herramienta Dapper es muy simple, básicamente provee un conjunto de métodos de extensión sobre la clase DBConnection que facilitan el mapeo de objetos. No me animo a calificarlo como ORM, pues carece de ciertas funcionalidades como lazy loading y cache, pero más allá de eso creo que es una alternativa muy interesante cuando uno tiene que trabajar sobre una base de datos ya existente. Prometo dedicar otro artículo para contar más detalles sobre Dapper.

Por otro lado, si bien utilicé la técnica de inyección de dependencias, no utilicé ningún framework para ello, pues en el contexto de la funcionalidad que desarrollé introducir un nuevo framework era más complejo que  resolver la inyección de forma manual.