En la pasada DrupalCamp 2012 formamos un pequeño grupo de interesados en el TDD (desarrollo guiado por pruebas) y decidimos llevar a cabo una iniciativa para practicar esta metodología de programación.
En la reunión celebrada el 31 de noviembre finalmente decidimos cómo la llevaríamos a cabo. Este es el plan:
- Celebraremos reuniones los martes y los jueves de 20 a 22 horas.
- Resolveremos katas de programación; en principio tomaremos como fuente la web de 12meses12katas.
- Serán reuniones online, buscaremos herramientas como google hangout.
- Las primeras sesiones serán guiadas. Compartiré mi escritorio e iré explicando cómo implemento la kata. Serán sesiones interactivas donde podréis plantear preguntas y proponer otras soluciones.
- Después de dos sesiones de iniciación, pasaremos a trabajar por separado. Lo ideal es resolver las katas en pair-programming, aunque también podemos hacerlas en "solo mode". Cuando las terminemos las iremos colgando en algún sitio y quedaremos para comparar y debatir nuestras soluciones.
Los que tengáis experiencia previa con TDD, podéis desarrollar directamente la kata por vuestra cuenta (o compartir también vuestros escritorios!).
Cualquiera puede participar, aunque quizá tendremos problemas técnicos si somos demasiados. Objetivo: aprender y divertirse.
Por favor, dejad vuestro e-mail aquí o enviádmelo a la cuenta carlescliment de gmail para que os pueda enviar la invitación de google hangouts.
¡Un saludo!

Comments
De categoria !
Muchas gracias a todos, espero que nos lo pasemos bien como dice Carlos y podamos/pueda aprender un montón.
Nos vemos el martes compis.
emails
Buenas.
Para poderos agregar al Google Hangouts voy a necesitar vuestros emails. Mi cuenta de gmail es "carlescliment" y podéis enviármelo también desde la pestaña contacto de mi perfil en esta web.
Os agregaré minutos antes de empezar.
¡Un saludo!
Gracias por la invitación
Soy nuevo en TDD pero me interesa mucho y espero aprender... sobre el horario no podré ingresar a las 20 horas, puedo ingresar a las 21 horas espero no haya ningún problema es que a esa hora recién llego a casa.
Este es mi correo, nramirez@businesstech.pe (Google Apps)
Saludos.
--
Néstor Ramírez Salas
Drupal Web Developer
@nramirezsalas
Streaming
Hola,
Una sugerencia, no se si se podria hacer un sreamming?
es decir que nosotros podriamos seguirte desde youtube.
Saludos
Disculpas nramirez, no vi tu
Disculpas nramirez, no vi tu respuesta a tiempo.
langelhc, intenté hacer un streaming por youtube pero solicité el servicio y no me llegó la autorización necesaria. Se supone que te envían un SMS al móvil, pero aún estoy esperando. ¡Tal vez en la próxima ocasión!
A los que asististeis a la reunión, muchas gracias y espero que os haya gustado. Como tuvimos tiempo (justo) de resolver la kata entera, creo que ya estáis preparados para intentar hacerla por vuestra cuenta.
Podemos de todos modos quedar mañana Jueves a la misma hora para empezar una nueva kata y conversar sobre las dudas que nos vayan saliendo.
¿Os interesa?
Aquí está la kata de noviembre de 12meses12katas: http://www.solveet.com/exercises/SQL-String-Generator/139
De categoria, lo único que
De categoria, lo único que entiendo, en mi lugar que no tengo los conocimiento de php suficientes. Ir al ritmo de ayer se me hace difícil asimilar tanta información en cuanto a programación, pero si fuí capaz de entender todo perfectamente.
La kata de ayer fue espectacular de la manera que se expuso pero reconozco que necesito horas para practicarla, así que la kata de ayer la iré desgranando a lo largo de estos días e iré posteando akí las dudas, así me podréis corregir fallos o recomendarme otras soluciones seguro que mejores... :)
Por mi Carles me apunto a las propuestas que vayas subiendo. Yo soy un fijo akí :).
Además esto es un vicio ...!
Y gracias a ti.
Un saludo a todos.
Miguel
PD1 - al final se grabo la sesión de ayer?
PD2 - el libro de Carlosble muy chulo. Habla de todos los conceptos que vimos ayer (Sut, Arrange, etc...)
Muy interesante la clase
Muy interesante la clase práctica de ayer. Muchos conceptos nuevos en los que hay que profundizar, eso también está claro.
Puede ser interesante de cara a la próxima reunión (sea el jueves o el martes) que tengamos en cuenta dos cosas
1) Trabajo propio. Esto es, enfrentarse a la kata para que vayan surgiendo las necesarias dudas. Tanto de TDD como de POO
2) Trabajo en equipo. No se como lo veréis, pero ya que en la sesión podemos participar todos, puede tener un formato más abierto. Aunque no completemos la nueva kata, ir aportando el como lo haríamos para iniciarla en conjunto.
Claro, para el punto 2 hay que darle caña al 1, de eso no hay duda :)
http://twitter.com/delineas
Personalmente yo daría unos
Personalmente yo daría unos días más, para que tuviéramos tiempo de practicar un poco lo visto ayer, o dejaría sitio a gente que no pudiera haber asistido.
Así, con un poco de trabajo individual, podríamos llevar los conceptos más asentados para seguir avanzando :-)
De nuevo gracias por todo, Carles!
Buenas, En primer lugar,
Buenas,
En primer lugar, perdón por mi ausencia ayer.
Según Dave Thomas, el "padre" de las code katas:
"There needs to be no pressure: this is why it is hard to practice in a project environment. it helps to keep it fun: make small steps forward when you can."
No olvidéis que da igual no terminar la kata. De hecho, una técnica habitual de hacerlas es fijar un tiempo, desarrollarla en ese tiempo, borrar lo hecho y volver a empezar. La gracia está en practicar, discutir, sin presiones.
Personalmente mi interés en este grupo de trabajo es "obligarme" a hacer las katas (y empecé mal :-P). Por ello creo que no es un gran inconveniente que no haya tiempo para prácticar solo, sino que veo más importante el mantener el ritmo y la frecuencia de las katas que el dar tiempo a que cada uno la trabaje.
Así que quizá queráis replantearos si lo dejáis para el martes...
--
Christian López Espínola (@penyaskito)
Buenas aportaciones,
Buenas aportaciones, Christian!
Además de obligarnos a hacer las katas, añadiría lo interesante de poder comentarlas en grupo y debatir soluciones.
¡Compartiendo siempre se aprende!
Estaría bien seguir la
Estaría bien seguir la propuesta de delineas y hacer la kata más participativa. Todos podemos hablar y compartir el escritorio, de manera que podemos debatir tanto como queramos. Personalmente prefiero esta forma de organizarnos.
Si en cambio queréis otra sesión guiada yo también voy a necesitar más tiempo para poderla preparar y que avancemos más rápido (¡una kata normalmente no se resuelve en menos de dos horas!). Si queréis lo dejamos para el martes que viene.
Tengo ya varios emails y tweets de gente que no pudo acudir pero le gustaría ver la sesión. Jesús, creo que la estábais grabando, ¿no? ¿La podemos subir a algún sitio?
Gracias a vosotros y un saludo.
Buenas, carles. Nosotros al
Buenas, carles.
Nosotros al menos no la estábamos grabando, me parece que esta primera sesión se ha perdido en el limbo :(
Una vez visto el desarrollo
Una vez visto el desarrollo de ayer, con una sesión sobra. Entre postear akí y compartir luego el escritorio con todos hay currete. Así que por mí nos vemos el martes que viene o al siguiente, no hace falta ir a piñon...
Que os parece ir posteando cada uno aki y que cada cual proponga un día para poder compartir escritorio y que se vaya apuntando la gente...
Otro que al final faltó
Buenas, y perdón por mi ausencia ayer. En principio no tenía "nada", pero acabó siendo uno de esos días en los que te aparece trabajo de la nada y acabas liado.
Personalmente yo también la preferiría también el martes que viene, más que nada porque mañana seguramente no pueda asistir pero la semana que viene estaré libre de nuevo.
Respecto a la grabación, si no se puede el streaming directo a través de Hangout, siempre se puede probar algo como XSplit y montar una cuenta en JustinTV para hacer streaming desde ahí. Yo lo he hecho alguna vez para TwitchTV (esto es parte de Justin), y no es muy difícil. Además también se queda la sesión guardada en la cuenta de Justin al terminarla directamente, sin tener que subir nada, así los que no hayan podido asistir siempre pueden verla luego.
Saludos!
Primera toma de contacto.
Hola de nuevo, antes de empezar el test quería postear un esquema
que no está depurado pero por lo menos puedo empezar a construir la kata.
http://twitpic.com/bb7i3k
Pensáis que así en una buena forma de comenzar y posteriormente ampliar y optimizar el esquema-kata? o es pura basura :-P
Saludos y gracias por los reportes...
Miguel
El esquema está muy chulo
El esquema está muy chulo como planteamiento inicial del problema, para tener las cosas claras.
En TDD el diseño no se planifica, pues va emergiendo poco a poco a través de los refactorings en cada test.
¡Un saludo!
¡Nos vemos el martes y 13
¡Nos vemos el martes y 13 entonces!
Sobre colgar código, creo que es mejor hacerlo en github, mucho más fácil de consultar. ¿Os parece?
Gracias, yo ya he colgado un
Gracias, yo ya he colgado un comienzo pero lo he dejado comentado para tenerlo de referencia. Conforme me salgan dudas que ya se asoman por las neuronas las posteo..
Hasta pronto.
Saludos.
Mi cuenta de github "lgrtm".
1º Question
He visto que hay metodos que se usan sin pasar test como por ejemplo el sumar un punto a un player, pensaba que tenía que estar todo con test. Pero al revisar tu código por encima he visto que llamas a funciones que no tienen test, supongo que son necesarias para hacer funcionar los otros test, me equivoco?
Thk
Los métodos para añadir
Los métodos para añadir puntos a un player [scoreLeft() y scoreRight()] están siendo ejercitados en el test junto al método getWinner(). De manera que para que getWinner() devuelva el resultado correctamente, es condición necesaria que scoreLeft() y scoreRight() funcionen bien.
Si recuerdas la kata, empezamos testeando unitariamente scoreLeft() y asegurándonos de que se había incrementado la puntuación con un método accesor getLeftScore(). Pero luego reflexionamos sobre ello y dijimos que había que evitar exponer la implementación de la clase con accesores para mantener el encapsulamiento. Es por esto que probábamos scoreLeft() y scoreRight() junto con getWinner() y eliminábamos los accesores innecesarios.
El objetivo es conseguir una interfaz pública lo más opaca posible, que oculte los detalles de la implementación de la clase.
Los métodos privados no se
Los métodos privados no se pueden probar desde el test, puesto que al ser privados solo pueden ser invocados desde dentro de la propia clase.
Los métodos privados por lo general surgen de los refactorings y sirven para ayudar a hacer más legible el código, ya que damos un nombre lo más expresivo posible a secciones de código. De esta manera los métodos quedan mucho más cortos y las explicaciones adicionales con comentarios resultan innecesarias.
2º Question
Revisando el test he visto una llamada de un objeto (no se si se dice así) tal cual que ahora no la entiendo o no la recuerdo de tu explicación.
$this->game->render($this->render);
Ahora no lo pillo :(
Thk
Hagamos un repaso...Una vez
Hagamos un repaso...
Una vez teníamos la kata de la lógica del juego resuelta, pasamos al renderizado de los puntos.
En un principio empezamos metiendo un método render() en la clase Game que devolvía un string dependiendo de la puntuación. "15-0", "15-15", etc...
Posteriormente hablamos del Single Responsibility Principle, o Principio de una Sola Responsabilidad, y decidimos que toda la lógica del renderizado la íbamos a mover a una clase aparte.
Empezamos a desarrollar una clase Render con un método que recibía un Game:
public function render(Game $game) {// (...)
}
Pero descubrimos que si lo hacíamos así, la clase Render iba a necesitar acceder a las puntuaciones de los jugadores (representadas con números enteros). Esto nos obligaba a implementar métodos accesores que expusieran los atributos privados $leftScore y $rightScore de la clase Game, algo que como vimos antes no nos parecía bien (encapsulamiento).
Para evitar esto aplicamos la técnica que recibe el nombre de Inversión de Control. Es decir, la clase Render ya no iba a preguntar a Game por las puntuaciones. Iba a ser Game quien se las iba a decir al Render, manteniendo la encapsulación. Explicado de otra manera, "no nos llames, nosotros te llamaremos".
Por eso hicimos que la clase Game tuviese un método render() que aceptaba como parámetro un objeto Render.
public function render(Render $render) {$render->render($this->leftScore, $this->rightScore);
}
Así, el objeto render obtenía la información necesaria (las puntuaciones) sin necesidad de exponer los atributos de Game.
Adicionalmente a esta explicación, he estado repasando mi código y hay algo que no veo bien.
Si te fijas en el test del render, estamos probándolo a través de la clase Game.
// Arrange
$render = new Render;
$game = new Game;
$game->scoreLeft();
$game->scoreRight();
$game->scoreRight();
// Act
$output = $game->render($render);
// Assert
$this->assertEquals("15-30", $output);
Bien pues creo que esa manera de probar no es la correcta, porque no es un test unitario. No estamos ejercitando directamente el SUT, y por lo tanto no es un test unitario. En el caso de que la clase Game tuviese un defecto, seguramente fallaría también el test del render, aunque el render estuviese bien.
Si volviera a hacer la kata la haría así:
// Arrange
$render = new Render;
// Act
$output = $render->render(1, 2);
// Assert
$this->assertEquals("15-30", $output);
Nota: he actualizado el código en github: https://github.com/carlescliment/Katas/blob/master/tenis/tests/GameScore...
¡Un saludo!
Documentación.
No encuentro documentación sobre la sintaxis de esto
public function render(Render $render) {
$render->render($this->leftScore, $this->rightScore);
}
render(Render $render) -> Render (esto es lo que no entiendo y no encuentro la documentación).
He mirado en google y en php pero no encuentro nada.
el Render que aparece justo
el Render que aparece justo tras el paréntesis se llama type hinting y es una feature bastante nueva en PHP.
Sirve para indicar que la función render debe recibir un objeto de la clase o interfaz Render. Si recibiese un objeto distinto, o un entero o un string, lanzaría una excepción.
Documentación.
No encuentro documentación sobre la sintaxis de esto
public function render(Render $render) {
$render->render($this->leftScore, $this->rightScore);
}
render(Render $render) -> Render (esto es lo que no entiendo y no encuentro la documentación).
He mirado en google y en php pero no encuentro nada.
Ok, entonces game es que le
Ok, entonces game es que le pasa los datos a render a traves del metodo render sin que render tenga que hacer un petición ( se entiende que ya los tiene no? ).
Que interesante.
Gracias por tu tiempo.
Saludos.
¡exacto! Interesante y
¡exacto!
Interesante y apasionante, ¿verdad? ^ ^
Ale las birras pagadas.
Ale las birras pagadas. Juasss XD
Thk
Me va a costar un tiempo
Me va a costar un tiempo hacer la kata, pero seguro que voy a aprender un huevo o más !!! XD
En unos días os cuento ...
3º Question
Yo voy poniendo preguntas y cuando se pueda se contesta. No me gusta agobiar a la peña.
A que se refiere la palabra triangulación?
Thk
Como vimos, siempre
Como vimos, siempre escribimos el código mínimo para que pase el test. Si hacemos una primera prueba sobre un método y esperamos que nos devuelva false, simplemente implementamos el return false.
public function testItShouldReturnFalseWhenFoo() {
// Arrange
$object = new MyClass();
// Act
$result = $object->fooMethod();
// Assert
$this->assertFalse($result);
public function fooMethod() {return false;
}
Triangular significa ir añadiendo tests de manera que, para que pasen, nos veamos obligados a completar todo el código necesario (y a refactorizar).
La ventaja de triangular es que garantizamos escribir el mínimo código posible con la máxima refactorización.
Como comentó alguien durante la sesión, triangular bien es quizá una de las partes más difíciles de TDD.
Diferencia entre IC y DI ?
Buenas, alguno podría explicarme cual es la diferencia entre Inversion de control e inyección de dependencias ?
Thk !
La inversión de control
La inversión de control supone dar la vuelta al flujo tradicional del código, en el que unas clases (o procedimientos) preguntaban a otras por los datos necesarios. Con la IoC las clases ya no se preguntan cosas entre sí, sino que se "mandan" unas a otras (tell, don't ask).
Una manera de conseguir la inversión de control es mediante la inyección de dependencias, que se basa en que no se instancian objetos dentro de métodos de una clase, sino que se "inyectan" como parámetros en la función.
// No inyectado
public function sendMail() {
$mailService = new MailService;
$mailService->send($this->title, $this->body);
}
// Inyectado
public function sendMail(MailService $mailService) {
$mailService->send($this->title, $this->body);
}
Como hay que asegurarse de que el objeto inyectado dispone de los métodos esperados, definimos una interfaz, que es un "contrato" de los métodos que debe implementar cualquier clase que la implemente.
Es decir, para conseguir la inversión de control estamos haciendo varias cosas:
1) Definir una interfaz, un protocolo de comunicación para todos los renders. La hemos llamado "Render", y establece que cualquier clase que la implemente debe implementar los métodos render($scoreLeft, $scoreRight), leftWins() y rightWins().
2) Una vez definida la interfaz, podemos inyectar cualquier render a nuestra clase Game. En la kata desarrollamos uno que convertía las puntuaciones a strings, pero podríamos escribir cualquier otro render, implementar la interfaz, y personalizar las respuestas de cada método.
3) La interfaz Render proporciona un método render($scoreLeft, $scoreRight) que permite invertir el control, ya que ya no es el render el que pregunta por los scores, sino el Game quien los da.
Leído y repasando links ...
Leído y repasando links ...
"ping" en render ?
Bueno el título se las trae, a falta de repasar el codigo de la kata, "Render" tiene que testear que le ha enviado unos datos "Game" ?
No, en el test unitario solo
No, en el test unitario solo testeamos que Render devuelve correctamente el valor Y ante unos parámetros X. Es decir, testeamos Render de manera aislada.
Necesitaríamos un pequeño test adicional que probase que la colaboración entre la clase Render y la clase Game funciona. Eso sería un test de integración.
Edito: ese test de integración lo podríamos cambiar por un test con un mock. Pasamos a Game un mock de Render, y nos aseguramos de que se llaman a los métodos correctamente.
Mañana lo ponemos en práctica en un momento ;)
No sé si me estoy adelantando
No sé si me estoy adelantando y Carles me mata xD, pero lo mismo a lgrtm le resulta interesante conocer el Code Coverage de PHPUnit http://www.phpunit.de/manual/current/en/code-coverage-analysis.html
Por otro lado, viendo un screencast de Carlos Ble, vi que tenía un widget que lanzaba los tests automáticamente con cada cambio... Lo más parecido que he podido encontrar para PHP (tampoco he buscado tanto) es esto, pero no mola lo mismo xD http://net.tutsplus.com/tutorials/php/automatic-testing-for-tdd-with-php/
No conocía la página
No conocía la página net.tutsplus.com.
¡Está genial!
¡Gracias Jesús!
(habrá que probar el watchr)
Me estoy dando cuenta que
Me estoy dando cuenta que tengo que darle caña a documentación, pero bueno poco a poco lo iré mirando que tambien tengo curro.
Gracias a todos por los links....
En twitter vi un post sobre libros a leer.
Estaría bien colocarlos akí tambien!!!
Se llega a tiempo para apuntarse uno?
No se si habéis empezado o no con la dinámica pero me gustaría apuntarme a ver si cojo el hilo :)
pedro.cambra at gmail
Genial Pedro, ¡bienvenido al
Genial Pedro, ¡bienvenido al grupo!
En principio el martes nos veremos en un hangout para ir desarrollando entre todos la kata de este mes.
¡Gracias por participar!
Grbaciones.
El otro día se nos escapo la grabación, para que no ocurra lo mismo, alguno tiene previsto o puede grabar la sesión en video?
Saludos.
Yo grabé un rato del martes,
Yo grabé un rato del martes, pero no lo tengo entero porque se me cayó la conexión...
¿hay un post para la sesión 2?
Yo grabe toda la sesión, así
Yo grabe toda la sesión, así que nada más mueva esto Carles la subimos, él si comento de abrir un nuevo post.
La calidad audio no es muy alla pero se entiende perfectamente, el video es de la calidad que nos salio del hangout.
En general se puede ver.
Saludos.
Miguel