Carlos Ble

Carlos Ble

I am a professional software developer, I solve problems.

I also teach and mentor developers to build better software.

Developing software since 2001.

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. [Online - en Español] 25 y 26 de Junio
    Test Doubles con JavaScript - Online
  2. [in English] July 7, 8 & 9
    TDD (open to the public) - Tenerife, Canary Islands
  3. [en Español] 14 y 15 Julio
    TDD (en abierto) - Gran Canaria, Canary Islands
  4. [in English] October 13, 14 & 15
    TDD (open to the public) - London, UK
  5. [en Español] 29, 30 y 31 de Octubre.
    TDD (en abierto) - Madrid, Spain

Conferences:

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

Archive for January, 2011



Kata de las APIs fluidas

En el próximo dojo de Huesca volveremos a intentar desarrollar APIs fluidas. Esta vez, a diferencia de Madrid, todos iremos a por la misma API para reducir complejidad y mal entendidos.

Qué es una API fluida? Básicamente una API que es más humana de leer. Podeis leer a Martin Fowler sobre ello aquí. Hay varias estrategias para desarrollar APIs fluidas. Nosotros utilizaremos métodos encadenados (method chaining).

Las APIs fluidas son muy cómodas de usar (véase la API de mockito para definir stubs o mocks). Sin embargo, su implementación no es trivial. De hecho, su código es complejo. Al fin y al cabo estamos creando casi un DSL y esto se acerca a la teoría de compiladores.La mejor manera de lidiar con problemas complejos es con código limpio, que exprese claramente su cometido.

Todavía no sé si es muy docente mezclar TDD con el diseño de APIs fluidas pero es una buena oportunidad para probarlo. Da mucho juego para usar dobles de prueba o no usarlos, o para escoger enfoque top-bottom o bottom-up. Despues de varios intentos podremos volver a probar retrospectiva.

En el dojo que hicimos en Autentia propuse 4 ejercicios diferentes. Podeis ver la implementación de Rafa de Castro aquí, de uno de ellos. En mi opinion muy buena aproximación.

Mi propuesta para este dojo de Huesca es implementar esta API:

  1. select("name").from(users)
  2. select("name").from(users).where("age").greater_than(18)
  3. select("name").from(users).where("surname").contains("rodriguez")
  4. select("name").from(users).where("age").greater_than(18).and("location").is("san francisco")

Como se ve, la complejidad va en aumento. La idea es que quien termine una, pueda saltar a la siguiente. No me importa qué representación tenga "users", aunque para mi sería una lista de objetos User. Lo que estamos haciendo aqui es algo parecido a Linq de .Net.  No me meto a difinir como sería el assert de la especificación, solo os propongo estas líneas como parte del acto (ACT), de la especificación, es decir, quiero tener esa API disponible en mi libreria para usarla cuando quiera filtrar información de objetos.

Si nunca has visto una API fluida te puede parecer imposible pero no lo es. La cuestion es que con los métodos encadenados, un método no tiene por que devolver  un tipo primitivo sino que puede devolver otro objeto ;-)

No hace falta saber TDD para venir, pero sí sera bueno conocer algun framework de testing unitario. JUnit si quereis usar Java. Yo haré la kata en Python. Si quereis usar Ruby o lo que sea, es OK :-)

Nos vemos en Huesca :-)

Este viernes en la reunión del grupo Agile-Canarias hicimos un pequeño coding dojo. En este caso el facilitador fue Yeray Darias. Eligió el estilo RandoriKata, que básicamente consiste en que sólo 2 personas programan mientras los demás miran y se van cambiando por turnos. Con este dojo creo que ya he estado en 3 o 4, aunque sólo estuve en 1 como facilitador (en Autentia, Madrid). En los dojos me he encontrado en ocasiones incómodo y esta última vez he intentado ir analizando cuales han podido ser las causas. Aprovecho para hacer una pequeña retrospectiva de mis experiencias para que en los próximos dojos mi experiencia y la de los demás sea mejor.

  • No debe haber prisas en el dojo. Creo que un dojo de menos de 4 horas es difícil que salga bien.
  • Es bueno que todo el mundo programe en pareja. La RandoriKata esta bien si hay 4 o como mucho 6 personas, pero si hay más, es imposible que todo el mundo preste atención al proyector, con lo cual no se producen buenas discusiones de grupo sobre el código.
  • Si se usan pomodoros para dividir el tiempo en fracciones, estas no deberian ser inferiores a 15 minutos, porque es difícil hacer algo bien en menos de 15 minutos. Creo además que sería bueno no mostrar la cuenta atrás del tiempo ni siquiera decir cuánto dura cada pomodoro. Así el factor tiempo corriendo no influye y la gente puede centrarse en hacerlo bien. No se puede escribir buen software con agobio. Al menos yo no puedo.
  • Si varias personas van a trabajar en la misma máquina, es recomendable que cada uno lleve de casa su propio teclado. Así no pierde tiempo con los malditos teclados de los portatiles. Conectas tu teclado USB y te quitas otro problema de encima.
  • Siempre que se haga TDD debe estar  presente el bloc de notas con las próximas especificaciones a cumplir. Si no lo tenemos, no habrá rumbo. Esto nos pasó en la RandoriKata que cada pareja que se sentaba cambiaba el diseño y tardaba mucho tiempo en saber qué hacer.
  • Hacer más incapié en el refactoring. No se trata de terminar un problema sino de escribir buen código.
  • Cuando una persona está programando con el proyector conectado y todos los demás miran, se deben aplicar las mismas reglas que en la programación por pareja, donde el que tiene el teclado es uno, y el resto de la audiencia es el otro. Aquí hay una lista de 21 razones para odiar pair programming, más alguna otra que se comenta.
    Con esto quiere decir que no te deberían interrumpir hasta que estes en verde y puedas discutir decisiones o aplicar refactoring. Que estés en rojo y JM Beas te repita "¡borra ese código! ¡borralo!" es algo que no favorece que hagas lo que querias hacer. Cuando estas haciendo la kata tienes que hacerla a tu manera, si te vas dejando guiar por lo que algunos harían, entonces no eres tu quien programa.
  • Como los demás han mirado y pueden no estar de acuerdo con tus decisiones, lo ideal es dejar tiempo para que despues de la kata en el proyector, otro valiente se siente y lo haga a su manera también en el proyector. Será la mejor manera de ver ambos diseños.
  • El juego de la vida de Conway está genial para un code retreat porque tienes todo el día, pero para un dojo no me parece apropiado. La gente que nunca ha jugado se hace preguntas como... "que clase de juego es ese?" ya que al hablar de juego piensan que sera algo interactivo. Cuando entienden las posibilidades que ofrece el juego de la vida a la hora de expresar diseños de software, el dojo se ha acabado. En el dojo de Madrid la mitad del tiempo se fué y la gente no habia entendido lo que tenía que hacer (aunque no era el juego de la vida). Creo que es bueno exponer el problema a resolver antes del dojo para que la gente pueda leer sobre ello. Lo haremos así para el dojo del próximo viernes en Huesca.

Un dojo no es un curso y cuando he visto gente que no tenía ni idea de TDD, o que ni siquiera había visto nunca JUnit, su paso por el dojo a veces es negativo. Piensa que estamos todos chalados. Creo que cuando llevas a un amigo a un dojo es bueno que le cuentes un poco de qué va la movida.

Cuales han sido tus experiencias? Qué esperas de un coding dojo?

Gracias a Biko2 y a Agile-Canarias, pude hablar sobre la actitud que se necesita para practicar eXtreme Programming y ser grabado para compartir estas ideas con la comunidad. El sonido es igual de malo que la acustica de la sala donde grabamos la charla. Hubo una primera grabación en Biko donde el sonido era mejor pero la charla no salió tan bien. En podgramando.es teneis tanto el audio de este video con algo más de calidad, como el audio de la primera version de la charla.

¿Hace falta ser un superhéroe para practicar XP? from Carlos Ble on Vimeo.

Algunas de las ideas que inspiraron esta charla se extraen del libro Code Complete de Steve McConnell.

How do frameworks and software architecture fit into a TDD or BDD environment? There are several currents of thought. Some representative statements might be:

  • In the presence of TDD, we don't need architecture. Everything will emerge as we go developing.
  • The framework will define the skeleton architecture and we'll implement the user stories with TDD
  • Architecture and a good domain driven design will take care of the majority of the requirements and once we know which classes we want to use, we evolve them using TDD
  • Give me a comprehensive domain model and we don't need TDD at all
  • Frameworks are evil. We don't want them anymore because the make us loose domain semantic. They are too restrictive, complex and make the code harder to understand.
  • Frameworks are the best tool ever! The framework we use is so complete that pretty much everything we need is made by itself so we just use it and develop very fast

I am starting thinking that all of them are partly incorrect. There is a place where the architecture, the framework and the practice of TDD meet and I believe it is in the integration level. Let see if I can explain this with my (apparently terrible) English.

Software products are most of the time designed to manage or manipulate data. There are exceptions, i.e a calculator doesn't need to store data, but most of the time we need a third party subsystem to help us. We need a data source and a data store. Frameworks help us integrating our code with all these third party subsystems avoiding the need to write the plumbing again and again. So at this point, I'd say it is silly to neglect the importance of a good framework. The problem arises when you want the framework to implement your business logic, that is, the user stories. When you design your product in a way, that changing the framework is impossible.

If the software construction process is really good, changing the framework you use, has to be possible and take just a couple of weeks (this depends on the size of the project but it should be decoupled enough). If you relay too much on the framework or don't take the time to design the project architecture, you might have trouble getting rid of the framework, even if you practice TDD/BDD.

The remaining question is, why do we need software architecture if we test-drive the design? Easy: because we have to make decisions beyond user stories, beyond business requirements. They add value to the business although it is not explicit.

Steve McConnell, in his book Code Complete enumerate the following architectural components:

  • Program Organization: Major building blocks of the product and its responsibilities.
  • Major classes
  • Data Design
  • Business Rules
  • User Interface Design
  • Resource Management
  • Security
  • Performance
  • Scalability
  • Interoperability
  • Internationalization/Localization (i18n, l10n)
  • Input/Output
  • Error Processing
  • Fault Tolerance

In my opinion, in the presence of TDD and a good framework, you don't have to think of some of these components. I like my classes, data design and business rules to emerge from doing TDD. I like to delegate security, resource management and interoperability in the framework and also part of other components.

However, I recognize that we have had trouble with our current project because of just doing TDD and not thinking of error processing, fault tolerance, user interface design and i18n/l10n. Fortunately we thought of security since the beginning so that with the tools provided by the framework we are comfortable so far. We made the mistake of not thinking in the architecture enough. I though,... "ok, the framework is MVC so that is our architecture and the rest of the things will emerge". I wrote a post on our architecture for the web here.
Michael Feathers has recently written on this excess of "TDD fixes all the problems". Mark Seemann has also written on this.

Because we never defined a way to process errors, at some screens we show the errors in a way, while other times we manage the errors in a different way. This is not terrible but affects the user experience. The worse thing is that in order to fix it, we need to review every feature to see what we decided at that point. With more thinking we could have applied TDD in a more homogeneous way so that all errors of a kind would have been managed the same.

Regarding fault tolerance, we have situations where we have to deal with a not sent email. Something went wrong, the email wasn't sent so we have to send it again. Same happens with messages to twitter or other social networks. As we didn't thought on this in high level, we have classes that solve the problem one way while other use a different mechanism. It is not terrible because it works, the problem is that in order to know how to recover from this faults, we have to inspect the code to see whether for that case we wrote something in the log, or we created a record in database or what. Again, the lack of homogeneity make us loose more time than we like and make the learning curve of the system bigger.

Not taking into account i18n and l10n (because the framework was supposed to deal with that) has lead to a situation where many encoding bugs went into production despite of doing TDD. I've written about encodings and Python here. Again the problem is that now, if we want our product to run in a new country or language, we have to do regression tests manually because there are so many things to take into account. Not only the language but the locales, geopositions and things like that. Some of this problems couldn't have been detected upfront, but we should have written an architectural document while solving them so that the next time, we know how to evolve the classes homogeneously.

These are the major drawbacks we've found so far, not thinking enough in the high level details.

Architecture is great to understand the big picture, frameworks are great for plumbing and TDD/BDD is great to design and evolve user stories, acceptance criteria, business requirements that customers understand. According to Steve, architecture should be as independent of the environment as possible because you avoid the temptation to overarchitect the system or to do a job that you can do better during construction (with TDD!). The architecture should tread the line between underspecifying and overspecifiying the system.

The problem I see with people that loves architecture is that they go too far into the details of the system. They force you to implement the business in a way that is awkward, wrong. Even if they use Domain Driven Design techniques, I find it a handicap to define some models upfront. Finding the right balance between architecture, use of frameworks and emerging design have a great impact in the quality of the product.