En post anteriores:
Canales y GoRoutines en AjSharp (Part 1)
Canales y GoRoutines en AjSharp (Part 2)
describí la implementación de gorutinas (goroutines, como en el lenguaje Go de Google), y canales en mi intérprete AjSharp. Al final del año que pasó, escribí una prueba rápida, implementando los mismos conceptos, pero para ser consumidos esta vez desde C# directamente. Pueden ver el código en
http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjConcurr
Primero, porté la clase Channel:
public class Channel
{
private AutoResetEvent sethandle = new AutoResetEvent(false);
private AutoResetEvent gethandle = new AutoResetEvent(false);
private object value;
public void Send(object value)
{
this.gethandle.WaitOne();
this.value = value;
this.sethandle.Set();
}
public object Receive()
{
this.gethandle.Set();
this.sethandle.WaitOne();
object result = this.value;
return result;
}
}
El código tiene una clase estática GoRoutines, con métodos como:
public static void Go(Action action)
{
Thread thread = new Thread(new ParameterizedThreadStart(GoRoutines.RunAction));
thread.IsBackground = true;
thread.Start(action);
//ThreadPool.QueueUserWorkItem(new WaitCallback(RunAction), action);
}
public static void Go(ITask task)
{
Thread thread = new Thread(new ParameterizedThreadStart(GoRoutines.RunTask));
thread.IsBackground = true;
thread.Start(task);
//ThreadPool.QueueUserWorkItem(new WaitCallback(RunTask), task);
}
Pueden lanzar una Action (lo que es en el framework delegate System.Action<>), en un nuevo thread (traté de hacerlo poniendo la tarea en la cola de ThreadPool, pero, no sé por qué, el rendimiento pasó a ser muy bajo; mi intento quedó en comentarios del código de arriba).
Cuando una acción recibe parámetros, se encapsulan los dos en una Task<>, como esta que recibe dos parámetros:
public class Task<T1, T2> : ITask
{
private Action<T1, T2> action;
private T1 parameter1;
private T2 parameter2;
public Task(Action<T1, T2> action, T1 parameter1, T2 parameter2)
{
this.action = action;
this.parameter1 = parameter1;
this.parameter2 = parameter2;
}
public void Run()
{
this.action(this.parameter1, this.parameter2);
}
}
(hay clases Task para uno, dos o tres parámetros).
Pueden invocar GoRoutines.Go directamente, especificando una acción y sus parámetros:
public static void Go<T1, T2>(Action<T1, T2> action, T1 parameter1, T2 parameter2)
{
Go(new Task<T1, T2>(action, parameter1, parameter2));
}
Podemos escribir esta invocación usando expresiones lambda:
[TestMethod]
public void RunGoRoutineWithTwoParameters()
{
int i = 0;
AutoResetEvent handle = new AutoResetEvent(false);
GoRoutines.Go((x, y) => { i = x + y; handle.Set(); }, 2, 3);
handle.WaitOne();
Assert.AreEqual(5, i);
}
Con todo esto implementado, escribí una aplicación de consola AjConcurr.Primes, reimplementando el ejemplo de números primos de mi anterior post:
Channel numbers = new Channel();
GoRoutines.Go(() => { for (int k = 2; ; k++) numbers.Send(k); });
Channel channel = numbers;
int prime = 0;
while (prime < 1000)
{
prime = (int)channel.Receive();
Console.WriteLine(prime);
Channel newchannel = new Channel();
GoRoutines.Go((input, output, p) =>
{
while (true)
{
int number = (int)input.Receive();
if ((number % p) != 0)
output.Send(number);
}
}, channel, newchannel, prime);
channel = newchannel;
}
Me gusta ver este código formateado en pastie:
http://pastie.org/761916
Próximos pasos:
- Mejorar Channel para soportar múltiples productores y consumidores de valores que operan de forma simultánea sobre el mismo canal.
- Agregar soporte de Futures
- Agregar características de reactive programming (sé que está el Reactive Framework, quería experimentar algo con código propio).
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
En mi anterior post describí algo de la implementación de canales y “goroutines” en AjSharp, mi intérprete de un lenguaje de scripting. Quisiera hoy mostrar algunos ejemplos del uso de esos canales y rutinas lanzadas en paralelo.
Primero, recordemos el código simple:
channel = new Channel();
go channel <- 10;
result = <- channel;
En la primera línea, se crea el canal. Luego, el comando go ejecuta en otro thread el envío del valor 10 al canal. En la última línea se toma el valor desde el canal, y se coloca en la variable result. channel <- 10 es “syntax sugar” para channel.Send(10). <-channel es una expresión (devuelve un valor, no es un comando, se puede colocar en cualquier lugar donde se espera una expresión), que codifica channel.Receive(). Las operaciones Send y Receive son bloqueantes: cuando enviamos un valor a un canal, si no hay otro thread leyendo, el thread que envía queda bloqueado, y viceversa. Esta conducta nos da una forma de coordinación entre el productor de valores para el canal y el consumidor de esos valores. Tengo que mejorar el código de implementación para soportar que varios productores (en distintos threads) puedan enviar valores a un mismo canal. Lo mismo para varios consumidores.
Podemos usar el canal varias veces:
channel = new Channel();
go for (k=1; k<=5; k++) channel.Send(k);
for (j=1; j<=5; j++)
result = result + channel.Receive();
que en notación de operadores, es lo mismo que:
channel = new Channel();
go for (k=1; k<=5; k++) channel <- k;
for (j=1; j<=5; j++)
result = result + <-channel;
En vez de generar solamente cinco valores, podemos escribir una goroutine que escriba todos los números en un canal:
channel = new Channel();
running = true;
k = 0;
go while(running) channel <- k++;
for (value = <-channel; value<=10; value = <-channel)
PrintLine(value);
La goruoutine no ejecuta por siempre: su ejecución es controlada, indirectamente, por el thread principal, usando las operaciones bloqueantes del canal. Si la goroutine intenta escribir en el canal, pero no hay quien esté leyendo, entonces la goroutine se bloquea.
Más interesante, podemos usar varios canales para comunicar distintos subprocesos:
channel = new Channel();
running = true;
k = 0;
go while(running) channel <- k++;
function filter(in, out)
{
while (true)
{
value = <-in;
PrintLine("Received in filter " + value);
if (value % 2)
out <- value;
}
}
odds = new Channel();
go filter(channel, odds);
for (number = <-odds; number <= 7; number = <-odds)
PrintLine("Received in main " + number);
running = false;
Este código crea un canal, y un thread paralelo que envía números naturales por ese canal. Otro thread toma valores del primer canal, filtra los impares (rechazando los pares) y los envía a un segundo canal. El thread principal toma valores de este segundo canal, e imprime los primeros resultados.
Vemos que podemos crear, conectar y usar muchos canales. El ejemplo que sigue (inspirado en el que brinda la gente de Google para el Go language ver http://golang.org/doc/go_tutorial.html#tmp_346) imprime los números primos menores de 1000:
numbers = new Channel();
running = true;
k = 1;
go while(running) { k++; numbers <- k; }
function filter(in, out, prime)
{
while (true)
{
value = <-in;
if (value % prime)
out <- value;
}
}
function makefilter(channel, number)
{
newchannel = new Channel();
go filter(channel, newchannel, number);
return newchannel;
}
channel = numbers;
number = <-channel;
while (number < 1000)
{
PrintLine("Prime " + number);
channel = makefilter(channel, number);
number = <-channel;
}
running = false;
Esto planeando agregar un comando done, para parar las goroutines que quedaron andando (una idea más liviana es que las goroutines se lanzen en threads de background). Por ahora, no necesité esa característica. Tengo que estudar el lenguaje Go más en detalle: al parecer, las goroutines se ejecutan en un solo thread, pero no estoy seguro. Para leer más:
http://scienceblogs.com/goodmath/2009/11/the_go_i_forgot_concurrency_an.php
Sutil tema: en el código de arriba, escribí una función makefilter. En mi primer intento, escribí ese código en línea, no como función, directamente dentro del ciclo while, pero tuve un problema: la rutina lanzada por go tiene acceso a las variables que estan en su “lexical scope”, y entonces, cuando la go ruitina accede, por ejemplo, a la variable channel, ese valor podría no ser el mismo que tenía cuando se pasó por el go (la rutina de dentro del go se ejecuta en paralelo), el código externo podría haberlo cambiado. La solución: escribir una función makefilter (que no es otra cosa que un lambda con nombre) para recibir y mantener el valor original de channel y otros valores, sin verse afectados por la rutina principal. En el ejemplo del lenguaje Go que cité arriba, el autor escribe la manipulación del canal en línea, sin apelar a una rutina (por lo menos en el primer ejemplo que muestra), así que debería estudiar más en detalle este tema.
Pueden bajar el código actual de AjSharp desde http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjLanguage. Los ejemplos presentados acá están en AjSharp.Tests/Examples y en AjSharp.Console/Examples (AjSharp.Console es una aplicación de consola que permite ejecutar programas AjSharp leyendo archivos o ingresando el código interactivamente).
Me gusta cómo queda el código del ejemplo de números primos en pastie http://pastie.org/758175 ;-)
Mis próximos pasos en canales y gorutinas: implementarlos y usarlos directamente en C# (ayer escribí un spike), y agregar a un proyecto como el AjAgents o similar. Pueden ver el spike en:
http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjConcurr
y el código de ejemplo de números primos en C# directo:
http://pastie.org/761916
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Hace dos años ya, estuve explorando Microsoft Robotics, y su librería CCR (Concurrency and Coordination). Esta tiene la implementación una port: podemos enviar un objeto por el port, y recibirlo y procesarlo en otra pieza de código, que puede ejecutarse en otro hilo de ejecución. También tiene la capacidad de ejecutar ambas partes en diferentes máquinas, una forma de conectar aplicaciones distribuidas. Yo escribí sobre el tema en:
Distributed Agents using DSS/VPL
Agentes Distribuidos usando DSS/VPL
Agentes Distribuidos y Fractales usando DSS/VPL
Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)
Algoritmos Genéticos con AjAgents y Concurrency and Coordination Runtime (CCR)
CCR posts (English)
Posts sobre CCR en español
Todo esto, me llevó a encontrarme con el concepto de canal: Channel programming (Wikipedia) y este año, leí sobre el nuevo lenguaje de Google, el lenguaje Go: http://golang.org. Pueden leer sobre Go y sus capacidades de manejo de concurrencia (go routines, channels) en: http://golang.org/doc/go_tutorial.html#tmp_346
También comencé a leer sobre proyecto Axum de Microsoft: http://en.wikipedia.org/wiki/Axum_%28programming_language%29
Con toda esta base, el último sábado agregué soporte de canales y goroutines en mi intérprete AjSharp (otros posts AjSharp interpreter). Pueden bajar y ver la versión actual desde http://code.google.com/p/ajcodekatas en trunk/AjLanguage
Primero, agregué un tipo nativo .NET Channel (a mejorar: agregar soporte para que el canal pueda soportar varios send y receive desde más de un thread):
public class Channel
{
private AutoResetEvent sethandle = new AutoResetEvent(false);
private AutoResetEvent gethandle = new AutoResetEvent(false);
private object value;
public void Send(object value)
{
this.gethandle.WaitOne();
this.value = value;
this.sethandle.Set();
}
public object Receive()
{
this.gethandle.Set();
this.sethandle.WaitOne();
object result = this.value;
return result;
}
}
Cuando se envía un objeto a un canal, el thread que lo envía se bloquea hasta que otro thread lea el canal (pienso agregar un QueueChannel, donde se puedan enviar varios objetos, a guardar en una cola, sin para los threads; supongo que la cola tendrá un tamaño limitado, para ir auto-coordinando los productores y consumidores de objetos del canal).
Siguiendo las ideas de goroutines en el lenguaje Go, agregué un nuevo comando en AjSharp: go <command> (ok, no mucha creatividad aquí… ;-)… igual hay que aclarar que los goruotines en Go tienen muchas más características que las que implemento acá). Esta nueva palabra lanza el comando en un thread separado, que comparte las variables del original, como en este ejemplo (recordemos que AjSharp tiene acceso a los objetos y clases nativas de .NET):
handle = new System.Threading.AutoResetEvent(false);
one = 0;
go { one = 1; handle.Set(); }
handle.WaitOne();
result = one;
Todo esto se agregó a la máquina de ejecución de AjSharp (por ejemplo, Channel es un tipo ya declarado dentro de la máquina, sin necesidad de usar el namespace completo), podemos usar entonces:
channel = new Channel();
go channel.Send(10);
result = channel.Receive();
Luego de tener esto andando, modifiqué algo más. Fue simple agregar “syntax sugar” al parser de AjSharp para que
<- channel
sea igual a
channel.Receive()
y que
channel <- value;
sea una forma de escribir:
channel.Send(value);
Entonces, el ejemplo anterior se puede escribir como:
channel = new Channel();
go channel <- 10;
result = <- channel;
En otro post, describiré algunos usos de estas características, con algún detalle de implementación. Ver el código actual en:
http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjLanguage
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Estoy escribiendo un intérprete no tipado con sintaxis tipo C#, que bauticé AjSharp. Hace un tiempo escribí sobre este proyecto de código abierto en:
AjSharp Programming Language a C#-like Dynamic Language
AjSharp: un lenguaje dinámico en C#
Pueden bajarse la versión actual desde http://code.google.com/p/ajcodekatas en trunk/AjLanguage (AjLanguage define el árbol de ejecución del intérprete, AjSharp tiene un parser, un lenguaje definido para construir ese árbol; la idea es colocar otros parsers sobre AjLanguage, por ejemplo, AjBasic).
Ayer sábado, agregué una nueva característica, la definición de un objecto. Ya de antes, AjSharp soporta la definición de una clase dinámica:
class Person
{
var Name;
var Age;
function AddYears(years)
{
this.Age = this.Age + years;
}
}
Pueden crear un objecto usando:
adam = new Person();
adam.AddYears(800);
adam.Name = "Adam";
El objeto creado es dinámico: se le pueden agregar variables de instancias y métodos, en cualquier momento:
adam.LastName = "unknown";
adam.EyeColor = "brown";
adam.SayHello = function() { PrintLine("Hello"); };
Pueden crear objetos, con esta notación, inicializando su estado:
adam = new Person() { FirstName = “Adam”, LastName = “Genesis”, Age = 800 };
Y hasta pueden definir un objeto sin tener una clase asociada:
dynobj = new { Name = “Adam”, Age = 800 };
Esto es equivalente a hacerlo más “programáticamente” así:
dynobj = new DynamicObject();
dynobj.FirstName = “Adam”;
dynobj.LastName = "Genesis”;
dynobj.Age = 800;
dynobj.FullName = function() { return FirstName + “ “ + LastName; }
Esto estaba implementado desde hace meses. Ayer agregué la notación:
object Adam
{
var Name = "Adam";
var Age = 700;
function AddYears(years)
{
this.Age = this.Age + years;
}
}
Adam.AddYears(100);
donde se puede definir un objecto único, dándole estructura, conducta y nombre.
La idea de AjLanguage es que pueda acceder a todas las clases y objetos del framework subyacente (en este caso, .NET, pero está pensado para ser reescribible sobre Java, si fuera necesario, claro, cambiando cualquier referencia a tipos nativos):
ds = new System.Data.DataSet();
dinfo = new System.IO.DirectoryInfo(“.”);
foreach (fi in dinfo.GetFiles())
{
PrintLine(fi.FullName);
}
Desde ayer, seguí implementando constructores. Tengo pensado definir visibilidades privadas y públicas (por ejemplo, las variables y métodos de instancia que comiencen con minúscula, hacerlas automáticamente privadas). También agregar propotipos, como en Javascript, lo que permitiría implementar cosas similares a los métodos de extensión de .NET.
Pero si van hoy al trunk, encontrarán que estuve implementando canales, como en en lenguaje Go de Google.
channel = new Channel();
go for (k=1; k<=5; k++) channel <- k;
for (j=1; j<=5; j++)
result = result + <-channel;
Pero eso dará para otro post más detallado. Con esa característica quiero explorar temas como programación reactiva, agentes, actores, shared transactional memory, ver:
http://clojure.org/Agents
http://en.wikipedia.org/wiki/Actor_model
http://en.wikipedia.org/wiki/Axum_%28programming_language%29
Por ejemplo, sería interesante que los canales comunicaran no sólo dos códigos en paralelos, sino máquinas diferentes. Y definir esas máquinas en tiempo de deployment, sin cambiar el código del programa. Podría reescribir los ejemplos de Distributed Agents using DSS/VPL o Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)
Como verán, me estoy divirtiendo!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Una de las prácticas que siempre intento “vender” a cualquiera involucrado en el desarrollo de software, es la práctica de Test-Driven Development. Una vez que se practica TDD, no quieren volver atrás. Es una forma de programar con tanta recompensa y gozo asociados, que me siento incómodo si no lo usa cuando escribo software real.
Gracias a un tweet de ayer de @jjfalcon, descubrí este ejemplo, en Youtube, del usuario objarni. El usa Ubuntu, programando en Python, usa pyTDDemon para ver inmediatamente el resultado de los tests.
Implementa algo sencillo: código que dado un string con una URL, identificar el protocolo, el dominio, y el recurso que está contenida en esa dirección. En TDD, se va escribiendo el test, el código que pasa el test, y se va progresando de a poco. No hace falta escribir el código correcto y completo desde el principio. Como en otras tantas actividades, el “baby-step”, el “pequeños pasos” de avance, nos ayuda para ir incrementalmente produciendo el resultado esperado.
Noten el ciclo rojo-verde-refactor, el código mínimo que se agrega en cada tests (a veces, retornando valores puestos a mano, sólo para pasar los tests), refactorizando el test si hay código duplicado, las micro-decisiones de diseño que se van tomando, etc… Excelente trabajo para mostrar en video!
Habría tanto para comentar de TDD. Por ahora, dos recursos. He “tagueado” más videos sobre TDD, en mi delicious:
http://delicious.com/ajlopez/tdd+video
Los enlaces que colecciono sobre TDD:
http://delicious.com/ajlopez/tdd
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Además de la reunión de hoy viernes ALT.NET Hispano VAN (Reunión Virtual): Automatizar mañana sábado 19 de diciembre (18 GMT, 3 de la tarda acá en Buenos Aires), tendremos otra reunión virtual, organizada por la comunidad ALT.NET Hispano, esta vez sobre el tema Domain-Driven Design.
Esta vez voy a hacer la presentación inicial. Mi idea es plantear los temas de DDD, desde un poco de historia, llegando a las ideas de Eric Evans, viendo cómo se puede implementar en .NET, con algún código de ejemplo. Tenemos que ver:
- Dominio
- Modelo
- Modelo de Dominio
- Capas sugeridas por Evans
- Implementando el Dominio
- Entities, Value Objects, Services, Repositories, Factories
- Persistencia, principal tema de infraestructura
- Ejemplo de código abierto
Creo que llegamos en tiempo para presentar conceptos de Command Query Separation aplicadas en .NET.
Gracias a Jorge Gamba que también escribió [VAN] Viendo la luz en “Domain-Driven Design” (DDD).
Más información sobre cómo asistir a la reunión virtual, software necesario, enlaces: http://altnet-hispano.pbworks.com/Descripcion-de-Reuniones
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Este viernes 18 de diciembre, habrá una nueva VAN (reunión virtual, des-conferencia) organizada por la incansable comunidad de ALT.NET Hispano. Esta vez el tema es la automatización, y la presentación principal estará a cargo del bueno de Martín Salías (@MartinSalias). Aunque es en viernes, en lugar de sábado, la hora es la habitual, 18 GMT (acá en Buenos Aires, 3 de la tarde). Hace un tiempo, Martín escribía en la lista del grupo, sobre el temario que va a encarar:
me gustaría encarar un tema … que es:
"antes de hacer algo por cuarta vez, automatízalo".
Creo que es muy común caer en repetición de tareas, y siempre tenemos oportunidad de automatizarlas, lo que brinda muchas ventajas:
- ahorra trabajo (productividad)
- optimiza tiempos (siempre la máquina va más rápido)
- aumenta la previsibilidad
- nos fuerza a ser más consistente en los procesos (tenemos que respetar cierto protocolo)
- facilita la mejora (es fácil agregar cosas en un proceso automático)
- permite obtener métricas fáciles de lo que se automatiza
Esto aplica a montones de cosas, desde:
- mejora de APIs y abstracciones (para mantenernos DRY)
- templates y generadores de código (para que el Maestro sea felíz) ;-)
- scripting para automatizar procesos de build, deployment, testing, etc
- encadenamiento (o workflow) de scripts
Temas/métodos puntuales:
- Scripting, scripting, scripting (Ruby, Python, Powershell, etc)
[se le preguntó si también habrá Integración Continua]
Digamos que a lo que quiero ir es a automatización mucho más allá del build server. Pero sobre éste nosotros tenemos además de compilación y
testing, todo nuestro proceso ISO (reporte a cliente, verificación de drops, etc).
Mi idea de todas maneras es contarlo a nivel más general y seguramente después se puede hacer otra mostrando como configurar CC.Net o Team
City, por ejemplo, cómo disparar diferentes tests (units, integration, code analysis, source analysis, dependencias, cálculo de coverage, etc) y cómo
tener alarmas, reportes, estadísticas, etc. Tal vez hasta alguien se anime a mostrar esto con TFS. :)
Más información sobre cómo asistir a la reunión virtual, software necesario, enlaces: http://altnet-hispano.pbworks.com/Descripcion-de-Reuniones
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
El bueno de Juan Gabardini anuncia en la lista Foro Agiles, un nuevo curso de Scrum de Tobias Mayer en Argentina. Copio el mensaje original:
Tobias Mayer facilitará un taller de un día en Buenos Aires, Argentina. Está orientado a Scrum Masters y agile coaches.
Para los que no lo conocen, Tobias dió el primer curso de CSM en Argentina, allá por el 2006. Luego de eso ha venido varias veces (no se cuantos, pero dió al menos 5 CSM en Bs As). ….
Se explorarán los principios y valores de Scrum. Este taller no se focaliza en las prácticas (se asume que los participantes tienen familiaridad con ellas) y explora Scrum en un nivel más profundo y humano. A través de una serie de juegos, ejercicios interactivos y conversaciones facilitadas, se adquirirá una comprensión más profunda del nuevo esquema de pensamiento requerido para hacer Scrum. Esto no es sobre metodologías o procesos, es sobre divertirse
Cuándo: 28 de enero 2010
Dónde: Perú 375, 1er piso (Southworks)
Costo: usd 220 + IVA
Registración: http://tinyurl.com/tobiasBsAsWorkshop
Este evento es organizado por Agiles Argentina y Agilar Argentina
Este evento será dado en inglés. Aunque por el tipo de evento no es imprescindible el hablar y entender perfectamente, ya que el resto de los que asistimos podremos dar una mano. Va el detalle en inglés.
Process/Mechanics
Scrum is quickly being seen as the de facto way of starting out down an Agile pathway. People see it as a quick and easy way in. The problem is that Scrum is very easily misunderstood. There are a multitude of Scrum Facades in place around the world, companies who claim to be doing Scrum because they have people with the titles of “Scrum Master” and “Product Owner”, have daily meetings, maybe even planning meetings, reviews and retrospectives, keep a backlog of work and show some sort of burn down graph each sprint.
Underneath the facade though, the same old command and control beast lurks, the same old fear and CYA behavior. Nothing has essentially changed. So what is missing? I believe the spirit of Scrum is missing, the essence of change.
Scrum is not just a framework and a set of roles, meetings and artifacts. Scrum is a way of being that is utterly different from any previous way of working that we have encountered in the software industry. To do Scrum — to really do Scrum — requires an absolute shift in the way we think and act.
Scrum relies on some core principles:
— Empiricism
— Self-Organization
— Collaboration
— Prioritization
— Rhythm
and some essential values:
— Courage
— Trustfulness
— Transparency
This session will allow Scrum practitioners to reach the next level of Scrum by exploring some of these underlying foundations in a highly experiential way. The session will consist of a series of interactive exercises and facilitated discussion designed to help participants not just understand, but embody these principles and values at a deep level.
I create and/or adapt new games frequently, the majority require no props, and usually require the participants to be on their feet. Most have simple formats and can be easily remembered. None of them have pre-determined outcomes: they are all about self-discovery. For more detailed information on the kinds of games and interactive exercises I’ll use for this session please follow one or more of these links to descriptions of sessions I have run previously.
This session is intended as a taster and it is hoped participants will be encouraged to explore more deeply the human interaction foundations of Scrum once they leave the conference.
Learning outcomes
Ya comenté sobre el bueno de Tobias en:
Tales from the Scrum: La esencia de Scrum
Tales from the Scrum: Un día en el equipo
Tales from the Scrum: El corazón de Scrum
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Este sábado 12 de diciembre, 19 GMT (4 de la tarde aquí en Buenos Aires) de nuevo tenemos VAN (Reunión virtual, des-conferencia) organizada por la comunidad de ALT.NET Hispano.
(Más información sobre cómo asistir a la reunión virtual, software necesario, enlaces:
http://altnet-hispano.pbworks.com/Descripcion-de-Reuniones
)
Esta vez el tema será Prism (Composite Application Guidance para Windows Presentation Foundation y Silverlight). La introducción estará a cargo del bueno de @juliandominguez, que nos comenta en la lista de ALT.NET Hispano:
La idea de este próximo sábado es presentar sobre Prism (o Composite Application Guidance for WPF and Silverlight para los que prefieren el nombre real pero aburrido).
¿Qué es Prism de patterns & practices y qué desafíos resuelve?
¿Qué beneficios les brinda a arquitectos, desarrolladores y a la interacción con diseñadores?
En esta sesión mostraré cómo Prism nos ayuda a trabajar en equipos distribuidos, no distribuidos, grandes o pequeños, con requerimientos cambiantes, aplicando conceptos como TDD y patrones de UI como Model View ViewModel (MVVM). También voy a mostrar cómo nos ayuda a reusar código que funcione en WPF y en Silverlight.
Vamos a estar viendo los beneficios que nos trae Prism a la hora de construir una aplicación compuesta, como así también en qué (lio?) nos metemos cuando queremos usar Prism en una aplicación que no lo amerita.
Espero que les resulte muy interesante a quienes no conocen Prism y tienen pensado empezar un proyecto en WPF o Silverlight.
Sé que normalmente las VAN suelen ser a las 18:00 GMT, pero debido a mi horario (actualmente estoy en Redmond), preferiría que sea las 19:00 GMT. Esto sería el sábado 12/12.
Así que la reunión será este sábado a las 19GMT (no a las 18GMT como otras veces).
Mi colección de enlaces sobre Prism:
http://delicious.com/ajlopez/prism
Otros interesantes:
http://delicious.com/ajlopez/mef
http://delicious.com/ajlopez/mvvm
http://delicious.com/ajlopez/silverlight
http://delicious.com/ajlopez/wpf
(especialmente si agregan examples o tutorial, como http://delicious.com/ajlopez/mef+example)
Si es la primera vez que topan con el término VAN, les recuerdo:
Si no conocen qué es una reunión VAN, pueden consultar VAN meetings. Para ver cómo se desarrolla una VAN de ALT.NET Hispano, y qué software necesitan para asistir, ver Descripcion-de-Reuniones-VAN. Pueden ver el historial de anteriores reuniones VAN (visiten las que dieron, por ejemplo, sobre NHibernate, WPF y demás) (yo participé en VAN sobre Scrum y en otra sobre generación de código). También pueden suscribirse para proponer nuevos temas, y colaborar con la comunidad. Si no pueden asistir a ésta VAN, seguramente quedará publicada más adelante, con video incluido.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Bueno, en realidad, no los Rolling Stones. Solamente Keith Richards, y no el de los Rolling, sino Keith Richards presidente de Keith Richards Consulting. Encuentro en un post de Gojko Adzic un post que comenta una charla de KRC:
Eight interesting techniques to test how a project is going
Es un muy interesante post, déjenme escribir esas técnicas, para saber si el proyecto y el equipo están en buena forma, sea que estén siguiendo Scrum o no. Esta es mi propia traducción de ese texto:
- 1. ¿Puede cualquier miembro del equipo escribir el objetivo del proyecto en una nota post-it con marcador grueso? Si no pueden, el final del juego no está claramente definido ni entendido por todos
- 2. Acérquese a un colega en su trabajo, y pídale ayuda para algo cualquiera. Vea cómo reacciona. Si encuentra una respuesta fría, la persona no está muy contento con su trabajo. Richards aconseja armar equipos con “aquellos que respondan ‘puedo’”. Esa gente mejorará la comunicación y el espíritu de equipo en su proyecto.
- 3. Cuando una fase del proyecto está oficialmente “hecha” (done), pregúntese a sí mismo: “¿Es seguro seguir adelante?”. Si esta pregunta le provoca una mala sensación en las tripas, es que no están listos todavía para avanzar a la siguiente etapa.
- 4. ¿Cuántos de sus proyectos terminan con una seria revisión del proyecto? Esto es, según Richards, crucial para la mejora de su organización. Permite prevenir errores repetidos y compartir conocimiento entre los equipos (yo agrego que, si trabaja en una organización con varios proyectos y equipos, tendría que haber comunicación entre equipos DURANTE los proyectos, comentando bloqueos, avances, hallazgos, problemas y soluciones; unas buenas reuniones periódicas con presentaciones timeboxed pueden ser un camino a seguir).
- 5. ¿Cómo reacciona la gente de su equipo cuando el cliente dice “cambié de idea”? Si reaccionan negativamente, el sistema que están construyendo no es tan flexible como debiera.
- 6. Pregúntele a alguien que le comente el estado actual de una tarea, y luego cállese 10 segundos; no hagan nada para provocar una respuesta. Si la persona se muestra insegura o nerviosa sobre algo, seguramente comenzará a comentarlo. Si se mantiene en silencio, las cosas van bien (este punto lo discutiría: debería haber comunicación y visibilidad sin necesidad de llegar a este tipo de “trick”).
- 7. ¿Conoce cuánto tiempo se empleó en la última iteración en pruebas? Si no puede estimarlo, no está tomando buenas métricas del proyecto. Tomar métricas de este tipo, dice Richards, es crucial para hacer estimaciones realistas (nota mía: ojalá tuviera un peso por cada vez que alguien en un equipo estimó una tarea SIN tener en cuenta pruebas, verificación, etc.; pongan atención a esto).
- 8. Tome un documento de su proyecto, usado durante una presentación. Si atrás hay diagramas dibujados a mano, señal que el documento no está claro, y necesitó de esa ayuda para ser explicado.
Me quedo principalmente con los puntos 1, 2, 3, 5 en primer lugar. Luego 7, 4.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Este sábado 5 de Diciembre, 18 GMT/UTC (3 de la tarde por aquí en Buenos Aires), habrá otra des-conferencia virtual de la comunidad ALT.NET Hispano. El tema será productividad, más específicamente Get Things Done (GTD) (ver también Consigue hacer el trabajo). La presentación inicial estará a cargo de Jeroen Sangers:
http://jeroensangers.com/
@jeroensangers
Este es el temario de Jeroen:
Mi presentación va más que nada sobre Getting Things Done y consiste
de tres partes:
1. Control: un flujo de trabajo para controlar tus acciones
2. Perspectiva: dar dirección a todo lo que haces
3. Consejos prácticas para implementar un sistema de productividad
GTD se populariza con un libro de David Allen. Pueden leer la descripción de GTD en el sitio de Allen:
What is GTD?
Ahí leo:
Sophisticated without being confining, the subtle effectiveness of GTD lies in its radically common sense notion that with a complete and current inventory of all your commitments, organized and reviewed in a systematic way, you can focus clearly, view your world from optimal angles and make trusted choices about what to do (and not do) at any moment. GTD embodies an easy, step-by-step and highly efficient method for achieving this relaxed, productive state. It includes:
- Capturing anything and everything that has your attention
- Defining actionable things discretely into outcomes and concrete next steps
- Organizing reminders and information in the most streamlined way, in appropriate categories, based on how and when you need to access them
- Keeping current and "on your game" with appropriately frequent reviews of the six horizons of your commitments (purpose, vision, goals, areas of focus, projects, and actions)
Pueden encontrar una buena descripción (con diagrama incluido, como el que aparece en el libro original) de GTD y una relación con los “cuadrantes de Covey” (me gusta recordar al creador de ese concepto, que es la matriz de Eisenhower).
Mis enlaces sobre GTD, y productividad:
http://delicious.com/ajlopez/gtd
http://delicious.com/ajlopez/productivity
Bueno, ya envíe varios posts sobre las VAN de ALT.NET Hispano, pero les recuerdo:
Si no conocen qué es una reunión VAN, pueden consultar VAN meetings. Para ver cómo se desarrolla una VAN de ALT.NET Hispano, y qué software necesitan para asistir, ver Descripcion-de-Reuniones-VAN. Pueden ver el historial de anteriores reuniones VAN (visiten las que dieron, por ejemplo, sobre NHibernate, WPF y demás) (yo participé en VAN sobre Scrum y en otra sobre generación de código). También pueden suscribirse para proponer nuevos temas, y colaborar con la comunidad. Si no pueden asistir a ésta VAN, seguramente quedará publicada más adelante, con video incluido.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Gracias a la gente del Microsoft User Group de Argentina, ayer miércoles 2 de diciembre estuve dando una jornada de Scrum teoría y práctica, de todo un día. Con unos treinta asistentes, estuvimos viendo temas como el manifiesto ágil, y las ideas que sustentan Scrum en particular. Así como también los roles, artefactos, reuniones, que se manejan en este marco de trabajo. Discutimos tópicos como contratos ágiles, relación con el cliente, la importancia del product owner, la auto-organización del equipo, el “ownership” que tienen que ganar, la idea de trabajar a un ritmo razonable, el “entrar en flujo”, Product backlog vs Sprint Backlog, y el clásico Chanchos y Gallinas.
Para mí, fue una grata experiencia: es uno de los cursos donde veo que más puedo aportar, y donde podemos practicar algo que considero muy importante conocer como es Scrum. Veo que la necesidad de tener equipos ágiles es creciente, no sólo en el desarrollo de software, sino en actividades en general. La labor en equipo permite llegar a objetivos que son más difícil de lograr individualmente o en simple grupo (vean que distingo entre equipo y grupo). Hay que estudiar más en detalle cuáles son los factores que hacen que Scrum funcione (me basé mucho en la idea de No somos vulcanos): hay un bias hacia mostrar los casos de éxito en la comunidad ágil, y no comentar los fracasos. Hay que pasar de la evidencia anecdótica a un fundamento más firme, no porque el marco de trabajo en sí lo necesite, sino para poder aplicarlo mejor, entender mejor en qué circunstancias funciona, y en cuáles se complica.
La parte teórica ocupó la mañana, pero ya después los asistentes se separaron en cuatro grupos, y comenzaron a trabajar en desarrollar un entregable, en dos sprints de 3 días de 10 minutos cada día. Fue una experiencia interesante: fuimos viendo cómo mejorar las reuniones, la precisión del backlog, los acuerdos con el product owner para los entregables de Sprint Review, el reparto de trabajo, la mejor partición de las tareas en el Product Backlog, y más.
Prometí publicar un post con los recursos que mencioné en el curso. Acá van los enlaces y bibliografía, que son similares a los que ya publiqué hace unos días para otros cursos dictados, pero para más comodidad, los concentro de nuevo en este post:
Reunión virtual de Scrum, con video (gran parte de la teoría vista en el curso está en este video) (ahí están los enlaces que presento acá).
Presentación usada en el curso ScrumSpanish.pptx
Pueden usar esta presentación compartida (en varios idiomas):
A Reusable Scrum Presentation. Introduce Scrum to your team, ScrumMaster and Product Owner.
Para leer en inglés y en español Scrum Primer http://agilethinking.net/ El sitio de Tobias Meyer, que me inició en el ScrumMastering en el 2006. http://www.implementingscrum.com/ Sitio donde encontraran la clásica historia: The classic story of the pig and chicken El Manifiesto Agil mencionado en la charla Artículo corto en inglés (pdf) What is Scrum? Reviews of Agile Product Backlog and User Story Management Tools: http://www.userstories.com/ Presentación en español sobre Contratos Ágiles Foro Agiles (Grupo Yahoo en español) Blog de Juan Gabardini Software Agil Enlaces y recursos adicionales en Scrum Práctico Scrum Cheat Sheet Scrum: Ficha Sinóptica Un libro que para preparar las primeras versiones del curso
Agile Project Management with Scrum
de Ken Schwaber ISBN:073561993x Microsoft Press © 2004
En ese libro, están enumerados estos recursos:
Agile Software Development with Scrum, Ken Schwaber and Mike Beedle (Prentice Hall, 2001)
Teoría y práctica de Scrum.
www.controlchaos.com/
El sitio de Ken Schwaber sobre Scrum.
http://www.jeffsutherland.com/
Jeff Sutherland tiene contenido relacionado con desarrollo de software, programación, tecnología, objetos, componentes y Scrum.
www.mountaingoatsoftware.com/scrum/
El sitio de Mike Cohn sobre Scrum.
www.scrumalliance.org
El hogar de los ScrumMaster certificados.
www.agilealliance.org
El sitio de la AgileAlliance, con recursos sobre Agile y Scrum.
http://groups.yahoo.com/group/scrumdevelopment/
El grupo de discusión de Scrum, con años de existencia.
www.xprogramming.com
El sitio de Ron Jeffries acerca de Extreme Programming (XP). XP provee varias de las prácticas que Scrum implementa para asegurar el incremento de funcionalidad potencialmente entregable.
Otras lecturas recomendadas
- Agile and Iterative Development: A Manager’s Guide by Craig Larman
- Agile Estimating and Planning by Mike Cohn
- Agile Retrospectives by Esther Derby and Diana Larsen
- Agile Software Development Ecosystems by Jim Highsmith
- Scrum and The Enterprise by Ken Schwaber
- User Stories Applied for Agile Software Development by Mike Cohn
- Artículos semanales en www.scrumalliance.org
Mis posts sobre Scrum (estoy ahí escribiendo una serie “Tales from the Scrum” donde trato más en detalle algunos puntos que tratamos en el curso).
Los enlaces que me interesaron los colecciono en:
http://delicious.com/ajlopez/scrum
http://delicious.com/ajlopez/agile
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
AjGenesis, mi proyecto open source de generación de código, usa tareas, templates (plantillas) y un modelo de libre definición, para generar artefactos de texto, en general código fuente, pero también archivos cualesquiera, como configuraciones, definición de proyectos, etc. Muchos de los ejemplos que están en el proyecto y otros que publiqué aparte, usan modelos serializados como archivos XML o de texto. Pero el modelo inicial puede ser cualquier entrada: no sólo esos archivos, sino cualquier fuente de información que nos dé alguna base de modelo. Hasta podemos armar archivos de modelo (recuerden, el modelo lo deciden uds, dónde va, qué tiene, es todo libre) desde otro modelo. Hace unos dos años, escribí sobre generar el modelo desde la base de datos. En mi opinión, la base de datos no es el modelo más expresivo, pero es uno muy ubicuo: puede servir como punto de partida, y desde la base de datos, generar un modelo que podemos refinar posteriormente.
(sobre el tema de modelos pueden leer Modelos y metamodelos en AjGenesis: los metamodelos no son necesarios ni obligatorios, pero es un tema que estoy agregando en el proyecto, como opcional).
(un tipo de modelo a explorar Otro modelo para AjGenesis)
Hoy quiero entonces volver sobre el tema de generar un modelo desde otro modelo, esta vez usando el esquema de la base de datos que tengamos entre manos. Es sólo un ejemplo “prueba de concepto”. Pero en el proyecto ágil en que estoy participando, el equipo tomó la base que ya tenían y generó un modelo usando técnicas como las de este ejemplo, usando AjGenesis, y ahora, ya abandonaron la base inicial, y usan directamente el modelo generado alguna vez y refinado desde entonces.
Pueden bajar el ejemplo actual de mi Skydrive DatabaseExample01.zip. (el código está en el repositorio de código en Codeplex, bajo el directorio examples\DatabaseExamples). El .zip de Skydrive tiene todo lo necesario, incluso la versión en desarrollo de AjGenesis ya compilada.
Despues de bajarlo y expandirlo, tenemos estas carpetas:

Hay un solo proyecto de ejemplo. EL contenido de Projects\Northwind\Metadata.xml:
<Metadata>
<Project>
<Name>Northwind</Name>
</Project>
<Database>
<Name>Northwind</Name>
<ConnectionString>server=.\SQLEXPRESS;database=Northwind;Integrated Security=true</ConnectionString>
</Database>
</Metadata>
Describe el string de conexión a usar para llegar a la base de ejemplo. Estoy usando la Northwind, en SQL Server (pueden usar el full o el express). Si no tienen esa base de datos, los scripts de creación están en el directorio Sql.
Para generar el proyecto, el modelos con sus entidades, ejecutar:
MakeModelFromDatabase.cmd
AjGenesis (compilado en el directorio Bin) comienza su trabajo:

El comando que ejecutamos contiene:
Bin\AjGenesis.Console Projects\Northwind\Metadata.xml Tasks\DatabaseProcess.ajg
Este comando carga el contenido de Metadata.xml como modelo en memoria, y ejecuta la tarea DatabaseProcess.ajg escrita en el lenguaje dinámico que uso AjBasic. Esta tarea usa las vista de Information Schema para obtener información acerca de la estructura de la base de datos (usando estas vistas, que están definidas en el estándar SQL, y presentes en varias bases de datos, nos abre la puerta para conseguir trabajar con otras marcas que no sean MS SQL Server; debería probar, por ejemplo, con Oracle).
La tarea crea el archivo Projects\Northwind\Project.xml:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<Project>
<Name>Northwind</Name>
<Model>
<Entities>
<Entity Source="Entities/Customer.xml"/>
<Entity Source="Entities/Shipper.xml"/>
<Entity Source="Entities/Supplier.xml"/>
<Entity Source="Entities/Order.xml"/>
<Entity Source="Entities/Product.xml"/>
<Entity Source="Entities/OrderDetail.xml"/>
<Entity Source="Entities/CustomerCustomerDemo.xml"/>
<Entity Source="Entities/CustomerDemographic.xml"/>
<Entity Source="Entities/Region.xml"/>
<Entity Source="Entities/Territory.xml"/>
<Entity Source="Entities/EmployeeTerritory.xml"/>
<Entity Source="Entities/Employee.xml"/>
<Entity Source="Entities/Category.xml"/>
</Entities>
</Model>
</Project>
El proyecto y las entidades son parecidas a las que usé en Generando aplicaciones con AjGenesis (pero no es igual, estoy experimentando con mejoras). Parte del contenido del archivo generado Projects\Northwind\Entities\Customer.xml nos da una idea de lo que se captura de una “Entity”:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<Entity>
<Name>Customer</Name>
<Description>Customer</Description>
<SetName>Customers</Name>
<Descriptor>Customer</Descriptor>
<SetDescriptor>Customers</SetDescriptor>
<SqlCatalog>Northwind</SqlCatalog>
<SqlSchema>dbo</SqlSchema>
<SqlName>Customers</SqlName>
<Properties>
<Property>
<Name>CustomerID</Name>
<Description>CustomerID</Description>
<SqlName>CustomerID</SqlName>
<SqlLength>5</SqlLength>
<IsKey>True</IsKey>
<SqlType>nchar</SqlType>
<SystemType>String</SystemType>
<IsNullable>False</IsNullable>
</Property>
....
</Properties>
</Entity>
La lógica principal de todo este proceso de generación, reside en la tarea Tasks\DatabaseProcess.ajg, de nuevo escrita en AjBasic (I love this language! :-) un fragmento:
cmd = new System.Data.SqlClient.SqlCommand()
cmd.Connection = conn
cmd.CommandText = "select * from Information_Schema.Tables where Table_Type = 'BASE TABLE'"
conn.Open()
PrintLine "Reader"
dr = cmd.ExecuteReader()
Tables = CreateList()
while dr.Read()
PrintLine "Table " & dr.Item("Table_Name") & ": " & dr.Item("Table_Type")
Table = CreateObject()
Table.SqlCatalog = dr.Item("Table_Catalog")
Table.SqlSchema = dr.Item("Table_Schema")
Table.SqlName = dr.Item("Table_Name")
Table.Name = Table.SqlName.Replace(" ","")
if IsPlural(Table.Name) then
Table.SetName = Table.Name
Table.Name = ToSingular(Table.Name)
else
Table.SetName = ToPlural(Table.Name)
end if
Table.Descriptor = Table.Name
Table.SetDescriptor = Table.SetName
Table.Description = Table.Name
Tables.Add(Table)
end while
dr.Close()
Posibles mejoras
Como escribí más arriba, este ejemplo es una “prueba de concepto”; una versión anterior la usamos en un proyecto real. Pero hay varios puntos a mejorar:
- Usar el modelo generado para generar una aplicación que funcione, con scaffolding o no.
- Soportar más metadata que obtengamos via Information Schema
- Probar con otras marcas de bases de datos, y con bases de datos reales
- Tratamiento de relaciones: detectar borrados en cascadas, soportar claves primarias compuestas, otras acciones.
Otros posts relacionados (aparte de los ya mencionados):
Si es la primera vez que se topan con generación de código con AjGenesis, tengo varios posts escritos. Recomiendo un video, producido gracias a la comunidad ALT.NET Hispano: Resultado de la VAN ALT.NET Hispano sobre Generación de Código
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Quisiera hoy detenerme en uno de los roles de Scrum: el Product Owner (podría traducirlo por “dueño del producto”, pero voy a seguir la costumbre de usar la denominación en inglés), y en particular, en una de sus actividades.
La principal actividad, que le compete completamente, es el mantenimiento de los items del Product Backlog, y sus prioridades. Recordemos que el Product Backlog es el documento que lista la funcionalidad que esperamos del producto terminado. Esta lista es evidentemente importante: mal armada, puede hacer que el producto a entregar no sea el que el cliente final necesita.
Esa lista no la decide el Equipo, y menos el Scrum Master. Lo decide el cliente, en reuniones anteriores al inicio del proceso, donde pueden intervenir distintos interesados, pero de ahí en más es el Product Owner el responsable de mantenerlo (un Product Backlog puede cambiar con el tiempo, no es un documento escrito en piedra). Este es el responsable de entender, mantener, y conocer las prioridades de esta lista, del que saldrá el producto que entregaremos al final del proceso.
Es común, si no se conoce Scrum, querer priorizar los items por su orden “lógico” de desarrollo. No: la idea es priorizar por importancia para el negocio, para lo que necesita el cliente. De ahí que las prioridades no las decide el Equipo, sino el Product Owner.
Esto implica que la persona que encarne ese rol, debe conocer del negocio del cliente. Debe tener contacto con los principales actores de la actividad del negocio, entenderlo, y debe conocer cuáles son las áreas importantes. Demos un ejemplo.
Si tenemos que desarrollar un sistema de seguros en línea, el Product Owner deberá decidir qué partes del sistema a entregar darán más valor al negocio, y por qué. Tal vez, el grueso del negocio sean los seguros de vida, o tal vez el seguro de camiones, o quizás el seguro de autos. Dependiendo de ese dato, se podrá priorizar el tener una aplicación para calcular un seguro de vida, antes que uno de autos. No se comienza por lo “más fácil”, o por “lo que nos están pidiendo ahora”, sino por lo más importante.
Si un equipo técnico tuviera que decidir sobre esos puntos, seguramente tomaría primero el tener una base de datos, o un sistema de seguridad, o cualquier otro punto. No es la idea en Scrum: la idea es entregar, al final de cada Sprint, iteración, algo que agregue valor. Por supuesto, lo entregado deberá cumplir con la calidad esperada por el cliente, pero debe estar alineado con los items del Product Backlog, armado y priorizado por el Product Owner.
Como escribía más arriba, el Product Backlog inicial no es necesariamente EL Product Backlog final. Pero los cambios, de items, de prioridades, deben ser hechos por el Product Owner. El Equipo podrá levantar la mano, sugerir cambios, pero la decisión de cualquier modificación, recae en el Product Owner. Y éste no deberá cambiar los items por cualquier causa: deberá consultar con los interesados en el proyecto, con los que conocen del negocio, y estar atento a cualquier cambio en el entorno, para poder priorizar los items que son necesarios mantener en el Product Backlog.
Vean entonces, la importancia del rol del Product Owner. De hecho, hay cursos especiales de entrenamiento de Product Owners, en el ambiente de Scrum. Muchas de las decisiones importantes pasan por él. Por supuesto, no son decisiones en solitario, consulta y recibe asesoramiento de otros interesados. Pero un Product Owner debe ser alguien que realmente se empape del negocio y del producto que queremos lograr. Puede que no sepa todo, pero debe tener el acceso a la información y al conocimiento de otras personas, y tener una mente y actitud de aprendizaje y atención al negocio.
Uno de los anti-patrones de Scrum que mencionaba en el post Anti-Patrones de Sprint era Demasiados cambios en los requerimientos, entre Sprints. Román Mussi comentaba:
Angel, sobre esto:
"Demasiados cambios en los requerimientos, entre Sprints"
Esto no estaría dependiendo del Product Owner? Y en ese caso... como puede intervenir el ScrumMaster para mitigar el problema?
Ciertamente, es un problema que puede nacer de un Product Backlog cambiante. Quisiera aclarar que los cambios pueden ser necesarios: tal vez el negocio de seguros cambión, y la plata ahora está en asegurar camiones: los seguros de vida donde poníamos nuestras fichas fueron afectados por algo, como la llegada de un competidor del extranjero, un cambio en la legislación, o lo que sea. Y esos cambios, el equipo debe enfrentarlos, sin perder impulso, sin sentir el “dolor del cambio”. Scrum, como todo lo ágil, está preparado para fomentar la aceptación del cambio, no de luchar contra él. Pero el anti-patrón aparece si los cambios no son producidos por una nueva evaluación del negocio.
Los cambios así sin sentido de negocio, pueden venir de varias causas. Por ejemplo, un Product Backlog débil inicialmente, que no estaba claro al comienzo, puede ir mejorando al ir entendiéndose mejor el producto a producir, y el negocio en el que está inserto. Igualmente, pediría tratar de evitar esta situación: antes de lanzar el proceso, debería quedar más claro el Product Backlog. No habría que escatimar esfuerzo en tener un buen Product Backlog. Insisto: puede que no sea el final, pero deberíamos haber invertido un tiempo para no desperdiciar tiempo y esfuerzo del equipo. Es claro que no esperamos un “gran diseño inicial”, no es un tema de diseño técnico: es tema de sentido común, sobre lo que queremos obtener.
Pero, por lo menos, si lo anterior tiene olor de anti-patrón inicial, por lo menos el documento evoluciona hacia algo mejor, más firme. Pero otra causa para que aparezca “mal olor” en el Product Backlog (más frecuente de lo esperado, en especial en proyectos largos), es ceder a las presiones externas: de pronto, por atender lo urgente (“tenemos que tener en línea los seguros de autos para la exposición Car2009 que comienza dentro de un mes”), o requerimientos internos de gente con poder en el cliente (“mi división necesita los seguros de camiones para ayer”), el Product Owner cede y cambia el Product Backlog. A ver, pongamos alguna aclaración y contexto: si realmente el futuro de la empresa depende del impacto que tenga en la exposición de autos que viene, entonces es válido el cambio (yo preguntaría entonces: esa exposición estaba planeada desde hace un año, por qué ese cambio de dirección no se previó antes?). Pero si solamente es un cambio promovido por urgencia, y no por importancia, estamos atacando el proceso.
De alguna forma, todo lo ágil, más allá de Scrum, nos trata de proteger del síndrome “lo urgente mata lo importante”. El Product Backlog es el documento primordial, que guía las decisiones del resto del proyecto. El tener un Product Backlog “manteca”, que cambia de forma a cada momento, o según “cómo calienta el sol”, que se modifica incluso en el medio del Sprint (los dioses de Scrum no lo permitan!!), es síntoma de estar reaccionado a lo urgente, en vez de actuando sobre lo importante. El Product Owner, ayudado por el Scrum Master, y el compromiso de la dirección, deberá encarar ese problema.
Espero que haya quedado claro la importancia del rol del Product Owner (en mi postura, el eslabón más débil en Sprint, por ser el que concentra tantas decisiones), y la salud del Product Backlog. Pienso que agregando ejemplos negativos al final, quedó mejor transmitido ese mensaje. He visto proyectos bien llevados, donde todo esto pasa desapercibido, justamente, porque es lo natural. Poner énfasis en los problemas, nos ayuda a entender por qué funciona un proyecto Scrum bien manejado.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Este sábado 28 de noviembre, la comunidad ALT.NET Hispano organiza una nueva VAN (Reunión virtual). Esta vez el horario (tomen nota) será 19:00 GMT/UTC (4 de la tarde por aquí en Buenos Aires, Argentina). El tema será el uso de Mocks, en nuestras pruebas automatizadas. La presentación del tema estará a cargo del bueno de Hadi Hariri (que pueden seguir en Twitter en @hhariri). Hadi vive en España, se presenta en su sitio:
http://hadihariri.com
de esta manera:
I'm a software developer and work as Tech Lead for iMeta Technologies. I also give talks and presentations. I love to travel and luckily get to do so when speaking at conferences. My main passions are Software Architecture, Web and TCP/IP development. I live in Málaga, with my wife Katya and my two wonderful sons, Maxim and Sasha. I run the local .NET User group for Málaga and the province. If you live in Málaga or are visiting, drop me a line.
Pueden leer sobre sus conferencias e intereses en:
http://hadihariri.com/blogengine/page/Conferences.aspx
http://hadihariri.com/blogengine/archive.aspx
El enlace a usar es http://snipr.com/virtualaltnet. La información sobre las VAN que vienen, están en la página del Calendario de ALT.NET Hispano. Ahí leo más detalles sobre esta reunión de mañana sábado:
La comunidad ALT.NET Hispano (http://altnethispano.org) realizará un evento virtual con el tema "Mocking" (e "Inyección de Dependencias"), a cargo de Hadi Hariri. Fecha: Sábado 28 de Noviembre a las 19:00 hrs. Hora Internacional (GMT/UTC), con una duración aproximada de 2 horas.
Lugar: Para atender la reunión deben usar el enlace: http://snipr.com/virtualaltnet el cual les demandará el uso del programa Microsoft Office Live Meeting 2007 Client. En esta ocasión la desconferencia estará a cargo de Hadi Hariri, Visual C# MVP, quien es consultor y desarrollador ante todo, así como apasionado de la arquitectura de software y el desarrollo de aplicaciones web. Es ponente habitual en conferencias sobre .NET y Win32, y ha escrito numerosas publicaciones.
Descripción: En esta charla primero repasaremos la inyección de dependencias e Inversión de Control y profundizaremos en los frameworks de Mocks. Veremos cómo funcionan, éstos últimos, así como también cómo sacarle el máximo de partida a ellos para hacer tests sostenibles. Examinaremos las diferencias entre Mocks y Stubs así como diferencias entre pruebas de estado e interacción.
Algunas páginas a revisar:
Inversion of Control Containers and the Dependency Injection pattern
Mocks can be your friend, or your worst nightmare
Mocks Aren't Stubs
Rhino Mocks
Moq
TypeMock
NMock
Pueden plantear sus comentarios e inquietudes sobre el tema de la reunión en: http://groups.google.com/group/altnet-hispano/t/57766b68494fe859 Para mayor información sobre cómo atender la reunión consulten: http://tinyurl.com/van-hispano Pueden vincular el Google Calendar al suyo (http://screenr.com/nr7), o bien descargar el iCal de este evento en particular: http://altnet-hispano.pbworks.com/f/VAN20091128.ics
Si no conocen qué es una reunión VAN, pueden consultar VAN meetings. Para ver cómo se desarrolla una VAN de ALT.NET Hispano, y qué software necesitan para asistir, ver Descripcion-de-Reuniones-VAN. Pueden ver el historial de anteriores reuniones VAN (visiten las que dieron, por ejemplo, sobre NHibernate, WPF y demás) (yo participé en VAN sobre Scrum y en otra sobre generación de código). También pueden suscribirse para proponer nuevos temas, y colaborar con la comunidad. Si no pueden asistir a ésta VAN, seguramente quedará publicada más adelante, con video incluido.
Con respecto a Mocks, y librerías de mocking, he dejado enlaces en:
http://delicious.com/ajlopez/mocks
http://delicious.com/ajlopez/rhino
http://delicious.com/ajlopez/moq
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
En estos días, estuve trabajando en generar código de clases C#, usando como punto de partida los archivos .hbm, que se usan en NHibernate para especificar el mapeo de clases y tablas de bases relacionales. Como es usual, cuando encaro algo de generación de código uso AjGenesis, mi proyecto open source de generación de código (practico el “dog fooding” :-).
(English version of this post Generating code with AjGenesis using NHibernate hbm files)
Pueden bajar un ejemplo de lo que estoy haciendo de mi Skydrive:
Examples > AjGenesis > NHibernateMappingExample01.zip
(el código en desarrollo está en el trunk, en este change actual, en el directorio examples\NHibernateMappinp:

pero si quieren ir directamente al ejemplo, pueden bajárselo completo desde el Skydrive que mencioné, que incluye el ejecutable de AjGenesis de la versión en desarrollo, no necesitan compilar nada).
Luego de expandir el archivo del ejemplo, tendrán este contenido:

Para crear clases C#, pueden probar de ejecutar los comandos:
GenerateClasses AjFirstExample
GenerateClasses AjTest
Para crear un proyecto .NET con los archivos .cs y .hbm, y una solución, ejecutar:
GenerateProject AjFirstExample
GenerateProject AjTest
Los archivos generados, en ambos casos, quedan en el directorio Build.
Hay dos proyectos ejemplo que son AjFirstExample, con dos mapeos simples, y AjTest, que tiene mapeos más interesantes, con “bags” y relaciones “many to one”.
En el ejemplo, cada proyecto se describe con un simple archivo Project.xml:
<Project Name="AjTest">
</Project>
En cuanto necesite más información, lo agregaré ahí, o en tags meta de los propios archivos de mapeo y configuración.
Este es uno de los archivos de mapeo que sirven de modelo inicial para este ejemplo de generación, en Projects\AjTest\Mappings, Department.hbm:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="AjTest.Entities"
namespace="AjTest.Entities"
>
<class name="Department" table="departments">
<id name="Id" column="Id" type="Int32">
<generator class="native"/>
</id>
<property name="Description" type="String"/>
<bag name="Employees" lazy="true" inverse="true" cascade="all">
<key column="IdDepartment"/>
<one-to-many class="AjTest.Entities.Employee, AjTest.Entities"/>
</bag>
</class>
</hibernate-mapping>
Este es el código generado para este mapeo, Department.generated.cs:
using System;
using System.Collections.Generic;
using Iesi.Collections.Generic;
namespace AjTest.Entities
{
public class Department {
public int Id { get; set; }
public string Description { get; set; }
public IList<Employee> Employees { get; set; }
public Department()
{
this.Employees = new List<Employee>();
}
}
}
Veamos el proceso de generación. Este es el contenido de GenerateProject.cmd:
@echo off
set ProjectName=%1%
if "%1%"=="" set ProjectName=AjFirstExample
Bin\AjGenesis.Console.exe Projects\%ProjectName%\Project.xml Tasks\AddMappings.ajg Tasks\BuildCSharp.ajg
xcopy Libraries\*.* Build\%ProjectName%\CSharp\Src\Libraries /Y /Q
La línea más importante es la que invoca a AjGenesis.Console.exe. El contenido de Project.xml se carga en memoria. La tarea AddMapping.ajg se carga y ejecuta (está escrita en un lenguaje dinámico, afectuosamente llamado AjBasic), y luego, se procesa la tarea BuildCSharp.ajg. Veamos el código de AddMapping.ajg:
' Add mappings from directory if not specified in Project model
Include("Utilities/Utilities.tpl")
if not Project.Mappings then
Project.Mappings = CreateList()
di = new System.IO.DirectoryInfo("Projects/${Project.Name}/Mappings")
for each fi in di.GetFiles("*.hbm.xml")
filename = fi.Name
Project.Mappings.Add(filename.Substring(0, filename.Length - 8))
end for
end if
Encuentra y agrega los nombres de los archivos de mapeo contenidos en el directorio de Mapping, dentro del proyecto (noten que se pueden usar clases y objetos del framework .NET). Una tarea más interesante es la GenerateCSharp.ajg. Primero, carga la dll de NHibernate, para usar más adelante su parser de archivos hbm:
include "Utilities/Utilities.tpl"
include "Utilities/FileUtilities.tpl"
include "Utilities/TypeUtilities.tpl"
Include("Utilities/NHibernateUtilities.tpl")
include "Templates/CSharp/UtilitiesCs.tpl"
include "Templates/CSharp/CSharpFunctions.tpl"
AssemblyManager.LoadFrom("Libraries/NHibernate.dll")
parser = new NHibernate.Cfg.MappingSchema.MappingDocumentParser()
Crea objetos dinámicos, donde coloca información de la solución y el proyecto a crear:
if not Project.BuildDir then
Project.BuildDir = "Build/${Project.Name}/CSharp"
end if
message "Creating Directories..."
FileManager.CreateDirectory(Project.BuildDir)
FileManager.CreateDirectory("${Project.BuildDir}/Sql")
FileManager.CreateDirectory("${Project.BuildDir}/Src")
FileManager.CreateDirectory("${Project.BuildDir}/Src/Libraries")
message "Defining Solution and Projects..."
Project.Solution = CreateObject()
Project.Solution.Guid = "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"
Project.Solution.Projects = CreateList()
message "Defining Entities Project..."
PrjEntities = CreateObject()
PrjEntities.Includes = CreateList()
PrjEntities.Guid = CreateGuid()
PrjEntities.COMGuid = CreateGuid()
Project.Solution.Projects.Add(PrjEntities)
Project.Entities = CreateList()
Ahora, itera sobre cada archivo hbm, lo lee usando el parser del propio NHibernate, toma información sobre las clases a generar:
for each MappingName in Project.Mappings
filename = "Projects/${Project.Name}/Mappings/${MappingName}.hbm.xml"
mapping = parser.Parse(OpenAsStream(filename))
for each hbmclass in mapping.Items where IsType(hbmclass, "HbmClass")
Entity = CreateObject()
Project.Entities.Add(Entity)
Entity.ClassName = hbmclass.name
Entity.Namespace = mapping.namespace
' Namespace as default project name for Entities Project
if not PrjEntities.Name then
PrjEntities.Name = mapping.namespace
PrjEntities.Directory = "${Project.BuildDir}/Src/${PrjEntities.Name}"
FileManager.CreateDirectory(PrjEntities.Directory)
end if
Entity.Properties = CreateList()
if hbmclass.Id then
Property = CreateObject()
Property.Name = hbmclass.Id.name
Property.Type = HbmTypeToCSharp(hbmclass.Id.type1, Entity.Namespace)
Entity.Properties.Add(Property)
end if
for each item in hbmclass.Items
if IsType(item, "HbmProperty") then
Property = CreateObject()
Property.Name = item.name
Property.Type = HbmTypeToCSharp(item.type1, Entity.Namespace)
Entity.Properties.Add(Property)
end if
if IsType(item, "HbmManyToOne") then
Property = CreateObject()
Property.Name = item.name
Property.Type = HbmTypeToCSharp(item.class, Entity.Namespace)
Entity.Properties.Add(Property)
end if
if IsType(item, "HbmSet") then
Property = CreateObject()
Property.Name = item.name
Property.IsSet = true
Property.Type = HbmTypeToCSharp(item.Item.class, Entity.Namespace)
Entity.Properties.Add(Property)
end if
if IsType(item, "HbmBag") then
Property = CreateObject()
Property.Name = item.name
Property.IsList = true
Property.Type = HbmTypeToCSharp(item.Item.class, Entity.Namespace)
Entity.Properties.Add(Property)
end if
end for
end for
end for
Pueden extender esta capacidades, procesando más tags (debería escribir un ejemplo usando los tags meta que puede contener el hbm; ya utilitarios de Java, como el venerable XDocLet, usaban esos tags para ayudarse en la generación de código, en Hibernate), y detectar más formas de mapeo de NHibernate. Ahora, pasa a la generación de código:
for each Entity in Project.Entities
TransformerManager.Transform("Templates/CSharp/Entity.tpl", "${PrjEntities.Directory}/${Entity.ClassName}.generated.cs", Environment)
PrjEntities.Includes.Add(CreateFileCs("${Entity.ClassName}.generated"))
end for
La tarea genera los archivos .cs, y también crea un archivo de solución y otro de proyecto C#, copiando y embebiendo los archivos de mapeo originales:
for each MappingName in Project.Mappings
filename = "Projects/${Project.Name}/Mappings/${MappingName}.hbm.xml"
targetfilename = "${PrjEntities.Directory}/${MappingName}.hbm.xml"
System.IO.File.Copy(filename, targetfilename, true)
PrjEntities.Includes.Add(CreateFileType(MappingName,"hbm.xml"))
end for
for each CsProject in Project.Solution.Projects where CsProject.ProjectType<>"Web"
FileManager.CreateDirectory(CsProject.Directory)
FileManager.CreateDirectory(CsProject.Directory & "/Properties")
TransformerManager.Transform("Templates/CSharp/CsProject.tpl", "${CsProject.Directory}/${CsProject.Name}.csproj", Environment)
TransformerManager.Transform("Templates/CSharp/AssemblyInfoCs.tpl", "${CsProject.Directory}/Properties/AssemblyInfo.cs", Environment)
end for
TransformerManager.Transform("Templates/Solution.tpl", "${Project.BuildDir}/Src/${Project.Name}.sln", Environment)
Esta es la solución generada:

Próximos pasos
Debería trabajar en algunos puntos:
- Generar una solución más completa, como en otros ejemplos de AjGenesis (con un proyecto de infraestructura, un proyecto de Service Layer o similar, una presentación web, etc…).
- Soportar más opciones de mapeo de NHibernate.
- Usar los tags meta.
Por ahora, pueden jugar con este ejemplo. Pueden cambiar los templates para generar más artefactos, por ejemplo, código VB.NET.
Gracias a @fabiomaulo por avisarmr de las capacidades públicas de parser de hbm dentro de NHibernate!
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Soy un gran usuario de Twitter. Generalmente, uso TweetDeck como cliente, aunque a veces voy por la interfaz web. Twitter es la implementación de un idea simple (mensajes cortos, podemos seguir a quien querramos que tenga perfil público, nos pueden seguir y dejar de seguir en cualquier momento (noten los cambios de Facebook a tener perfiles públicos, veo que motivados por la facilidad que se da en Twitter)) Todo eso ha cambiado la forma en que interactuamos. En especial, en el ambiente del desarrollo del software, Twitter es un gran complemente (podría ser un reemplazo) a los lectores de feeds. Veamos un ejemplo de lo efectivo que puede ser.
Todo comenzó ayer sábado, con un mensaje de @jfroma, desarrollador de software argentino, como yo, que escribía:

Yo no había leído todos sus mensajes del viernes, así, que curioso sobre ese comentario, fuí y los leí. El mensaje original aludía al patró Model View View Model. Sé que José (@jfroma) ha estado trabajando en ejemplos de data binding en WPF usando modelos recuperados con NHibernate, así que seguí el link que apuntaba al usuario @michaellperry, para leer sus mensajes. Era mi primer contacto con Michael:

Encontré, entre sus mensajes del viernes, esta presentació:
Session Detail: Data binding without INotifyPropertyChanged
preguntando para confirmar a @jfroma:

Ahora, tenía más contexto (una frase que repito muchas veces: con contexto, uno se puede manejar más entre la información que recibe). Con todo esto, descubro los intereses de Michael en su blog (noten cómo Michael usa su estado Twitter a la izquierda):
http://adventuresinsoftware.com/blog

Descubrí la librería de código abierto de la presentación de Michael:
http://updatecontrols.net

Como siempre que encuentro algo interesante, ya sea para mí, o que pienso que puede ser interesante para alguien, comencé a tweetear sobre el tema. Al rato, veo que @jyinglee desde China, también tomó nota, haciendo RT de mi mensaje:
Todo comenzó con un simple mensaje. Este es el poder de Twitter, es“serendipity with help” (descubrimiento accidental con ayuda), con la ayuda de gente interesante que nos sigue y a la que seguimos.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Este sábado 21 de Noviembre, tendremos VAN (reunión virtual) organizada por la comunidad ALT.NET Hispano. El tema será ASP.NET MVC, en particular, la versión 2. Como siempre, la reunión no será sólo una exposición, sino también discusión, preguntas, ejemplos, recursos, opiniones. Hasta donde sé, el horario es el de siempre 5:00pm GMT (2 de la tarde acá en Buenos Aires). Y en enlace a usar es http://snipr.com/virtualaltnet (más detalle sobre software y qué es una VAN al final de este post).
La presentación inicial estará a cargo de Cristian Prieto, Microsoft ASP.NET MVP, MCPD ASP.NET Web Development Applications 3.5, MCTS Workflow Foundation 3.5:
http://www.cprieto.com/ (me gusta el título “IDisposable Thoughts” :-)
Hi, My name is Cristian Prieto, I'm a Senior Software Developer living in Guatemala, Central America. I mainly "speak" in .Net languages (like C#, F# and _even_ VB.NET) but I really love programming in Python/Ruby/Erlang. When I'm not programming (or speaking at a .net user group) I enjoy reading and spend my life with my beautiful wife (Emy) and my three cats: Cocco, Motto and Chester
Pueden seguirlo en Twitter como @cprieto:
y en LinkedIn como http://www.linkedin.com/in/cprieto. Ahí leemos su experiencia:
- Experienced Web Developer with more than 9 years in technologies like ASP.NET, PHP, Python, JavaScript and distributed programming.
- Agile software developer proficient with patterns and best practices like Test Driven Development, Behavior Driven Development and Continuous Integration.
- Lover of agile process based development like Lean Development, Kanban and Scrum.
- Technical Community Leader, mentor of new development trends and best practices. Awarded Microsoft ASP.NET MVP 2009
- Accustomed to work with many languages and tools.
- Self-thought and early adopter
Cristian Prieto’s Specialties:
ASP.NET, SQL Server, Web Development in general
Python, Best practices, Multi tier application development, Agile development (lean, kanban, scrum)
Escribe el bueno de Cristian en la lista de ALT.NET Hispano, cuál va a ser el tema de la charla:
Como ustedes recordaran, este sábado 21 de noviembre tendremos la VAN acerca de ASP.NET MVC 2, quería comentar un poco de que esperar para esta VAN (bueno, quizás también por parte del nerviosismo de ser mi primera VAN :P)
ASP.NET MVC fue "cocinado" durante 1 año y mientras tanto nos mantubieron pegados a la silla con 5 CTP's y un par de betas... después de varios meses hemos visto aplicaciones en producción con la plataforma, 5 libros acerca del tema, muchos y muchos webcasts (hay 2 en alt.net hispano :D) y conferencias de "cómo explotarla", multiples proyectos de ejemplo.... y, obviamente, muchas preguntas luego de hacer el "hola mundo".
¿Qué pasa cuando necesitamos algo más que el típico proyecto de NerdDinner? ¿Qué pasa cuando mi aplicación realmente no es un típico ejemplo? ¿Dónde pongo la lógica? ¿Cómo divido y saco provecho de la framework? ¿Qué otras cosas podemos tener bajo la manga para hacernos la vida más sencilla?
Para aclarar estas dudas, examinaremos desde el punto de vista histórico y práctico con qué solemos comenzar y hasta dónde lo podemos llevar, mencionando cosas como MvcContrib y MvcTurbine y dónde encajan cosas como SharpArchitecture en todo esto...
¿Porqué menciono todo esto si la charla es de ASP.NET MVC 2?, simple, porque gran parte de los "problemas" que solemos encontrarnos con ASP.NET MVC vienen o prometen venir solucionados en la "cajita" de la versión 2...
Espero verlos en la VAN, y espero que les guste lo que he preparado :)
Todo indica que va a ser una VAN muy interesante: el título del mensaje (y de este post) alude a un proyecto “fracaso” Oxite, con código disponibl, que fue critica por la comunidad por los “bad smell” que presentaba en la implementación, y a CodeCamp, un nuevo proyecto de código abierto, que sirve de muestra de mejores prácticas con ASP.NET MVC (Model View Controller). Cristian menciona también a proyectos como SharpArchitecture, MvcContrib y MvcTurbine.
Si no conocen qué es una reunión VAN, pueden consultar VAN meetings. Para ver cómo se desarrolla una VAN de ALT.NET Hispano, y qué software necesitan para asistir, ver Descripcion-de-Reuniones-VAN. Pueden ver el historial de anteriores reuniones VAN (visiten las que dieron, por ejemplo, sobre NHibernate, WPF y demás) (yo participé en VAN sobre Scrum y en otra sobre generación de código). Supongo (pero confirmen) que la URL de entrada de esta VAN será http://snipr.com/virtualaltnet. Cualquier cosa, pueden consultar la lista de correo de ALT.NET Hispano. También pueden suscribirse para proponer nuevos temas, y colaborar con la comunidad. Si no pueden asistir a ésta VAN, seguramente quedará publicada más adelante, con video incluido.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
En general no anuncio los cursos que estoy por dar (la difusión queda a cargo de cada institución), pero este es un curso que quiero destacar, porque trata de un tema que pienso que todo grupo de desarrolladores por lo menos tendría que conocer y practicar en algún momento. Es un curso que hace unos meses que no estoy dando por Buenos Aires, y siempre he tenido buenas experiencias dándolo.
Gracias a la gente del Microsoft User Group de Argentina, daré un curso de Scrum con una explicación inicial, y luego todo práctica, el miércoles 2 de diciembre de 2009. Pueden ver más datos, costos, y forma de inscribirse en:
Jornada de Scrum, teoría y práctica
El contenido (lo copio de ahí):
- El Equipo de trabajo. Los Roles: ScrumMaster. Product Owner. Daily Scrum. Chickens y Pigs. ScrumMaster vs Project Manager.
- Objetivos: Control empírico del proceso de desarrollo. Dar visibilidad de lo que se está haciendo. Generar una relación de confianza y comunicación constante entre el cliente y el equipo.
- Los Conceptos: Iteraciones. Autoorganización. Descripción del método.
- La Documentación: Qué es, cómo se arman y cómo se utilizan el Product Backlog, el Sprint Backlog y Burndown Chart.
- La Práctica: Se formarán equipos de trabajo, que resolverán un caso práctico. Se asignarán los roles y se discutirá cada caso en particular, buscando arribar a la solución al final de la jornada.
Lo importante es el trabajo práctico. Iremos descubriendo juntos algunas características, prácticas, y el por qué de cada cosa, en el marco de trabajo Scrum.
Para los que no puedan asistir, recuerden que siempre escribo por acá sobre el tema en posts sobre Scrum. Ahí encontraran un varios posts, con enlaces, referencias, presentaciones, sobre el tema Scrum y ágil en general. Los posts primeros a revisar, con material relacionado, incluso un video de una charla y discusión sobre el tema, en:
Resultado de la VAN en ALT.NET Hispano sobre Scrum
Scrum Práctico
Scrum Práctico en Santa Fe
Explicando Scrum
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
En esta serie de post, aún falta que escriba describiendo de principio a fin lo que es Scrum. Para llegar a ese punto, primero quiero compartir con Uds. esta traducción de un post de Tobias Mayer, quien fue mi instructor de Scrum Mastering en 2006. El post original, en inglés, lo encuentran en:
Essence of Scrum
Acá va mi traducción:
Scrum comenzó su vida como uno de las nuevas formas Agiles para construir software. En estos días, se lo considera una forma que puede ser usada para mejorar el mundo del trabajo, en un sentido más general, y así, cambiar la forma en que los individuos piensan e interactúan con otros en situaciones de trabajo. El potencial completo de Scrum está por explorar.
En resumen, Scrum es una manera simple de manejar problemas complejos, proveyendo un marco de trabajo para soportar la innovación y permitir que equipos auto-organizados entreguen resultados de alta calidad en tiempos cortos. Scrum es un estado de la mente; en una manera de pensar que libera el espíritu creativo mientras se mantiene firmemente apoyado en principio sólidos y largamente respetados, incluyendo el empirismo, la emergencia y la auto-organización.
Empirismo se refiere al proceso continuo de inspeccionar/adaptar que permite que tanto trabajadores como gerentes tomen decisiones en tiempo real, basado en datos actuales, y como resultado, puedan responder rápidamente a condiciones siempre cambiantes que se presentan en el ambiente, como por ejemplo, el mercado donde el software a construir es vendido o distribuido.
La Emergencia surge de una aproximación empírica. Implica que todas las soluciones a todos los problemas se volverán claros a medida que trabajamos. No se volverán claros si simplemente hablamos de ellos. El “Big Up Front Design” (gran diseño de antemano) sólo producirá un “Big Wrong Design” (gran diseño erróneo) o a lo sumo un “Big Working But Totally Inflexible Design” (gran diseño que funciona pero totalmente inflexible). Cuando permitimos que las soluciones emerjan es siempre la solución más simple y apropiada, para el contexto actual, la que sube a la superficie. La emergencia junto con el empirismos nos guiaran a la solución más apropiada y flexible (es decir, que podemos cambiar).
Auto-organización se refiere a la estructura de los equipos que crean el producto. Se les da poder a pequeños equipos multidisciplinarios para que puedan tomar decisiones importantes, necesarias para 1) crear un producto de alta calidad, y 2) manejar su propio proceso. Acá la idea es que aquellos que hacen el trabajo conocen mejor que nadie cómo hacer el trabajo. Estos equipos trabajan de una manera altamente interactiva y generativa, donde el producto emerge del diálogo continuo, de la exploración e iteración. La auto-organización funciona cuando hay objetivos y límites claros.
Además de estos principios, Scrum se apoya en dos mecanismos principales: priorización y “timeboxing” (poner límites de tiempo a una tarea).
Priorización simplemente significa que hay cosas que son más importantes que otras. Esto es tan obvio que se olvida muchas veces cuando pensamos “necesitamos esto AHORA”. Scrum nos ayuda a poner el foco de vuelta en seleccionar cuáles son las cosas más importantes a hacer primero, y entonces, a hacerlas! Tomándose el tiempo para priorizar, y siendo rigurosos sobre eso, es esencial para el éxito de Scrum.
Timeboxing es un mecanismo simple para manejar la complejidad. No podemos imaginar el slistema completo de una vez, todo junto, entonces, tomamos un pequeño problema y en un corto espacio de tiempo, digamos una semana o un mes, trabajamos en solucionar ese problema. Los resultados de esa acción nos guiaran entonces a una solución para el próximo problema, más grande, y nos dará más conocimiento sobre las necesidades del sistema en conjunto.
Cambio organizacional
Con Scrum, las jerarquías de gerencia de las organizaciones tienden a ser niveladas y los equipos de desarrollo tienen más contacto directo e inmediato con los clientes. El ambiente de trabajo se vuelve menos “comandar-y-controlar” hacia un estilo más colaborativo. Se promueve el diálogo regular y abierto sobre la documentación extensiva, y el acuerdo negociado es preferido a los contratos de trabajo formales e impersonales.
Las cualidades de apertura, honestidad y coraje son fomentadas en todos los niveles, y la ganancia individual se vuelve secundaria ante el avance colectivo. Un ambiente Scrum es uno que soporta a la gente, donde las personas de todos los niveles muestran respeto y confianza entre ellos. Las decisiones se toman por consenso, más que por imposición de alguien de más arriba, y todo el conocimiento es compartido, de una manera transparente y sin recelos.
Scrum va en contra de lo que hacen muchas compañías de la industria del software, donde una forma en fases acoplada con un alto grado de micro-gerenciamiento, y una insistencia en procesos definidos y documentación extensiva, se han hecho la norma por treinta años. Muchas compañías se basan en el miedo y el dinero como motivaciones claves para sus trabajadores. Esta forma de trabajo ha mostrado éxitos a corto plazo, pero más y más compañías están comenzando a entender que no es una buena estrategia para el largo palzo. Sin embargo, el concepto de cambiar a algo tan radical como Scrum aterroriza a muchos corazones de ejecutivos y gerentes de nivel medio.
Scrum está aún en la etapa de los “early-adopter” (los que abrazan tempranamente las nuevas ideas). Tomará muchos años para que la mayoría de las compañías reconozcan los beneficios de crear más lugares de trabajo, llenos de confianza. Sin ese cambio, muchas compañías de software se irán hundiendo bajo el peso de sus procesos pesados, y fuerzas de trabajo sobrecargadas. Otros, aquellos que abracen el método liviano, ágil, de Scrum, tendrán la gran oportunidad de sobrevivir y prosperar. Para aquellos que pasen a Scrum, y lo abracen completamente, la vuelta atrás a a los viejos días de trabajo será impensable. Un cambio de paradigma está ocurriendo en el lugar de trabajo, y Scrum es una parte importante de ese cambio.
Nota: el término Scrum proviene de un “paper” titulado The New New Product Development game de Hirotaka Takeuchi y Ikujiro Nonaka. En rugby, un scrum es una forma de recomenzar el juego, luego de una infracción accidental o después que la pelota salió de juego. La práctica de Scrum en el mundo del software incluye reuniones regulares diarias y cortas donde los miembros del equipo se juntan para comunicar su progreso. Debido a la similitud entre la pausa del juego (trabajo), y habiendo los jugadores (miembros del equipo) armado la reunión, ésta se conoce comúnmente como el Daily Scrum. Jeff Sutherland, John Scumniotales y Jeff McKenna son los responsables de haber introducido el término Scrum en el mundo del desarrollo del software en 1993, mientras trabajaban en la Easel Corporation, una compañía de herrmientas de software de Massachusetts. Ken Schwaber escribió el “paper” original sobre Scrum, SCRUM Development Process, que fue presentado en la conferencia OOPSLA en 1995.
Otras referencias:
Scrum: its place in the world
Scrum for Software Development
Gracias a Tobias por tan buena descripción de Scrum.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
More Posts
Next page »