Category Archives: Ingeniería del Software

Configurar Git (BitBucket) en Visual Studio 2010 y no morir en el intento

 

Que Git se ha convertido en el más famoso y mejor controlador de versiones de código es una cosa que ya sabéis pero, ¿cómo puedo configurar las herramientas necesarias para poder trabajar con un repositorio Git en mi Visual Studio 2010?

El objetivo de este pequeño tutorial es conseguirlo sin morir en el intento

Nota: Este tutorial no explica el funcionamiento de un control de versiones por lo que doy por supuesto que todo el mundo sabe lo que es un commit, push, pull, branch, etc… Otro día haré un artículo dedicado a explicar más a fondo como funciona un control de versiones :)

 

¿BitBucket o GitHub?

¡Para empezar! Necesitamos una cuenta en algún servicio de repositorio de Git (si no dispones de uno local o el de tu empresa).

Actualmente existen dos grandes servicios gratuitos de Git que son GitHub y BitBucket. No voy a entrar a discutir cual es mejor en este artículo, solo diré que BitBucket te permite tener, de forma gratuita, repositorios privados lo cual es perfecto para esas pequeñas aplicaciones que tienes en casa y quieres salvaguardar.

Es por este motivo principalmente por lo que yo uso BitBucket como Source Control :)

 

¿Ya tienes cuenta en BitBucket? ¡Descarguemos Git!

 

Descargando y Configurando Git para Windows

Bien, lo primero que necesitamos es descargar Git para Windows el cual podemos encontrar aquí: http://code.google.com/p/msysgit/downloads/list

Descarga e instala la última versión disponible.

 

No hay que modificar casi nada durante el proceso de instalación. La única opción que recomiendo modificar es la de “Adjusing your PATH environment” la cual aconsejo cambiar de “Use Git Bash only” a “Run git from the Windows Command Prompt” tal y como se ve en la siguiente captura:

 

El resto lo puedes dejar igual.

 

¡Bien! ¡Ya lo tenemos instalado! Ahora tenemos que configurarlo para que funcione con nuestra cuenta de BitBucktet.

Para ello ejecutamos el “Git Bash” (si, es una consola, no te asustes, jeje) e introducimos la configuración global de nuestro usuario de BitBucket e Email escribiendo:

git config --global user.name "tu usuario de BitBucket aquí"

git config --globla user.email "tu email de BitBucket aquí"

 

Con esto ya lo tenemos!

Ahora vamos a configurar las herramientas en el Visual Studio 2010.

Configurando Git en Visual Studio 2010

Debido a que Visual Studio no incluye Git como control de código por defecto (solo incluye SourceSafe y Team Foundation Server) necesitamos instalar una pequeña extensión de Git para que funcione.
Para ello vamos a “Tools > Extension Manager” o “Herramientas > Administrador de Extensiones” en castellano y, en la Galería Online buscamos “Git” para instalar el “Git Source Control Provider“:

Una vez instalado lo escogemos como Source Control por defecto en “Herramientas > Opciones > Source Control > Selección de Complemento > Git Source Control Provider”

 

Lo próximo que debemos hacer es abrir (o crear) la solución que queremos subir a BitBucket y, pulsando botón derecho sobre el nombre de la solución clickamos en “New Repository“.

Esto creará un nuevo repositorio Git en el mismo directorio en el que está la solución.

Verás que en el “Solution Explorer” aparecen unos símbolos con un “+” amarillo. Esto indica que el fichero es nuevo y no se encuentra en tu repositorio local.

Haciendo click derecho de nuevo sobre la solución y pulsando en “Pending Changes” podremos ver el listado de ficheros pendientes, escribir un comentario y hacer el primer commit contra tu repositorio local.

¡Ya está! ¡Ya tenemos configurado Git para Visual Studio! Eso si, de momento solo lo deja en local y BitBucket ni lo hemos usado.

¿Qué toca ahora? Configurar Git Bash para que suba nuestros commits a BitBucket.

 

Configurar Remote y hacer Push desde Visual Studio a BitBucket

De nuevo botón derecho en la solución > Pending Changes > Git Bash y se nos abrirá la consola de Git. Ahora tenemos que configurar el acceso remoto.

Para ello escribimos lo siguiente:

git remote add origin https://usuario@bitbucket.org/nombre_del_repositorio.git

Supongamos que mi usuario es “vfportero” y mi repositorio en BitBucket se llama “demo”. El remote sería así:

git remote add origin https://vfportero@bitbucket.org/demo.git

 

¡Perfecto! Con esto ya podemos escribir: 

git push

Nos pedirá el password de BitBucket y, una vez escrito, y el bash solito se encargará de subir los ficheros al repositorio remoto :)

 

Espero que os haya servido de ayuda.

¡Nos vemos Compilando!

TDD: Un ejemplo práctico sobre como mejorar la calidad de tu código

 

Ultimamente se habla mucho de diseño ágil pero la realidad de muchas empresas de desarrollo dista mucho de implementarlo de forma eficiente o directamente de usarlo en cualquiera de sus aspectos

Y es que el agilismo es una metodología muy fácil de entender pero costosa de poner en práctica si no se hace de la manera adecuada.

Por ese mismo motivo he visto que sería interesante dedicar una entrada a explicar de forma práctica y sencilla qué es TDD y cómo se utiliza en un proyecto.

 

Lo primero de todo confesar que no soy un experto en la materia y por ello es de obligada necesidad indicar que, si quereis profundizar más en estos temas, vayais a la web www.dirigidoportests.com de Carlos Blé, autor de “Diseño Ágil con TDD” el libro de cabecera de todo aquel desarrollador que quiera empezar a trabajar con esta metodología.

Además dar las gracias encarecidamente a Javier Casal por darme las clases magistrales de TDD y la gente de 12Meses12Katas por el ejemplo práctico para compartir con todos vosotros :)

 

¿Qué es TDD (Test Driven Development)?

El diseño dirigido por test, o TDD, es una técnica de diseño e implementación de software consistente en generar las pruebas unitarias justas y necesarias para obtener la implementación de las funciones que el cliente necesita minimizando los errores que llegan a producción.

El diseño por test no solo nos ahorra implementar más de lo debido si no que nos informa de si un cambio posterior “rompe” algo de lo que ya hemos implementado y nos facilita la tarea de entregar un código más limpio y libre de errores.

TDD no se trata de escribir cientos y cientos de pruebas si no se escribir las que necesites (y cuanto más simples mejor) para cumplir las necesidades del cliente y poder, posteriormente, empezar a desarrollar para cumplir dichos requisitos.

 

Como indico en el título esto es un ejemplo práctico sobre como utilizar TDD para resolver un problema concreto por lo que he hecho uso del problema de Noviembre del 2011 de 12Meses12Katas para ilustrar este post: KataPotter

Para ello vamos a crear una biblioteca de clases C# en Visual Studio 2010 y usaremos el framework de pruebas NUnit.

 

Explicando el problema

Bien, el problema que se nos plantea es la creación de un programa que calcule el importe de una coleción de libros aplicando un determinado descuento en función de los distintos tipos de libros que compremos. Partiendo de que cada libro tiene un coste de 8€ el cliente nos indica que, si se adquieren dos libros distintos, se aplique un 5% de descuento a ambos libros, un 10% si se compran 3, un 20% para 4 distintos y un 25% para la serie completa de 5 libros.

Otra condición del cliente es que el programa obtenga el precio más económico si hay varias combinaciones posibles de packs.

 

Como entrada recibiremos un array con los códigos de los libros a comprar (de 0 a 4) y como salida obtendremos un valor double.

¡Muy bien! Ya sabemos que tenemos que hacer y que quiere el cliente por lo que vamos a escribir las primeras pruebas.

 

Pruebas Sencillas

Lo primero que debemos hacer es escribir unas pruebas sencillas que implementen los casos más básicos. La primera y más sencilla es que cuando nuestra cesta de compra esté vacia el precio total es 0. En NUnit sería así:

[Test]
public void EmptyBasket()
{
     Assert.AreEqual(0, _bookPriceCalculator.CalculateBasket(new int[] { }));
}

Sin entrar en explicar la sintaxis de NUnit simplemente indicar que esta prueba comprueba que si se le pasa un array vacio el sistema devuelve 0.

¿Cómo resolvemos esta prueba con la menor cantidad de código posible? Muy fácil:

public double CalculateBasket(int[] books)
{
     return 0;
}

¡Exacto! Esa es la solución más sencilla que hace que la prueba sea correcta. Obviamente en cuanto añadamos una segunda prueba tendremos que rehacer nuestro código pero de esto se trata TDD.

¡Ok! Vamos ha añadir una nueva prueba para indicar una nueva condición impuesta por el cliente: Cada libro vale 8€

[Test]
public void TwoSameBook()
{
     Assert.AreEqual(8 * 2, _bookPriceCalculator.CalculateBasket(new int[] { 0, 0 }));
}

En esta prueba indicamos que si se compran dos veces el libro “0” el precio total es de 16€. ¿Cómo modificamos nuestro método para que pase las dos pruebas?

public double CalculateBasket(int[] books)
{
     return books.Length * 8;
}

¡Vale! No es muy elegante pero solucionaría cualquier prueba que no implique un descuento por lo que podemos cerrar el capítulo de pruebas sencillas.

 

Añadiendo Funcionalidad: Calculando Descuentos

Nuestro cliente nos había puesto como premisa que, si se compraban dos o más libros distintos había que aplicar un descuento determinado por lo que vamos a crear una serie de pruebas de ejemplo que implementen esta funcionalidad:

[Test]
public void TwoDifferentBooks()
{
            Assert.AreEqual(8 * 2 * 0.95, _bookPriceCalculator.CalculateBasket(new int[] { 0, 1 }));
}

[Test]
public void SeveralDiscountsTwo_One()
{
            Assert.AreEqual(8 + (8 * 2 * 0.95), _bookPriceCalculator.CalculateBasket(new int[] { 0, 0, 1 }));
}

Como veis en las pruebas tan solo declaramos una entrada de datos y la solución que nuestro cliente espera. Es trabajo del desarrollador el encontrar el modo en que el código del programa satisfaga todas las nuevas pruebas sin “romper” ninguna de las anteriores ya implementadas.

La solución que se me ha ocurrido a mi es hacer una clase “BookPack” que simbolice un “paquete de libros” donde todos los libros deben de ser distintos por lo que cada compra se traduce realmente en varios “BookPacks” cada uno con su precio y descuento.

Sin tener en cuenta la última condición (que indicaba que se ha de escoger la combinación más económica), la solución más sencilla es esta:

List<BookPack> BookPacks = new List<BookPack>();

foreach (int bookCode in books)
{
     BookPack currentBookPack = null;
     
     foreach (var bookPack in BookPacks)
     {
          if (!bookPack.HasThisBook(bookCode))
          {
              currentBookPack = bookPack;          
          }
     }

     if (currentBookPack == null)
            {
                BookPacks.Add(new BookPack(bookCode));
            }
            else
            {
                currentBookPack .Books.Add(bookCode);
            }
}
return BookPacks.Sum(bookPack => BookPack.GetBookPackPrice(bookPack.Books.Count));

Donde “GetBookPackPrice” devuelve el precio del paquete en función de cuantos libros tiene:

public static double GetBookPackPrice(int quantity)
        {
            return 8 * quantity * GetDiscountPerDifferentBooks(quantity);
        }
//GetDiscountPerDifferentBooks devuelve 1, 0.95, 0.9, 0.8 o 0.75 en función de si se compran 1, 2, 3, 4 o 5 libros distintos respectivamente.

Con esto ya tenemos implementada tanto la funcionalidad básica (ningún libro o varios libros iguales) como el descuento básico por “paquetes de libros”. Sólo nos faltaría añadir la última condición del cliente: que se elija la combinación más económica a la hora de hacer los paquetes.

 

Pruebas Finales: Obteniendo el paquete más económico

No es lo mismo hacer dos paquetes de 4 libros (51.2€ en total) que 1 de 5 y otro de 3 (51.6€). Con el código anterior obtendríamos la opción más desfavorable ya que solo se crea un nuevo paquete cuando el libro actual ya se encuentra en el paquete actual y no se tiene en cuenta el importe final.

Para añadir esta nueva funcionalidad vamos a escribir la última prueba:

[Test]
        public void SeveralDiscountsFourFour()
        {
            Assert.AreEqual(2 * (8 * 4 * 0.8), _bookPriceCalculator.CalculateBasket(new int[] { 0, 0, 1, 1, 2, 2, 3, 4 }));
        }

La implementación para este caso consiste en cambiar el concepto “CurrentBookPack” que tan solo va rellenando paquetes por “CheapestBookPack” el cual compara entre los distintos paquetes y se queda con el más económico.

Como el código resultante ya es más largo y enrevesado como para ponerlo en un post mejor lo veis directamente en mi repositorio de GitHub para este ejemplo ;-):

https://github.com/vfportero/Noviembre-KataPotter/tree/master/vfportero

 

Conclusiones Finales

Creo que este es un gran ejemplo para explicar las virtudes de TDD ya que en un mismo proyecto hemos tenido que hacer 3 modificaciones que han alterado por completo el funcionamiento de la aplicación

Al principio solo teníamos que calcular importes sencillos (8 * unidades), después se añadió unos descuentos por volumen para terminar con un sistema más inteligente que se queda con la combinación más económica.

Ahora extrapola este ejemplo a un proyecto real con cientos de clases y miles de líneas y piensa que pasaría si tuvieras que hacer este tipo de cambios… asusta, ¿verdad?

Y es que ¿cuantas veces hemos “arreglado algo y roto otro cosa”? ¿cuantas veces los requerimientos del software cambian y debemos adaptarnos rapidamente a las nuevas necesidades? ¿cuantas veces programamos más de lo debido?

 

TDD ayuda a solucionar estos problemas facilitandote el modo en el que organizas tus tareas. Cuando programas primero una prueba estás abstrayendote de algoritmos y estrategias para centrarte en entender el problema y la solución exacta que quiere el cliente.

Si logras crear pruebas simples que explican una pequeña parte del código podrás tener un sistema casi perfecto cuando el producto se entregue además de ganar en flexibilidad en caso de los requerimientos cambien en medio del desarrollo.

 

Está claro que escribir pruebas antes de programar es un trabajo extra que en muchos casos no se puede asumir pero, a la larga, ahorra mucho tiempo en mantenimiento y evita problemas de código heredado.

 

TDD, como otras herramientas dentro del agilismo, solo te da una serie de “buenas practicas” que te ayudan a mejorar tu calidad como desarrollador. Está en tu mano decidir hasta que punto utilizar TDD :-)

 

Para terminar solo invitar a todos aquellos interesados en este tema a que se pasen por la web de 12Meses12Katas donde encontraran ejemplos y soluciones a problemas como este “KataPotter” que hemos explicado aquí. Os recomiendo que os junteis con ese amigo programador con el que siempre haceis el friki, compreis una caja de cervezas, y empeceis a trabajar con una de estas Katas en parejas.

Mientras uno programa una prueba el otro programa el código que la implementa y viceversa. Vereis como TDD se ve de otra manera 😉

 

¡Nos vemos Compilando!

Arquitectura MVC, ¿como puede mejorar mi aplicación?

Y es que ultimamente hemos oido mucho hablar sobre MVC pero, ¿qué es realmente y para que se usa? Empecemos desde el principio:

 

MVC son las siglas de Model-View-Controller (Modelo-Vista-Controlador) y es un patrón de la arquitectura del software descrito en 1979 por el Noruego Trygve Reenskaug.

 

El punto principal de MVC es dividir la aplicación en tres capas reales, una para datos, otra para la lógica y otra para la presentación consiguiendo que sea mantenible, escalable y reutilizable.

Para explicar en qué consiste y como funciona vamos a utilizar como ejemplo una hipotética aplicación web .NET que accede a una base de datos SQL SERVER a la que aplicamos este patrón.

  • El “Modelo“, o capa de datos, es el conjunto de clases que representan la información con la que vamos a trabajar y su lógica de negocio. En nuestro ejemplo serían las clases en las que consultamos a la base de datos SQL SERVER mediante, por ejemplo. modelos de Entity Framework.
  • La “Vista“, o capa de presentación, define el modo en el que el usuario ve los datos y como interactúa con ellos. Una página HTML con formularios sería un ejemplo claro de este tipo de capa.
  • El “Controlador“, o capa de lógica, es la que gestiona las peticiones de la Vista solicitando los datos necesarios al Modelo y adaptándolos para su correcta visualización. En .NET serían métodos que actuan como respuesta a un POST de un formulario HTML, captura los datos que el usuario ha introducido y solicita lo necesario al Modelo para retroalimentar la Vista.

 

 

Para terminar de explicar el funcionamiento vamos a platear un formulario de Login en nuestra web de ejemplo.

La Vista sería la página HTML con un <form> con dos <input> uno para el usuario y otro para la contraseña.

Al hacer submit del formulario la petición iría al Controlador que recupera esos datos y solicita al Modelo que busque si el usuario/contraseña introducidos son válidos.

El Modelo realiza la consulta a base de datos y le devuelve el resultado al Controlador que es el que determina si el intento de Login ha sido correcto o no. En caso de ser correcto iniciamos sesión en el sistema y redirijimos a una página de incio del usuario (por ejemplo), en caso de ser erroneo volvemos a la misma vista pero indicando un mensaje de error y el sistema vuelve al punto inicial en el que se espera una acción por parte del usuario.

 

Ventajas de usar MVC

 

  • Escalabilidad

La principal ventaja de separar la aplicación en tres capas reales es la escalabilidad.

Un par de ejemplos: bastaría con recargar el modelo si añades o editas una tabla o crear una nueva vista si quieres hacer una versión para navegador de dispositivo móvil.

  • Simplicidad

Otra gran ventaja es la simplicidad con la que se puede gestionar y mantener el sistema así como la posibilidad de trabajar en paralelo. Puedes tener a diseñadores trabajando en las vistas mientras que los desarrolladores se pueden centrar en el Controlador y el Modelo. ¿Qué quieres cambiar el diseño de la web? Tan solo edita el HTML y la aplicación seguirá funcionando.

  • Desarollo mediante TDD

Al tener la lógica separada de la interfaz es mucho más sencillo crear las pruebas unitarias y desarrollar mediante TDD (Test Driven Development). Sobre esto último dedicaré un artículo más adelante.

  • Rapidez y limpieza de código.

No hay ViewState, ni HTML autogenerado por controles, ni mantenimiento de estado en el código. Lo que interpreta el navegador es exactamente lo que hemos escrito. Eso hace que la página sea más ligera y cargue en menos tiempo.

  • Facilidad para el uso de jQuery

Al tener en la Vista código HTML directamente podemos integrar controles jQuery de forma más sencilla que en WebForms.

 

Conclusiones: ¿WebForms o MVC?

Como habeis podido comprobar en este punto las ventajas de usar este patrón son muchas pero no es oro todo lo que reluce.

MVC es una arquitectura muy compleja que requiere una abstracción mayor por parte del desarrollador que hace que el desarrollo sea más lento por eso solo es recomendable usarlo en ciertos tipos de proyectos.

Si lo que necesitas es hacer un prototipo o RAD, entonces utiliza WebForms.

Si necesitas que la página almacene datos y no quieres estar continuamente haciendo peticiones a la capa de persistencia, entonces utiliza WebForms.

Si tu equipo de desarrollo es pequeño y no trabajais con TDD, entonces utiliza WebForms.

 

En cambio, si tu equipo está segmentado en Diseñadores y Desarrolladores, dispones de conocimientos avanzados de JavaScript y Ajax y necesitas tener un control total del código generado MVC es el patrón que debes utilizar. Si además es un proyecto de cierta embergadura, necesitais controlar mediante pruebas unitarias y va cambiando/ampliandose de forma constante MVC es la solución.

 

Nos vemos Compilando!!