Carlos Ble

Carlos Ble

I am a professional software developer, I solve problems.

I also teach and mentor developers to build better software.

Working as an independent professional since 2009.

Can I help you?

  • Do you need high quality tailor-made software?
  • Need training on TDD, clean code or refactoring?
  • Is it risky? do you need advise?
  • May I pair with you to write better code?

Events

Upcoming public training courses:

  1. [in English] May 5, 6 & 7
    TDD - Train the Trainers (iSQI)
    Potsdam, Berlin
  2. [en Español] 23, 24 y 25 de Abril.
    Curso de TDD con examen de certificacion iSQI
    Madrid
  3. [en Español] 29, 30 y 31 de Octubre.
    Curso de TDD con examen de certificacion iSQI
    Madrid

Conferences:

  1. I'll be at SocratesUK 2014
  2. I'll be at the London Test Gathering Workshops.

Archive for July, 2011



Erlang en la #kataplaya

Hoy decidimos desafiar a los #katayunos haciendo una #kataplaya. Una kata a 50 metros del mar, en un bonito pub playero. kataplaya1Aprovechamos el profundo conocimiento de Joel Reymont (@wagerlabs) del lenguaje Erlang y nos pusimos con el String Calculator en este lenguaje. Aquí se ve el código de la primera iteración, hecha con el mejor TDD que pudimos y un segundo snapshot de código demostrando potencia de Erlang pero dejando a un lado TDD.

Erlang es un lenguaje funcional, que NO está basado en el paradigma de la orientación a objetos. Debo confesar que me ha gustado mucho. Yeray Darias y yo hemos disfrutando viendo nuestras primeras lineas de Erlang :-)
Me ha gustado más que Lisp y Prolog, aunque ya hace años que no uso ninguno de los dos, pero este parece más limpio (no hay miles de paréntesis juntos). Trabajando con un experto al lado como Joel, hemos podido ver rápidamente por qué Erlang tiene muy buena pinta para escalar. Por un lado, se maneja bastante a bajo nivel, lo que da sensación de ahorrar muchos recursos. Por otro, el estado no se guarda, se procesa. Y al menos en lo que hemos visto hoy, la gestión de la memoria es sencilla, no es como C. Por otro lado, la posibilidad de diseñar una funcion en distintos bloques dependiendo del patterng matching de los argumentos de entrada, evita bastantes bloques condicionales y pareciera que nos ayuda a escribir código más limpio.No te fies de este post como una review seria de Erlang, son sólo mis impresiones despues de dos horas de code kata, en una kata que además es trivial.

A ver para cuándo la siguiente #kataplaya :-)

Individuos e interacciones

Utilizo parte de esta frase del manifiesto ágil para resumir los dos días que la #TLP2k11 nos ha dado oportunidad de ditlp2k11_aeropuertosfrutar en compañia de grandes profesionales. Alberto Perdomo y Alberto Vilches vinieron invitados a Tenerife desde Gran Canaria y Madrid respectivamente. Junto con Yeray Darias y Oscar Moreno, tuvimos ocasión de charlar largo y tendido sobre tecnología, comunidades y desarrollo de software en general. El resultado para mí, muy inspirador como siempre que hay interacción en persona, que es cómo el conocimiento se transmite mejor.

El efecto directo que han tenido para mí estos dias ya se nota: acabo de despublicar el post que escribí hace unos meses rajando de Git. Si alguien quiere recuperarlo seguro que Google lo mantiene en caché tiempo pero @albertoperdomo me ayudó a entender que no era acertado. Aunque ya lo hizo en su día con un comentario al post, su energía en persona cambió mi percepción. Cuando dejamos Git, nosotros teniamos claro que los problemas encontrados quedaban bajo nuestra responsabilidad al no aprender a usar la herramienta correctamente, pero en el blog post le culpaba de los contratiempos que tuvimos. En realidad todo lo que debía haber dicho es que no es fácil de usar, que tiene una curva de aprendizaje alta y que Mercurial me resulta más sencillo. Alberto nos hizo un pequeño tutorial de Git en el aeropuerto que me inspiró a grabar en breve dos screencasts narrados, uno sobre Git y otro sobre Mercurial. Mis clientes me lo llevan pidiendo algún tiempo.

tlp2k11_cenaCiertamente mi blog ya no es el sitio donde puedo publicar lo que yo quiera cuando quiera. Teniendo una media de 100+ visitas diarias cuando no publico nada y entre 400 y 2000 cuando hago un nuevo post (un dia fueron 90.000) , tengo que cuidar más la forma en que me expreso. No puedo publicar en caliente, todo lo más, escribir, releer y publicar un día despues. Si hablo mal de alguna herramienta tendré que hacerlo con los argumentos menos discutibles posibles. Esto no quiere decir que deje de dar mi opinión y que no siga ganando opiniones opuestas pero al menos será más difícil dar lugar a las discusiones fuera de tono. A mi no me parece bien que Linus por ejemplo raje a KDE y Gnome cuando le cuadra y como quiere asi que intentaré no seguir su ejemplo. Logicamente salvando las distancias. Ni soy ni quiero ser una decima parte de mediatico que Linus.

Cambiando de tema, me encantó la frase de @albertovilches: "mi trabajo no sólo debe ser bueno, debe ser excelente" cuando se refería a los desarrollos que hace para sus clientes. Me la voy a copiar con su permiso. He aprendido en las ponencias de ambos que Ruby on Rails y Grails tienen algunos detalles que me gustaría que existieran en Django.Despues de oir a @albertovilches, ya tengo claro que si hay que hacer web sobre stack Java, lo haré con Grails :-)

Otro punto importante fue la guerra de comunidades. Las comunidades de desarrolladores son generalmente como los equipos de futbol. Eres de uno o de otro, y tu equipo es mejor que los demás. Hay demasiado fanatismo. Se dice que la comunidad ágil es fundamentalista porque critica a la gente que no sigue practicas como TDD (o que las sigue pero no lo dice) y sin embargo yo creo que es una imagen distorsionada. Normalmente los más charlatanes de una comunidad, son los que menos se lo curran. Esto ya ocurría con los grupos de usuarios de Linux hace más de 10 años. Se produce endogamia. Cuando un profesional tiene vocación por lo que hace, sus ideas no deberían ser tan distantes de las de otro de igual vocación aunque uno haga Java y el otro Ruby. En el caso Ruby y Java, ambos lenguajes se basan en el paradigma de la orientación a objetos. Un programa bien hecho con Java no debería ser tan distinto de uno bien hecho en Ruby si ambos siguen un buen diseño orientado a objetos. No podríamos decir lo mismo si uno es Erlang y el otro Java. Así que utilizar la comunidad en la que uno participe para tratar de evaluar la profesionalidad de cualquiera de los dos, me parece equivocado.Aunque algunas comunidades como la de PHP se han ganado mala fama, no significa que no haya autenticos profesionales que utilizan PHP. Desde la version 5, ya se puede hacer lo mismo que con otros lenguajes orientados objetos, aunque a mí siga sin gustarme demasiado.

Para llevar la profesión a donde queremos que llegue (que nos dejen de considerar bomberuchos) será cuestión de ser más autocríticos y más abiertos a la hora de intercambiar opiniones con otros colegas.

Sólo me queda felicitar a Innova7 por esta nueva edición de la Tenerife Lan Party, a Yeray Darias (a.k.a Hannibal Smith) por asegurarse que todo salía bien, y a Oscar, Alberto y Alberto por las ganas de trabajar que me contagian y por decir lo que piensan a la cara de una forma educada y razonada.

Es un placer que se hagan eventos de este tipo en casa porque estoy mucho menos estresado que cuando voy fuera :-)

Aprovecho para anunciar que @albertovilches está en la organización de la conferencia Groovy que se hace en noviembre de este 2011 en Madrid: http://greach.es/

pyDoubles 1.3 released

What's new in pyDoubles 1.3?

  1. times statement is also available in spies, not only mocks
  2. stubs ignoring arguments can live together with stubs defined with arguments
  3. a new matcher: obj_with_fields

1: This sintax is now possible:

  1.  
  2. assert_that_method(spy_obj.some_method).was_called().times(2)
  3. or
  4. assert_that_method(spy_obj.some_method).was_called(
  5. ).with_args(SOME_VALUE).times(2)
  6.  

2: The most precise matching condition will be used:

  1.  
  2. when(spy_obj.some_method).then_return(SOME_VALUE)
  3. when(spy_obj.some_method).with_args(10
  4. ).then_return(OTHER_VALUE)
  5.  

The two lines above inside a test would mean the objet will return OTHER_VALUE when the input parameter will be 10 and SOME_VALUE in any other case. In previous releases, it would return SOME_VALUE always because stubs ignoring arguments use to override any other stub definition.

3: obj_with_fields matcher:

  1.  
  2. assert_that_method(spy_obj.some_method).was_called(
  3. ).with_args(obj_with_fields({'id': 20, 'name': 'Carlos'}))
  4.  

Which means the object passed in as a parameter, should have fields id and name with those values.

El objetivo no es terminar

Nos lanzamos a programar con el objetivo incorrecto: terminar. El software nunca se termina, así que partir con el objetivo de terminar es partir con el barco hacia el arrecife. Lo vas a hundir. El software evoluciona o degenera, pero nunca se termina.

El verdadero objetivo es hacerlo lo mejor posible con los recursos que se tienen. Esto lo estoy experimentando de primera mano desde hace tiempo con mis propios proyectos. Es una visión basada en la experiencia.

Cuando hemos pensado que teniamos que terminar un hito, pocas veces hemos conseguido implementar lo que teníamos en mente en el tiempo y forma imaginados. Sin embargo, el 100% de las veces que hemos perseguido terminar, hemos introducido bugs y problemas de regresión.

Por otra parte, cuando hemos trabajado en proyectos colaterales con el fin de construir una buena herramienta en lugar de "terminar algo", hemos alcanzado una calidad que sobrepasa lo que podíamos imaginar. Calidad significa, conseguir un producto que nos aporta valor en corto plazo de tiempo y que nos permite seguirlo evolucionando con poco esfuerzo para seguir ampliando su valía. Los dos frameworks open source que he desarrollado en mi vida confirman esta idea. La clave ha sido abordar pequeñas funcionalidades de necesidad prioritaria, pensando siempre en cómo se utilizarían y no en cuándo estaría terminado.

Cuando nos sentamos a programar no se debe tener la mente puesta en sacar la próxima release. La mente debe estar concentrada en resolver lo mejor posible el próximo criterio de aceptación o el próximo test. El único momento en que se puede hacer énfasis en "terminar" es cuando un test unitario está rojo y hay que conseguir el verde.

No se puede desarrollar con prisa porque se consigue justo lo contrario de lo que se quiere. Cuando cambiamos prisa por concentración se alcanza un beneficio espectacular. Como dicen en el libro Rework, la palabra ASAP (As soon as possible) es un veneno.

En muchos proyectos seguiremos viéndonos obligados a dar estimaciones muy abstractas a medio y largo plazo pero todo el mundo sabe que las estimaciones de este tiempo son casi como tirar los dados. Si te ves obligado a estimar lo inestimable, al menos no te creas tu mismo que el objetivo es cumplir con esa estimación. El objetivo es entregar la herramienta más útil al cliente y para ello hay que priorizar adecuadamente, meter la tijera y trabajar sin el objetivo de llegar a esa supuesta estimación.

The stubbing spy

Do you really need a stub or do you better use a spy? Or is it a spy object with some stubbed specifications? Let's see some examples using pyDoubles:

You can choose a stub object to prepare the scenario and then, assert on the returned value of the system under test.

  1.  
  2. def test_using_a_stub(self):
  3. USERID = 20
  4. collaborator = stub(Collaborator())
  5. when(collaborator.one_arg_method).with_args(
  6. USERID).then_return(SUCCESS)
  7. sut = SystemUnderTests(collaborator)
  8.  
  9. result = sut.exercise_method()
  10.  
  11. assert_that(result, equal_to(OK))
  12.  

The test above says: "I don't really care what the SUT does internally as long as the returned value is the expected, but it might need help from a collaborator, so I set it up, just in case."
Note the "might" part of the sentence. It is not necessary to specify the possible arguments in the call to the collaborator. This tests is more robust and still serves the same:

  1.  
  2. def test_stub_simplification(self):
  3. collaborator = stub(Collaborator())
  4. when(collaborator.one_arg_method).then_return(SUCCESS)
  5. sut = SystemUnderTests(collaborator)
  6.  
  7. result = sut.exercise_method()
  8.  
  9. assert_that(result, equal_to(OK))
  10.  

Now, let's replace the stub with a spy object, assuming we don't need to specify any stub behavior:

  1.  
  2. def test_if_arguments_are_important_check_them_out(self):
  3. USERID = 20
  4. collaborator = spy(Collaborator())
  5. sut = SystemUnderTests(collaborator)
  6.  
  7. result = sut.exercise_method()
  8.  
  9. assert_that_method(collaborator.one_arg_method
  10. ).was_called().with_args(USERID)
  11. assert_that(result, equal_to(OK))
  12.  

The test above means: "The SUT needs to call its collaborator at least once in order to complete the operation. I want to make sure that happens apart from getting the expected value."
Depending on the problem, we can have just one test with the 2 asserts, or maybe 2 tests, with one assert each.

We didn't need to define any stub method, but what if we need it?:

  1.  
  2. def test_if_arguments_are_important_check_them_out(self):
  3. USERID = 20
  4. collaborator = spy(Collaborator())
  5. when(collaborator.one_arg_method).then_return(SUCCESS)
  6. sut = SystemUnderTests(collaborator)
  7.  
  8. result = sut.exercise_method()
  9.  
  10. assert_that_method(collaborator.one_arg_method
  11. ).was_called().with_args(USERID)
  12. assert_that(result, equal_to(OK))
  13.  

We don't tell the stub what arguments is going to receive. That is not important. The stub part is intended to prepare the scenario. The easier the scenario setup is, the better. We do assert on the arguments at the end of the execution.

Conclusion:
If calling the collaborator is a critical part of the action, use a spy and make sure arguments are passed in as they should. If you need to stub out a method in the spy object, do not specify the arguments in the stub definition. In the stub definition, just tell the framework the returned value and later on, assert on the arguments once the system under test execution has finished

Reason: If you specify arguments in the stub definition and also don't assert at the end, you need to debug the failing test to find out that maybe some argument wasn't passed in.
It is more efficient to let the doubles framework tell you what was wrong :-)

Ultra simplifying SOLID

This is just another way of viewing the SOLID design principles very very shortly :-)

  • S: Methods with no more than 5 lines of code,
    classes with no more than 3 public methods (average).
  • O: If it works, don't touch it (extend it)
  • L: Don't abuse inheritance (are they really the same thing?)
  • I: This one was placed here to form the word "solid"
    but it's the same as S.
  • D: Never create the instance of the dependency inside the object
    which uses it.

Cartel de lujo en la #XPweek

Del 20 al 23 de septiembre de 2011, tendrá lugar la #XPweek en Madrid. Se trata de los dos cursos abiertos de iExpertos, sobre iniciación a TDD y TDD avanzado, donde además veremos otras cuestiones de XP como la programación en pareja y el ciclo de desarrollo de los proyectos. En esta ocasión contaremos con la actuación estelar de algunos de los profesionales más importantes del país:

Alfredo Casado: Estará con nosotros en el curso de introducción (20 y 21) hablandonos sobre legibilidad de los tests. Cómo escribir tests para humanos con la ayuda de herramientas como Hamcrest. Alfredo es uno de los desarrolladores con más experiencia en eXtreme Programming en España. Además es un excelente docente, de hecho, ha impartido clases en varias universidades.

Enrique Amodeo: Estará también el en curso de introducción hablándonos del Principio de única responsabilidad (SRP) y de refactoring de manera práctica. Enrique lleva años practicando XP y liderando equipos de desarrollo. Sin duda una de las figuras más destacadas del país en cuanto a desarrollo ágil y arquitectura del software.

Xavi Gost: En el curso de TDD avanzado, Xavi nos hablará de BDD con Javascript, Jasmine y de arquitectura Javascript. Nos presentará su framework Javascript y tendremos la oportunidad de aprender sobre arquitectura SPI. Xavi Gost es probablemente el más veterano de todos nosotros en prácticas de ingeniería ágiles. Actualmente al frente de BeCodeMyFriend, la incubadora punk.

Alberto Vilches: Alberto es referente nacional en tecnología Grails. Como el framework base para nuestro curso de TDD avanzado será Django, Alberto nos ayudará a entender cómo los conceptos explicados se pueden aplicar en Grails. Nos dará trucos y consejos para sacarle el máximo partido a todo lo que vemos en el curso.

Yo seré docente en ambos cursos y estaré encargado de coordinar la participación de estos grandes profesionales en las distintas etapas por las que vayamos pasando.

Aún quedan plazas libres, escríbenos a info@iexpertos.com para reservar la tuya :-)

TDD: resultados empíricos

Hace poco en una code kata alguien me dijo, ... "y qué ventajas tiene esto de hacer TDD?". Le dije... en nuestro proyecto, actualmente con casi 25.000 lineas de código Python (multiplica x4 si piensas en Java), no hemos necesitado nunca bugtracker. Cuando ha aparecido algun bug, se ha corregido enseguida y vuelto a subir a producción. Podemos hacer una release a producción cada dos días y sólo con una persona de QA, que dedica 10 minutos antes de cada release. No llegamos al continuos deployment por falta de recursos pero estamos muy cerca.
Cuando tenemos que hacer un cambio, lo hacemos en cuestión de horas o minutos y podemos subir a producción con total garantía (98%) de no haber roto nada.
Cualquiera del equipo le puede meter mano a cualquier parte del proyecto.
Lógicamente no obtenemos estos resultados por la practica de TDD en exclusiva, sino por todas las practicas y valores de eXtreme Programming (recuerda que TDD/BDD es una parte de XP).
Y todavía podía seguir enumerando ventajas. Sin embargo, el código de nuestro proyecto no es open source, así que la gente tiene que creernos. Ahora, con pyDoubles, puedes ver los resultados tu mism@:

Resultados empíricos basados en pyDoubles:
En la última release del framework, la 1.2, hemos conseguido compatibilidad total con Hamcrest, el framework más conocido de matchers, para mejorar la legibilidad de los tests. Estratégicamente esto hace que pyDoubles pueda convertirse en un framework de referencia, ya que Hamcrest es muy popular y ahora ambos frameworks encajan perfectamente. Es un gran logro a nivel de negocio, teniendo en cuenta que queremos que pyDoubles sea usado.
¿Sabes cuanto nos ha costado a nivel de desarrollo? 3 horas de trabajo. Puedes ver los commits que se han hecho de la version 1.1 a la 1.2 si quieres mas datos objetivos. Nunca habiamos visto el código de Hamcrest ni habíamos desarrollado pyDoubles pensando en Hamcrest, sin embargo, hemos desarrollo siguiendo SOLID, dejando todo abierto a extensión y cerrado a modificación. El resultado es contundente. Apenas un poquito de esfuerzo para alcanzar un gran resultado.
¿Cuánto nos podía haber costado esto sin hacer bien TDD? Probablemente semanas de trabajo. Probablemente haber tirado medio framework y haberlo tenido que reescribir, con el riesgo de cargarnos por el camino las funcionalidades existentes.
En esta release 1.2 no solo hemos tardado poco, sino que estamos seguros de que no se ha roto ninguna funcionalidad.
¿Cuál es el orden de beneficio de esta forma de trabajar? Dificil de cuantificar pero la sensación es de ser 10 veces más productivos. Entonces ahora ¿es más caro o es más barato hacer un buen TDD/BDD?

No necesitamos convencer a nadie, los datos empíricos van demostrando las ventajas por su propio peso :-)
Olvídate de convencer a tu entorno sobre las ventajas de XP, practica con el ejemplo.

Próximo dojo: el reto XP

El próximo martes 12 de julio, facilitaré un coding dojo en las instalaciones de DECiDE, que llevará por título, El reto XP.

Este evento es totalmente gratuito y las plazas son limitadas. Para inscribirse, está la siguiente url: http://decide.stagehq.com/events/916

El dojo no estará basado en una kata sino que tendrá un formato eliminatoria. Se planteará un reto a los participantes que les ayude a medir su nivel de interiorización de las prácticas y valores de eXtreme Programming. A lo largo de la jornada, algunas parejas irán siendo eliminadas aunque tendrán posibilidad de volver al juego en alguna ocasión.

Como siempre, hay que venir al dojo con el portátil y el entorno de desarrollo favorito instalado. Empezaremos a las 17h y la duración máxima será de 3 horas. Se programará en pareja pero no es preciso venir en pareja.

De nuevo, otro evento gratuito de la mano de iExpertos :-) , con la inestimable colaboración de Decide.

pyDoubles 1.1 released

There you go another version of the pyDoubles framework, mock objects for Python and more ;-)

What's new in this release?
Two minor bugfixes. You can see test cases and fixes here and here.
If you want to assert that a given object was passed in as a parameter, as exposed in this test, you have to declare the special methods "__eq__" (equals) and "__ne__" (not equals) in your objects. They are invoked when the framework asserts that the objects are the same. Otherwise, pyDoubles will see they are different instances of the object and will fail on the assertion.

On the other hand there are two new statements: