Archive for the '13620' Category

Coding Dojo – “TDD on the rocks”

Wednesday, March 14th, 2012

Ayer martes 13 de Marzo asistí a la reunión mensual de Agiles Buenos Aires. Fue un coding dojo sobre TDD, dirigido por el bueno de @HernanWilkinson. Pueden ver la descripción del evento en:

http://www.meetup.com/agiles-bsas/events/55342802/

En la reunión de marzo, Hernan Wilkinson facilitará un coding dojo en el que se trabajará sobre un ejercicio de programación para practicar diseño orientado a objetos y la utilización de TDD.

La idea es que todos podamos participar, por lo que usaremos la técnica de Coding Dojo, estilo Randori.

Venite preparado con tu laptop, con las baterias bien cargadas, con tu lenguaje preferido (Java, C#, Ruby, Smalltalk, etc.) y con muchas ganas de discutir, aprender y pasarla bien.

Fue una muy interesante reunión, donde aprendimos de TDD, pasos, refactoring, etc. Y hubo discusiones interesantes.

Hernán armó un coding dojo diferente, escribió en la lista del meetup:

La idea es que haya un proyector donde se ve que están haciendo los que pasan al frente y son dos. Cuando el que está con la computadora termina, toma la computadora el otro y pasa uno nuevo para ser el próximo que toma la posta. Lo único malo que tiene esta modalidad es que a veces la computadora que se usa no es cómoda para todos por el teclado o el lenguaje o ide no lo conocen todos, etc., lo que hace mas lento el desarrollo del ejercicio por eso para contrarrestar este problema es que vamos a hacer un "Randori" customizado :-), que consiste en que todos vayan con su laptop copiando lo que se está mostrando con el proyecto, cada uno con su lenguaje preferido, ide preferido, etc. y que cuando pasan al frente, pasan con su laptop y lo unico que hay que hacer es conectar la laptop al proyector. Además contrarrestar el problema que comenté, tiene la ventaja de que todos van a estar programando realmente y no siguiendo el ejercicio solo con los "ojos" y se va a poder ver cómo va quedando el mismo problema con distintos lenguajes. Se podría decir que la contra es que por ahí uno que sabe Java le costará entender a otro que lo hace en Ruby, pero el problema no es tan complicado como para que la diferencia entre los lenguajes haga difícil entender la solución que se desarrolla en cada uno de ellos. Creo que va a estar muy interesante y si funciona bien después lo patentamos!!

Felicitaciones a la organización (tengo que anotar quienes fueron sponsors), y en particular a Hernán, que supo manejar la sesión, muy interesante, informativa, y divertida. El trabaja en el día a día, con sus equipos, con TDD desde hace 10 años aprox. Así que tiene mucho para transmitirnos, la reunión de ayer fue el principio. Ya tengo pensado incorporar todo lo visto al Proyecto Hogwarts, veremos si tengo tiempo disponible.

Yo estuve desde el comienzo, hasta las 20:30hs, pero siguió la reunión. Asistieron más de veinte personas, muchas que asistían por primera vez a estas reuniones de Agiles@Buenos Aires. Nos repartimos en equipos de dos, para hacer pair-programming. (Uy! No pude anotar el nombre de mi compañero, salí apurado porque tenía que llegar temprano a otro lado). Trabajamos en C#, Visual Studio 2008, en la notebook que uso.

Fue muy interesante ver pasar equipos al frente, y discutir entre todos cuál era el próximo paso a implementar. Hubo gente de Java, C#, Ruby, en distintos sistemas operativos, IDEs y editores.

Hernán nos dió una guía de pasos a seguir (además de los clásicos de TDD: rojo, verde, refactor):

Pasos a seguir:

–Caso más simple “positivo”

–Caso negativo

–Caso concreto distinto

–Más de un caso concreto

–Casos bordes

–Pensar-:)

Hoy, Hernán publicó la presentación en:

http://www.slideshare.net/hernanwilkinson/tdd-on-the-rocks

(en el slide 4 están los pasos que mencioné antes).

El problema planteado fue:

– Calendario de días laborables y no laborables

– Se debe saber si una fecha particular es laborable o no

– Se debe configurar con:

– día de la semana no laboral (ej. Domingo)

– día de mes no laboral (ej. Primero de Enero)

– fecha particular no laboral (ej. 4 de Abril de 2012)

Publiqué lo que hizo mi equipo (hasta que me tuve que ir) en:

https://github.com/ajlopez/TddOnTheRocks

