VAN sobre principios SOLID en AltNetHispano

El sábado pasado participé como ponente en una VAN (reunión virtual) de AltNetHispano sobre principios SOLID (uno de los temas que más me gusta de esta profesión). Aquí podrán encontrar el listado completo de videos de VANs o verla directamente aquí:

Presentación: aquí. Código antes de aplicar los refactorings: aquí.

Les dejo el video gentilmente editado por la gente de AltNetHispano, si quieren un adelanto, lean el resumen que dejo abajo.

Quiero compartir en este post es un breve resumen sobre los temas que surgieron como preguntas y las repercusiones con el fin de que sirva de guia para aquel que quiera ver el video de 2 horas y algo más.

Mostré 3 o 4 ejemplos de código real de alguno de mis proyectos o extractado de algún caso real de clientes de consultoría.

En el primer ejemplo transformamos una clase que violaba claramente el principio de responsabilidad única. Separamos el código en dos clases. Luego avanzamos un poco más sobre el caso analizando una violación al principio de inversión de la dependencia y también codificamos una solución.

En el segundo ejemplo tomamos como base una consulta hecha por Edgar Ramos la lista de AltNetHispano, en el que planteaba un problema que me pareció muy útil para demostrar el principio abierto-cerrado.

El tercer ejemplo vimos el principio de segregación de interfaces. Presenté una refactorización del patrón repositorio separándolo en un repositorio básico basado en generics y uno o más Enhanced Query Objects del gran @fabiomaulo (el gran ausente de la VAN, el pobre estaba sin PC, parece).

Hablando sobre el ejemplo anterior conté una anécdota sobre un reemplazo de repositorios que tuvimos que encarar (desde IBatis.NET a NHibernate) y nos costó bastante por estar en clara violación del principio de sustitucion de Liskov.

El cuarto ejemplo fue una respuesta a la consulta de un colega sobre un procesador de archivos basado en reglas que fuera configurable. Propuse una solución basada en interfaces y Windsor como container de inyección de dependencias.

Tanto durante la VAN como en twitter (aquí y aquí) surgieron comentarios interesantes y preguntas (ver repercusión aquí). Sobre todo esto trataré de escribir posts ampliando mis respuestas.

Por último los comentarios que me llenan de orgullo (aquí, aquí y aquí) puesto que vienen de mis colegas, a los cuales también respeto mucho.

Si lo desean pueden descargar la presentación y la

Referencias:

[1] http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
[2] http://en.wikipedia.org/wiki/Solid_(object-oriented_design)
[3] http://www.lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspx
[4] http://blogs.msdn.com/b/cdndevs/archive/2009/07/15/the-solid-principles-explained-with-motivational-posters.aspx
[5] http://cdn.cloudfiles.mosso.com/c82752/pablos_solid_ebook.pdf
[6] http://www.hanselminutes.com/default.aspx?showID=163

Gracias a todos.

Code Camp 2010 en Buenos Aires, aprendiendo entre amigos

Ayer anduve por el CodeCamp 2010 en Buenos Aires y, como siempre, lo mejor fue ver a muchos amigos.

Primero estuve viendo Iron Ruby paso a paso a cargo de Johnny Halife mostrando la integración de componentes escritos en .NET y código Ruby. El ejemplo no fue trivial, diría incluso que interesante para los que aun no nos convencen las técnicas de acceso a datos de Ruby. Jonhy escribio repositorios en .NET y mostro como usarlos desde IronRuby.

Update: Johnny publicó sus comentarios aquí.

Luego del break estuve en el Randori Coding Dojo con Adrian Eidelman y Ruben Altman. Fue una experiencia interesante, estos muchachos se mandaron con una actividad muy difícil ante público desconocido porque depende fuertemente de la colaboración.

El ejercicio propuesto fue la lógica de un tablero de puntuación de tenis y me gusto ya que tiene un nivel de dificultad variado permitiendo atacar cuestiones sencillas al principio. Creo que logramos un buen ejemplo de TDD, pequeños pasos, solo escribir el código necesario para pasar el test, refactoring, etc.

Finalmente salió muy bien, aprendimos varias cosas sobre como llevar adelante este tipo de ejercicios. Seguramente postearé algo al respecto próximamente.

Luego del almuerzo me di una vuelta por la sesión ASP.NET MVC Tips and Tricks de la gente de BalckFish. Me gustaron los tips, muchos ayudan a dar un pasito mas en el esfuerzo por hacer cada vez mas eficiente nuestro software. Pueden encontrar el codigo en un proyecto Visual Studio 2010 aquí.

Por último me di una vuelta por la sesión Productividad mas allá de la velocidad de tus dedos de @kzu y @vga. En la primera parte kzu se mando un ejercicio de TDD interesante pero puso en relieve una vez mas que el TDD es un tema difícil para mostrar en publico y con tiempo acotado. Definitivamente es algo para aprender haciendo en lugar de mirando.

Por último quiero felicitar a Miguel Saez y a Microsoft por la organización, todos los años nos da un buen lugar donde encontrar amigos.

Nos vemos

De como Charly cantó sobre software

En su tema Dinosaurios Charly dice:

Los amigos del barrio pueden desaparecer
los cantores de radio pueden desaparecer
los que están en los diarios pueden desaparecer
la persona que amas puede desaparecer.

y sigue en la segunda estrofa:

Los que están en el aire pueden desaparecer, en el aire.
Los que están en la calle pueden desaparecer, en la calle.
Los amigos del barrio pueden desaparecer,
pero los dinosaurios van a desaparecer.

En el último renglón pronostica que los dinosaurios van a desaparecer como han aparecido y desaparecido innumerables dinosaurios en la industria del software.

Por supuesto que no entraré aquí en detalles sobre cuales son “mis” dinosaurios, seria una discusión inútil puesto que cada uno tendrá los suyos.

Lo mas importante viene a continuación:

Si los pesados, mi amor,
llevan todo ese montón
de equipaje en la mano
Oh! mi amor
yo quiero estar liviano.

y remata con el consejo:

Cuando el mundo tira para abajo
es mejor no estar atado a nada,
imaginen a los dinosaurios en la cama.

Aunque no hace falta que el mundo tire para abajo, la enseñanza para los que diseñamos software es bien directa: debemos andar livianos.

Andar livianos en en diseño de software es elegir con criterio y libertad los frameworks que necesitamos y, sobre todo, descartar lo que no necesitamos. Cuanto mas pequeños e independientes mejor.

No recomiendo esos frameworks que arrastran un montón de otros componentes, muchos menos los monolíticos que “solucionan todo”, desde la persistencia hasta la interfaz a usuario.

Andemos livianos colegas, no nos atemos a nada.

Sabiendo que soy mal comentarista, les dejo la letra y la versión cantada por Charly

Nos vemos.

Dependencias ocultas entre clientes y servicios

Hace unos días, en una revisión de código, encontré una definición de interfaz de un servicio que no me gustó. No fue inmediatamente evidente para mi pero uno de sus métodos era un code smell.

Esta es la interfaz:

<span style="color: blue;">public interface </span><span style="color: #2b91af;">IIpStsStore</span>{
    <span style="color: blue;">void </span>AddCredential(<span style="color: blue;">string </span>userName, <span style="color: blue;">string </span>password);
    <span style="color: blue;">void </span>RemoveCredential(<span style="color: blue;">string </span>userName);
    <span style="color: blue;">bool </span>CredentialExist(<span style="color: blue;">string </span>userName);
}

El método que me olía mal es el último. Luego de exprimir el cerebro un poco me di cuenta del motivo. Ese método, a mi juicio, propicia un acoplamiento innecesario entre el cliente del servicio y la implementación de dicho servicio.

Si exponemos ese método seguramente el cliente del servicio lo va a usar y no tendremos control de este uso, es decir, no sabremos exactamente cuando van a utilizarlo.

Supongamos que la primera implementación de ese servicio accede directamente al recurso donde se almacenan las credenciales. En ese caso, si el cliente llama a AddCredential() e inmediatamente llama a CredentialExist(), todo funcionará correctamente.

El problema aparecerá cuando hagamos otra implementación del servicio IpStsStore que funcione en forma asíncrona. En ese caso ya no habrá garantía de que la secuencia de métodos mencionada mas arriba siga funcionando.

En definitiva, tenemos un acoplamiento entre el cliente y la implementación del servicio, algo que siempre debe tratar de evitarse, además, como suele ocurrir en estos casos, luego de pensar un poco el diseño, ese método tampoco era necesario, un típico caso YAGNI.

Que nunca falte un registro de actividad en tu aplicación. Nunca.

La semana pasada un cliente me llamó debido a que una de sus aplicaciones recién lanzada estaba un tanto inestable. Quiero compartir hoy con ustedes la recomendación que le di, la mas simple y mas efectiva que recuerdo haber dado.

Mas allá de revisar algunas cuestiones directamente relacionadas con las inestabilidades reportadas por usuarios finales, lo primero que les pedí es que me mostraran los logs para enterarme de que no los tenían.

Hoy no hay excusas para no tener información de este tipo en la plataforma .NET, todos los tipos de aplicaciones (Web, Desktop, Servicios, etc.) proveen un mecanismo centralizado de

Aquí algunos consejos básicos:

  • Registren todas las excepciones (básico)
  • No es necesario utilizar try – catch innecesariamente en todo su código, es suficiente con engancharse en el handler centralizado.
  • Registre información con distinto nivel de detalle (los niveles corresponden a log4net pero los demás utilitarios tienen niveles similares), al menos:
    • ERROR: las excepciones, deje que el framework se encargue de mostrar mensajes, callstacks, etc. También registre errores de formato, de protocolo, etc, aunque también podría utilizarse el nivel WARNING (o WARN).
    • INFO: algunos puntos importantes del funcionamiento de la aplicación tales como el inicio, datos de configuración utilizados, finalización, etc.
    • DEBUG: en esta modalidad puede registrarse información mas detallada del funcionamiento de la aplicación.
  • Configure correctamente el nivel de registro en cada ambiente. Generalmente uso nivel INFO en ambientes de producción (que también registra WARN, ERROR y CRITICAL) y nivel DEBUG en ambientes de desarrollo.
  • Use herramientas sencillas (log4net, NLog) y registre la información en simple archivos de texto. Nunca me resulto cómodo utilizar el registro de eventos de Windows.

Para aplicaciones ASP.NET

<span style="color: blue;">protected void </span>Application_Start()
{
    Error += Application_Error;
}

<span style="color: #0000ff; font-size: x-small;"><span style="color: #0000ff; font-size: x-small;">private</span></span><span style="font-size: x-small;"> </span><span style="color: #0000ff; font-size: x-small;"><span style="color: #0000ff; font-size: x-small;">void</span></span><span style="font-size: x-small;"> Application_Error(    </span><span style="color: #0000ff; font-size: x-small;"><span style="color: #0000ff; font-size: x-small;">object</span></span><span style="font-size: x-small;"> sender, </span><span style="color: #2b91af; font-size: x-small;"><span style="color: #2b91af; font-size: x-small;">EventArgs</span></span><span style="font-size: x-small;"> e)

{
</span>
<blockquote><span style="font-size: x-small;">
</span><span style="color: #2b91af; font-size: x-small;"><span style="color: #2b91af; font-size: x-small;">Exception</span></span><span style="font-size: x-small;"> ex = Server.GetLastError();
</span></blockquote>
<span style="font-size: x-small;">
</span>
<blockquote><span style="font-size: x-small;">
log.Error(</span><span style="color: #a31515; font-size: x-small;"><span style="color: #a31515; font-size: x-small;">"Application_Error", ex</span></span><span style="font-size: x-small;">);
</span></blockquote>
<span style="font-size: x-small;">
<blockquote>
Server.ClearError();</blockquote>
}

</span>

Para aplicaciones Desktop

<span style="color: blue;">static void </span>Main()
{
<span style="color: #2b91af;"><span style="color: #333333;">    </span>AppDomain</span>.CurrentDomain.UnhandledException +=
        UnhandledExceptionHandler;

    <span style="color: #2b91af;">Application</span>.Run(<span style="color: blue;">new </span><span style="color: #2b91af;">Principal</span>());
}
<span style="color: blue;">private static void </span>UnhandledExceptionHandler(
    <span style="color: blue;">object </span>sender, <span style="color: #2b91af;">UnhandledExceptionEventArgs </span>args)
{
    <span style="color: blue;">var </span>e = (<span style="color: #2b91af;">Exception</span>)args.ExceptionObject;

    log.Error(<span style="color: #a31515; font-size: x-small;"><span style="color: #a31515; font-size: x-small;">"Application_Error", ex</span></span><span style="font-size: x-small;">);

</span>    <span style="color: blue;">if </span>(<span style="color: #2b91af;">MessageBox</span>.Show(<span style="color: #a31515;">"Reporte este error:\n" </span>+         e + <span style="color: #a31515;">"\n\n¿Desea copiarlo al portapapeles?"</span>,
        <span style="color: #a31515;">"Error en Clasificador"</span>,
        <span style="color: #2b91af;">MessageBoxButtons</span>.YesNo, <span style="color: #2b91af;"><span style="color: #333333;">        </span>MessageBoxIcon</span>.Error) == <span style="color: #2b91af;">DialogResult</span>.Yes)
    {
        <span style="color: #2b91af;">Clipboard</span>.SetText(e.ToString());
    }
    <span style="color: #2b91af;">Environment</span>.Exit(1);
}

Mas informacion:

¿Cuándo estaremos listos para Azure?

En la presentación de ayer en CodeCamp/09 uno de los colegas asistentes preguntó cuando estaría liberado Windows Azure para su uso en aplicaciones en producción.

No tenia idea de la respuesta en ese momento (ahora se que van a anunciarlo en Noviembre en el PDC), sin embargo salto a mi mente otra pregunta: ¿Cuándo estaremos nosotros listos para Azure?

Realmente es un entorno de ejecución diferente del que conocemos y que nos demandará bastante tiempo entender, dominar y encontrar la mejor manera de hacer las cosas.

También importante entender que Azure apunta a resolver problemas que muchos aún no tienen y, seguramente, las concesiones de diseño que se han hecho parecerán limitaciones excesivas. Suena raro que no tengamos file system, que no haya soporte para sesiones in process, que no existan otras comodidades similares pero son “pérdidas” razonables para aplicaciones masivamente escalables.

Estoy seguro de que Azure estará listo mucho tiempo antes que nosotros.

Sean buenos.

Azure en CodeCamp09 – Salió bien

Hace minutos terminamos con Mariano la conferencia sobre Azure en CodeCamp. Todo salió bien, un poco ajustados con el tiempo.

Dejo aquí los links de la charla.

Windows Azure Platform:
http://www.azure.com/

Space de la charla en Assembla:
https://www.assembla.com/wiki/show/prx-guamini

El repositorio con todos los artefactos de la charla:
http://code.assembla.com/prx-guamini/subversion/nodes/trunk

Gracias por venir!

Sean buenos

Azure mejora

Una buena noticia para el sufrido administrador de servicios Azure. El proceso de actualización de un servicio ahora permite realizar la operación en un solo paso: Upgrade.

Hasta hace unos días era necesario seguir el siguiente proceso: a) detener la aplicación; b) borrarla; c) subir la nueva y d) ponerla en marcha.

Aquí se ve la nueva opción:

image

Aquí pueden ver la pantalla que informa sobre el avance del proceso de actualización.

image

Aún hay que esperar varios minutos para que el proceso termine pero al menos puedo dedicarme a otra cosa.

Sean buenos.

CodeCamp 2009

El viernes pasado me enteré de que la charla con que nos postulamos para la edición 2009 de CodeCamp junto con Mariano había sido aceptada.

El título preliminar es “Cloud Computing – Explorando Windows Azure Services” asi que estaremos investigando más profundamente la plataforma Azure.

Publicaré en este blog los avances en el proceso, los interesados estan invitados a volver.

Nos vemos allá.