en el directorio Src. Traté de hacer commit por test, pero escribí rápido los comentarios.

Fue un muy interesante ejercicio. Estoy comenzando a escribir en https://github.com/ajlopez/TddOnTheRocks/tree/master/MySrc otro “approach” más alineado con lo que hago habitualmente para poder comparar las diferencias de énfasis en los dos estilos.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

IoC y DI: Hello, world con Spring Framework

Friday, August 13th, 2010

Ya vimos algo de Inversion of Control y Dependency Injection en:

Definiendo Inversion of Control y Dependency Injection
Introducción a IoC y DI: Otro ejemplo web
Introducción a IoC y DI: Un ejemplo web
Introducción a IoC y DI: Hello, world flexible

material producido dentro del Proyecto Hogwarts. En el post donde definía IoC y DI, mencioné la existencia de contenedores de IoC: utilitarios que facilitan el “armado” de los objetos y sus relaciones. En el primer post de la serie, describí el ejemplo más simple posible. Veamos ahora de poder levantar el mismo ejemplo apelando a un contendor de IoC.

Uno de los más conocidos, uno de los primeros, es el Spring Framework de .NET (port de la implementación inicial en Java). Veamos la estructura del ejemplo (que se puede bajar de HelloWorldSpringExample.zip).

 

Vemos que refiere a Spring.Core, una librería que les dejo incluida en el ejemplo. Seguimos teniendo nuestras interfaces IMessageProcessor, IMessageProvider, y nuestras clases concretas MessageProcessor y MessageProvider. Pero nuestro programa ahora ejecuta:

    class Program
    {
        static void Main(string[] args)
        {
            IApplicationContext context = ContextRegistry.GetContext();
            IMessageProcessor processor = (IMessageProcessor)context.GetObject("processor");
            processor.Process();
        }
    }

Spring tendrá a su cargo crear los objetos, a medida que los pedimos. El ContextRegistry es parte de Spring. Levanta información de los objetos que queremos trabajar. Para poder usarlo, tenemos que incluir los namespaces:

using Spring.Context.Support;
using Spring.Context;

En su forma más sencilla, como la de arriba, toma sus datos de la configuración:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="context" 
      type="Spring.Context.Support.ContextHandler, Spring.Core"/>
    </sectionGroup>
  </configSections>
  <spring>
    <context 
      type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
      <resource uri="file://SpringConfig.xml"/>
      <!--<resource uri="assembly://HelloWorld1/HelloWorld1/EmbeddedSpringConfig.xml"/>-->
    </context>
  </spring>
</configuration>

Se definió un nuevo sectionGroup llamado spring, que es leído por la librería. Ahí se puede poner la configuración de nuestro ejemplo, pero elegí referir a un archivo aparte, así podemos cambiarlo sin tocar la configuración general de la aplicación. Vean que dejé comentado otra forma: incluir ese archivo de configuración como recurso embebido. El SpringConfig.xml está marcado en el proyecto como Copy to Output Directory Always.

El archivo SpringConfig.xml tiene:

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns='http://www.springframework.net'>
  <object id='provider' type='HelloWorldSpringExample.MessageProvider'>
    <property name='Message' value='Hello, World'></property>
  </object>
  <object id='processor' type='HelloWorldSpringExample.MessageProcessor'>
    <property name='Provider' ref='provider'/>
  </object>
</objects>

Podemos definir cada objeto, darle:

– un id (nombre)

– un tipo (qué tipo concreto creamos)

– argumentos para su constructor

– valores para sus propiedades

Cuando especificamos un valor podemos poner value=”Hello, world” un valor en concreto, o podemos referir a otro objeto conocido y creable por Spring, usando ref=”provider”.

Entonces, cada objeto lo completamos inyectándole otros objetos via propiedades o argumentos en el constructor.

Notemos la forma en que la propiedad Provider del MessageProcessor es "inyectada": referenciando (atributo ref) a otro objeto que Spring conoce cómo crear.

De esta forma, se pueden levantar grafos de objetos complejos, pidiendo posiblemente uno desde nuestro programa. En este ejemplo, pedimos el objeto con id=processor. Automáticamente, Spring creó el objeto con id=provider, y le inyectó el mensaje que contiene.

Tenemos que ver otro ejemplo de Spring, tener algún ejemplo web, y usar otros contenedores, como Ninject o StructureMap. Y cuando tengamos más experiencia, volveremos a ver qué se consiguió con esto, y qué características tienen los contenedores IoC.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Definiendo Inversion of Control and Dependency Injection

Thursday, August 12th, 2010

Después de algunos ejemplos de código, dentro del Proyecto Hogwarts:

Introducción a IoC y DI: Otro ejemplo web
Introducción a IoC y DI: Un ejemplo web
Introducción a IoC y DI: Hello, world flexible

veamos de definir los términos Inversion of Control (Inversión de Control) y Dependency Injection (Inyección de Dependencias).

Recordemos lo que vimos en los ejemplos: los objetos no funcionan solos, forman un grafo de objetos. Algunos objetos colaboran con otros. Se dice entonces que los objetos consumidores tienen dependencia de los objetos que consumen como ayudantes. En una aplicación real, el mantener las dependencias puede irse complicando, debido a la cantidad de clases y responsabilidades. También, puede que querramos modificar las implementaciones. Vimos que nos conviene ir definiendo interfaces, y referirse a ellas, para no ligar los objetos consumidores a implementaciones concretas.

Inversion of Control refiere, entonces, a que el objeto consumidor no crea los objectos ayudantes, de los que depende. No se le adosa esa responsabilidad. Como vimos en los ejemplos, en esos objetos desaparece el "new" de los objetos ayudantes.

Dependency Injection se refiere a una forma de implementar IoC: el objeto consumidor recibe sus dependencias en propiedades o en argumentos de constructor.

Recordemos el ejemplo de servicio consumiendo repositorio, gráficamente:

El código de nuestro servicio no tenía new (con lo que tiene Inversion of Control). Pero bien podría haber pedido expresamente a otro que le diera el objeto, como en:

public class CustomerService
{
    private ICustomerRepository repository;
    public CustomerService()
    {
        this.repository = Registry.GetInstance<ICustomerRepository>();
    }
    public IEnumerable<Customer> GetCustomers()
    {
        return repository.GetAll();
    }
}

En este caso, sería simplemente Inversion of Control: alguien, la clase Registry, tendría la responsabilidad de ubicar o crear la instancia a usar. Pero CustomerService pide esa resolución explícitamente.

En cambio, el código de nuestro ejemplo era:

public class CustomerService
{
    private ICustomerRepository repository;
    public CustomerService(ICustomerRepository repository)
    {
        this.repository = repository;
    }
    public IEnumerable<Customer> GetCustomers()
    {
        return repository.GetAll();
    }
}

Acá apareció Dependency Injection: CustomerService ni siquiera pide el repositorio, alguien de afuera se lo da. Tenemos que estudiar que podemos usar librerías llamadas contenedores de IoC que nos facilitan la inyección automática de esas dependencias.

No necesariamente se inyecta un solo objeto: otras clases más complejas podrán necesitar de más objetos inyectados. Tenemos que investigar formas de inyectarle esas dependencias. Por ahora, lo vimos “manualmente”: vamos a ver que hay librerías llamadas IoC Containers, contenedores de Inversion of Control, que nos pueden ayudar a armar el grafo que necesitamos en un contexto (en producción, en pruebas TDD, etc…)


Artículos en inglés para consultar con más detalles:


Inversion of Control Containers and the Dependency Injection pattern (Martin Fowler)

Inversion of Control and Dependency Injection: Working with Windsor Container

Mis enlaces sobre el tema:

http://delicious.com/ajlopez/ioc

http://delicious.com/ajlopez/di

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Introducción a IoC y DI: otro ejemplo web

Wednesday, July 28th, 2010

Sigamos explorando Inversion of Control y Dependency Injection, dentro del Proyecto Hogwarts. Anteriores posts del tema:

Introducción a IoC y DI: Un ejemplo web
Introducción a IoC y DI: Hello, world flexible

Simplemente para ver otro ejemplo sencillo de programación con interfaces, veamos de agregar un objeto presenter en un ejemplo web. La forma de llenar la página con datos (dar datos a la vista) y la forma de atender comandos del usuario (un botón de aceptar en un formulario para grabar lo ingresado), lo separamos del "code behind" y le asignamos esa responsabilidad a un objeto Presenter:

Notemos que la vista que va a consumir no es una clase concreta, sino una interfaz. Eso nos va a permitir cambiar la vista, o probar a nuestro objeto presenter sin necesidad de darle una página web para operar, sino algún otro objeto más adecuado para nuestras pruebas.
El código de este ejemplo se puede bajar de PresenterExample.zip.

Esta vez, la solución tiene dos proyectos de librería de clases, y una aplicación web:

 

El primer proyecto se basa en nuestro anterior ejemplo: contiene el servicio, ayudado por repositorios.

El segundo proyecto define la interfaz que tiene que cumplir todas las vistas de lista de Customers, ICustomerListView:

namespace Customers.Presenters {  public interface ICustomerListView
   {
      IEnumerable<Customer> Customers { set; }
   }
}

El Presenter consume tanto a la vista como al servicio:

 public class CustomerPresenter  {
    private ICustomerService service;
    private ICustomerListView view;
    public CustomerPresenter(ICustomerService service, ICustomerListView view)
    {
       this.service = service;
       this.view = view;
    }
    public void Initialize()
    {
      this.view.Customers = this.service.GetCustomers();
    }
 }

Vean que el servicio también lo ve como una interfaz. Finalmente, el código de la página arma todos los objetos y se "conecta" con el Presenter para que éste la maneje. En nuestro ejemplo, sólo para llenar sus datos:

  public partial class _Default : System.Web.UI.Page, ICustomerListView
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                CustomerPresenter presenter = new CustomerPresenter(new CustomerService(new InMemoryCustomerRepository()), this);
                presenter.Initialize();
            }
        }
        public IEnumerable<Customer> Customers
        {
            set
            {
                this.grdCustomers.DataSource = value;
                this.grdCustomers.DataBind();
            }
        }
    }

Este ejemplo es un paso más hacia el tema de esta serie de post: Inversion of Control y Dependency Injection, términos que tenemos que definir. Pero, como en el post anterior, hay algo para mejorar: en el código de la página decidimos qué objetos concretos conectamos en un grafo de objetos colaboradores. Lo que quisiéramos mejorar es la definición de esos objetos concretos: tratar de no tenerlo de alguna forma fijo en el código, sino tener alguna otra manera de instanciarlos y de cambiar cuáles son las clases concretas a usar.

Este material será incluido en el curso online del Southworks Professional Improvement Program en http://pip.southworks.net/ (pueden ir ahí para ir explorando el curso de TDD ya publicado).

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Proyecto Hogwarts: Sitio en línea, Southworks Professional Improvement Program

Friday, July 23rd, 2010

Después de haber publicado varios posts de avance sobre el Proyecto Hogwarts, finalmente pudimos hacer pública la versión beta (yo imagino que en beta constante) del material del curso de introducción a TDD, como parte del como parte del Southworks Professional Improvement Program. Pueden registrarse gratuitamente en:

http://pip.southworks.net/

Tienen lecciones en línea, con código, videos, ejercicios, explicaciones de conceptos, bibliografía, enlaces. Como comentaba al principio, para mí está en beta constante. Si hay algo que no se entiende o no queda claro, tienen un foro para plantear dudas. Si tienen una sugerencia, también puede dejarla ahí.

Está soportado en la plataforma open source de Moodle, con PHP y MySQL.

Tenemos otro curso en desarrollo: Inversion of Control y Dependency Injection (van a ver ahí que está dado de alta, incompleto). Próximos cursos a incluir: Mocks (como una continuación de TDD), principios S.O.L.I.D.

Ayer jueves 22, los buenos de @MartinSalias y @sebarenzi dictaron un taller presencial de TDD con máquinas acá en Buenos Aires, basado en el material del curso. La idea es que cada curso también tiene contrapartida de cursos, talleres presenciales. Esperamos redondear la idea, para organizar cómo darlos en otros lugares. Por ejemplo, ahora estamos probando que un instructor de una empresa, dicte el curso de introducción a TDD en su equipo.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Introducción a IoC y DI: Un ejemplo web

Wednesday, July 21st, 2010

Sigo posteando material de lo que se está produciendo en el Proyecto Hogwarts. Esta vez, sobre el tema de Inversion of Control y Dependency Injection. Dentro de poco, estará disponible un sitio en línea con un curso de TDD, y otros en construcción. En el anterior post:

Introducción a IoC, DI: Hello, world flexible

había planteado un ejemplo simple, veamos alguno apenas más complejo. Y veamos de plantearla con interfaces.

Lo que vimos en ese ejemplo es que:

– Un objeto A puede necesitar la ayuda de otro objeto B, pero conociendo la interface, sin ligarse a una clase en concreto

– Al objeto A alguien le provee el objeto B

Lo que vamos explorar ahora, es un ejemplo donde al objeto A le damos alguna vez un objeto B1, y otras veces el objeto B2. Para que no sea sólo una aplicación de consola, veamos de levantar el alcance, y hagamos un ejemplo web.

Sea una simple aplicación web, donde tenemos una página para presionar dos enlaces para leer y mostrar los clientes:

La idea es tener DOS implementaciones de una interface que se haga responsable de implementar un repositorio de clientes (digamos, una lista de clientes). Si presionamos en el primer enlace, se usará un repositorio en memoria:

 

Si presionamos en el segundo enlace, usaremos el repositorio de base de datos:

Pueden bajarse el ejemplo desde mi Skydrive CustomersExample.zip. Contiene una solución .NET y los scripts para crear la base de datos en SQL Server.

En este ejemplo, vamos a usar un servicio que se ayudará de un repositorio para conseguir los objetos que necesita la presentación. Veamos cómo se implementó.

Tenemos entonces, un servicio que necesita consumir un repositorio. Como en el ejemplo de Hello, world, el objeto consumidor no referencia a una clase concreta, sino a una interfaz:

Esa interfaz está definida como:

namespace Customers
{
 public interface ICustomerRepository
 {
 Customer GetById(int id);
 void Insert(Customer customer);
 void Update(Customer customer);
 void Delete(Customer customer);
 IQueryable<Customer> GetAll();
 }
}

Luego tenemos dos implementaciones de esta interfaz:

Una es la implementación del repositorio en memoria, parte del código:

 public class InMemoryCustomerRepository : ICustomerRepository
 {
 private IList<Customer> customers = new List<Customer>();
 public InMemoryCustomerRepository()
 {
 for (int k = 1; k <= 10; k++)
 {
 customers.Add(new Customer()
 {
 Id = k,
 Name = string.Format("Customer {0}", k),
 Address = string.Format("Address {0}", k),
 Notes = string.Format("Notes {0}", k)
 });
 }
 }
//....
 }

La otra implementación de la interfaz accede a una base de datos, código parcial:

 public class DatabaseCustomerRepository : ICustomerRepository
 {
 private string connectionstring;
 public DatabaseCustomerRepository(string connectionstring)
 {
 this.connectionstring = connectionstring;
 }
 public Customer GetById(int id)
 {
 SqlConnection conn = new SqlConnection(this.connectionstring);
 SqlCommand cmd = new SqlCommand("select Id, Name, Address, Notes from Customer where Id = @Id", conn);
 cmd.Parameters.Add(new SqlParameter("@Id", id));
 conn.Open();
 SqlDataReader reader = cmd.ExecuteReader();
 Customer customer = null;
 if (reader.Read())
 customer = this.GetCustomer(reader);
 reader.Close();
 conn.Close();
 return customer;
 }
///...
 }

Lo que se usó en este ejemplo es que al crear el objeto servicio le pasamos en los argumentos del constructor cuál implementación de repositorio queremos usar. Así, en la acción de ver por memoria, el código es:

protected void lnkMemory_Click(object sender, EventArgs e)
 {
 CustomerService service = new CustomerService(new InMemoryCustomerRepository());
 this.grdCustomers.DataSource = service.GetCustomers();
 this.grdCustomers.DataBind();
 }

La otra opción es por base de datos:

 protected void lnkData_Click(object sender, EventArgs e)
 {
 CustomerService service = new CustomerService(new DatabaseCustomerRepository("server=.\SQLEXPRESS;database=Customers;integrated security=true"));
 this.grdCustomers.DataSource = service.GetCustomers();
 this.grdCustomers.DataBind();
 }

Notemos que al servicio le "inyectamos" su ayudante, esta vez usando un parámetro de su constructor (en el ejemplo Hello World, habiamos inyectado usando propiedades).

Esto nos muestra:

– La capacidad de abstraer lo que necesitamos (la interfaz de repositorio) de cómo lo implementamos

– Nos permite cambiar la implementación y que todo siga funcionando igual

Acá usamos las DOS implementaciones al mismo tiempo. Pero es más común usar solo una.

Podríamos haber codificado el acceso a los clientes en el propio servicio. Pero lo separamos para:

– Poder mejorar el servicio (p.ej., en temas de seguridad) separando esas otras funcionalidades de la más simple de recuperación de clientes.

– Poder cambiar el ayudante, sin necesidad de cambiar el servicio y sus consumidores.

Hasta podemos ir armando una aplicación de demostración, usando durante semanas la implementación del repositorio en memoria. Mientras, en un desarrollo ágil, vamos iterando, mejorando nuestro dominio, SIN tener una base de datos por debajo. El cliente final va viendo nuestro avance, y solamente cuando tenemos algo más definido, vamos definiendo la base de datos subyacente y operando sobre ella.

También, este "approach" nos permite cambiar la implementación de la base de datos. Ahora, la implementación va contra SQL Server, pero si mañana necesitamos ir contra Oracle, cambiamos la implementación, y ni servicio y otros se enteran de ese cambio.

Y por último, veremos, más adelante en otro curso (Mocks con TDD), que podemos usar implementaciones de repositorios que no vayan contra la base, para alivianar nuestros tests del servicio.

Y todo, por haber programado contra la interfaz, y segregado responsabilidades.

Tenemos que avanzar en un sentido: no queremos tener que cambiar el código de creación del servicio, para que una vez use una implementación del repositorio (en memoria) y otra vez use una distinta (en base de datos). Quisiéramos que el cambiar esa relación NO IMPLIQUE tener que cambiar el código. Esa es la idea que subyace en lo que tenemos que definir en los próximos post de este tema: qué es Inversion of Control, qué es Dependency Injection, y contenedores de IoC.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Introducción a IoC y DI: Hello, world, flexible

Tuesday, July 13th, 2010

Dentro del Proyecto Hogwarts, estamos produciendo material para un curso de Inversion of Control y Dependency Injection, que quedará en línea (además de preparar alguna charla o taller presencial). No voy a explicar todavía los términos, sino que quisiera seguir otro camino: tomando la aplicación más simple, ir viendo de flexibilizarla, hasta llegar en algún momento a usar IoC y DI (siglas de los términos en inglés para Inversión de Control e Inyección de Dependencias).

¿Cuál es la aplicación más simple? Tomemos un clásico “Hello, world” en C# (espero publicar más adelante una serie de versiones en Java, que culmine con el uso de Spring Framework, como hago en mis cursos sobre el tema):

 class Program
 {
 static void Main(string[] args)
 {
 Console.WriteLine("Hello, world");
 }
 }

¿Qué podemos querer cambiar de esa aplicación? Se me ocurren dos cosas:

– El mensaje

– La forma de procesarlo

Son dos responsabilidades, que podemos asignarlas a dos clases nuevas, digamos, MessageProvider:

 public class MessageProvider
 {
 public string Message { get; set; }
 }

y a MessageProcessor:

 public class MessageProcessor
 {
 public MessageProvider Provider { get; set; }
 public void Process()
 {
 Console.WriteLine(this.Provider.Message);
 }
 }

Nuestro Hello World puede quedar ahora de esta forma:

 static void Main(string[] args)
 {
 MessageProvider provider = new MessageProvider() { Message = "Hello, World" };
 MessageProcessor processor = new MessageProcessor() { Provider = provider };
 processor.Process();
 }

Vean que creamos los dos objetos de dos clases concretas, y los “conectamos”: como el MessageProcessor necesita de un MessageProvider, se lo proveemos mediante una propiedad (podríamos haberlo hecho mediante un parámetro en el constructor). Lo que estamos haciendo es construir un grafo de objetos, y dada la forma en que colaboran entre ellos, el grafo lo armamos nosotros. La alternativa sería: DENTRO de MessageProcessor crear un MessageProvider y usarlo. Pero eso dejaría acoplada la responsabilidad de cuál mensaje procesar al propio MessageProcessor. De la forma adoptada arriba, si queremos cambiar el mensaje, NO ALTERAMOS el código de MessageProcessor. A este objeto “le llueve del cielo” su colaborador. Vemos la aparición de un camino a seguir: los “new” de los objetos colaboradores, no están en el código de los consumidores de esos colaboradores. Más adelante, pasaremos a ejemplos más de la vida real. Pero por ahora, exploremos estos temas con ejemplo sencillo. Luego, el problema (armar el grafo de objetos) y la solución (lo armamos “por fuera” de los objetos) será la misma, con variantes, en ejemplos medios y complejos.

Próximo paso: ahora que tenemos objetos que se hacen cargo de las responsabilidades que descubrimos, podemos refinar el ejemplo: ahora, MessageProcessor está acoplado a una clase concreta MessageProvider. Pero ¿qué necesita realmente MessageProcessor? En lugar de consumir un objeto de una clase concreta, ahora que tenemos un mini caso de uso codificado, podemos extraer, “descubrir” la interface que necesita consumir MessageProcessor. Y ya que estamos, también extraer, descubrir la interface, la conducta expuesta de cualquier MessageProcessor que se nos ocurra mañana. Pueden hacerlo a mano, o apelar a las capacidades de Refactoring, Extract Interface de Visual Studio. Tenemos IMessageProvider:

 public interface IMessageProvider
 {
 string Message { get; set; }
 }

IMessageProcessor:

 public interface IMessageProcessor
 {
 void Process();
 IMessageProvider Provider { get; set; }
 }

Y nuestras clases ahora implementan y esperan esas interfaces:

 public class MessageProvider : HelloWorldInterfacesExample.IMessageProvider
 {
 public string Message { get; set; }
 }
 public class MessageProcessor : HelloWorldInterfacesExample.IMessageProcessor
 {
 public IMessageProvider Provider { get; set; }
 public void Process()
 {
 Console.WriteLine(this.Provider.Message);
 }
 }

Vemos que MessageProcessor es UNA implementación de IMessageProcessor, y que no espera un MessageProvider, sino que se las arregla con cualquier implementación, actual o futura, de IMessageProvider. Como antes, él no se preocupa de crear esa instancia ayudante, sino que alguien proveerá.

Nuestra invocación queda:

 static void Main(string[] args)
 {
 IMessageProvider provider = new MessageProvider() { Message = "Hello, World" };
 IMessageProcessor processor = new MessageProcessor() { Provider = provider };
 processor.Process();
 }

Por ahora, no parece que ganemos mucho (para este ejemplo simple). Si tenemos que cambiar el proveedor del mensaje, el mensaje, o la forma de procesarlo (por ejemplo, que genere, en lugar de un mensaje en pantalla, otra cosa, como un archivo PDF o una página web), tenemos que tocar el código de nuestra rutina de inicio. Exploraremos cómo, ayudados por algún framework, conseguir que ese armado y esos datos se deleguen a configuración.

Código de los ejemplos en HelloWorldObjectsExample.zip y HelloWorldInterfacesExample.zip

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

TDD: Primeros pasos en Visual Studio

Tuesday, July 6th, 2010

He estado escribiendo algunos posts sobre TDD (Test-Driven Development) relacionados con el curso en preparación del Proyecto Hogwarts. La idea es publicar el material del curso presencial que se está armando en ese proyecto, para que quede en línea en un sitio público. Mientras tanto, sigo adelantando algunos temas por acá.

Recordemos el primer ejemplo, en video:

Un ejemplo de TDD

Quisiera repasar unos simples puntos, en este post. Primero, en ese ejemplo trabajamos con Visual Studio 2008, y con las facilidades de test que tiene ese entorno en una versión Architect. Deberíamos explorar en algún momento de escribir test con otras librerías, y en otros entornos, lenguajes (como Java/Eclipse). En el ejemplo presentado (ver el post, el video, y ahí el código para bajar), se armaron dos proyectos:

 

Uno es un proyecto de librería de clases, y el segundo es un proyecto de test:

 

(Recordemos: no todas las versiones del Visual Studio soportan este tipo de proyecto. Está disponible a partir de la versión Architect. Tendremos que estudiar alternativas de código abierto, como NUnit, que varían en los detalles pero con conceptos similares).

El código que van a ver que se terminó generando en el ejemplo, es:

using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Calculator.Tests
{
 [TestClass]
 public class CalculatorTests
 {
 [TestMethod]
 public void AddTwoNumbers()
 {
 Calculator calculator = new Calculator();
 int result = calculator.Add(2, 3);
 Assert.AreEqual(5, result);
 }
 [TestMethod]
 public void AddManyNumbers()
 {
 Calculator calculator = new Calculator();
 for (int k = 1; k <= 10; k++)
 {
 int j = k + 1;
 int result = calculator.Add(k, j);
 Assert.AreEqual(k + j, result);
 }
 }
 }
}

¿Qué hay para destacar de este código? Primero, el uso de atributos como [TestClass] y [TestMethod]. Estos son los atributos iniciales que estamos utilizando. Tendremos que estudiar otros, y cómo hay atributos similares en otras librerías, como NUnit. Pero ¿qué son estos atributos? Son la forma que tiene este entorno de implementar dos soluciones de frameworks de TDD, a dos problemas: ¿cómo identificar un test? ¿cómo agruparlos?

Lo que usa Visual Studio (y NUnit y otros), es hacer que cada test esté implementado como un método. No es un programa, es un método. Y para ubicar el método y distinguirlo de otros, usamos el atribute [TestMethod].

También este entorno tiene la facilidad de ejecutar un método, o todos los métodos de la solución. Pero también puede ejecutar los tests que están en una clase. Los métodos de tests no están “flotando” en cualquier clase, sino en las que están marcadas con el atributo [TestClass].

En nuestro tercer video:

Ejemplo de TDD: Implementando una Pila (Parte 2)

aparecieron nuevos atributos, como [TestInitialize]. Tendremos que explicarlos y repasarlos, en un próximo post, y escribir tests usando otros atributos. Comenzaremos a entender, entonces, el funcionamiento de un framework de tests (como cuándo crea una instancia de objeto de la clase tests, cómo invoca los métodos de tests, el ciclo de vida de las variables del objeto de test, el uso de archivos externos, etc..)

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Proyecto Hogwarts: Taller de TDD en Buenos Aires

Tuesday, July 6th, 2010

Como parte del:

Proyecto Hogwarts

se están preparando varios cursos (TDD, Inversion of Control, Mocks, S.O.L.I.D…), como parte del Southworks Professional Improvement Program (el nombre definitivo de los entregables visibles de proyecto interno Hogwarts), con material para instructores, y material para asistentes. La primera instancia pública de un taller sobre uno de estos temas, acaba de ser anunciada:

Media Jornada – Taller de Test-Driven Development (TDD)

en el MUG (Microsoft User Group) de Argentina. El curso estará a cargo de @MartinSalias y @sebarenzi. Leo en la página:

22 de Julio 2010
Lugar: Auditorio del MUG: Rivadavia 1479 1er Piso – Ciudad de Buenos Aires.

En este taller se realizará una introducción a Test-Driven Development, desde su motivación y principios, sus conceptos principales, y la mecánica de trabajo, poniendo énfasis en la práctica. Los ejercicios se realizarán en C# utilizando Visual Studio 2010.

Fecha: Jueves 22 de julio de 2010, en el horario de 14:00 a 18:00hs.

Prácticas en laboratorio.

Contenidos:
Introducción a TDD
Ejemplos y prácticas:

Pruebas Unitarias
Secuencia Rojo, Verde, Refactor
Listas de tests
Refactorización
Cobertura de Código
Diferencia entre pruebas unitarias y de integración
Desacoplamiento e Inyección de dependencias
Dependencias falsas y objetos mock

Vean que es con práctica en máquina. Lean ahí en la página del anuncio el costo del curso. Se anunciará ahí un sitio público en línea, para quienes asistan a uno de estos cursos presenciales, o para quienes no puedan acudir, pero quieran ir aprendiendo, con su tiempo y máquina, sobre temas de TDD (texto explicativo, videos, ejemplos, ejercicios, preguntas, bibliografía, material para si quieren dar un curso presencial en su zona). En el sitio estará el material a presentar en el curso. Seguramente, aparecerá un post por acá anunciando la URL.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Ejemplo de TDD: Implementando una pila (Parte 2)

Tuesday, June 29th, 2010

Ya he escrito sobre el:

Proyecto Hogwarts

y publicado dos posts sobre el tema TDD (Test-Driven Development)

Un ejemplo de TDD
Ejemplo de TDD: Implementando una pila (Parte 1)

Vuelvo al tema, después de mudanza, consolidación de libros, y algo de gripe o símil gripe.

Quiero hoy proseguir con el ejemplo de la pila. El ejemplo había quedado usando una Stack de .NET (decisión tomada para facilitar la demo). Ahora, en este siguiente paso, refactorizamos la implementación para usar una List de .NET, en lugar de Stack. Hacemos este cambio para mostrar que podemos modificar la implementación interna, y estar seguros de que todo sigue funcionando porque hemos escrito los tests correspondientes.

También en el este ejemplo refactorizamos el tests, apareciendo por primera vez el atribute [TestInitialize].

Finalmente, se agrega Code Coverage, que comentaremos en detalle más adelante.

Les dejo acá el video (pueden verlo directamente en Youtube en Pueden ver el video en http://www.youtube.com/watch?v=nDxwLvyMwag con opción a pantalla completa):

[View:http://www.youtube.com/watch?v=nDxwLvyMwag]

Les dejo el código del ejemplo desarrollado: TddStack02.zip

Estamos trabajando para que este curso quede en línea, además de tener material para un instructor de curso presencial. Además de estar escribiendo material para los siguientes cursos:

– Inversion of Control y Dependecy Injection
– Mocks
– Principios SOLID
– Algún ejemplo de aplicación con todo esto aplicado

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez