Tratando de Ser Paciente con esta Pasión

Hola! ante todo no pretendo aburrirlos con una introducción!

Soy simplemente un desarrollador que , si encuentro un tema interesante sobre el que me parece que pueda aportar mi experiencia, trataré de sumar , tratando de hacer alguna breve reseña al respecto.

Gracias por leer!

martes, 15 de julio de 2014

Deuda técnica /Technical Debt

Cuando, Cómo , Por qué ? Como la evitamos ?

Cuando pensé en desarrollar este tema, fue porque creo que la mayoría de los desarrolladores no somos muchas veces consciente de la significancia de este Issue, de este concepto y del peso y su impacto en nuestras tareas.  Muchas veces siquiera no tenemos en cuenta , en las estimaciones, el costo de “saldar” esta deuda.

Creo que todos en algún punto del proyecto empezamos a generar este “debe” en nuestros desarrollos, y surgen por distintas causas, desde las no mal intencionadas , como deadlines, ignorancia, una mala noche con los niños,  etc hasta quizas las propias de no tan buenas causas, como ser decidia, estar en discordia con el proyecto , con el sueldo, y otro sin fin de motivaciones.

Que es deuda tecnica?

Es hacer cosas de manera no correctas ( hardcodeos, codigo mal diseñado, sin test, hacks, en general muchos “if’s”) pero que funcionan y en general solucionan un tema “muy caliente” que por circunstancia contractual, muchas veces queda en el “provisorio / para siempre”. Esto nos afecta, ya que indiscutiblemente es un parche, para las implementaciones a futuro. que luego evolucionarán sobre estas malas implementaciones , volviendo mas dificil arreglar cosas que fueron, desde su nacimiento, mal concebidas.

Cómo prevenirla , cómo la soluciono?

Es importante entender que no siempre surge de un apurón, ya que  tambien muchas veces simplemente surge por que no sabemos que estamos creando la misma.Creo que todos en mayor o menor medida estamos creando siempre deuda técnica, desde el vamos basado en la creencia que todos podemos mejorar en nuestra profesión. El tema es hacer algo que no nos complique en demasía pensando en el futuro.

Nosotros iremos descubriendo que algo que fue maravilloso en una epoca, ahora lo vemos como algo simplemente mal.

Atacar este problema debe ser tanto una cuestión de conciencia personal como algo que lo debemos ver como un subject del equipo

Algunas ideas

A nivel de desarrollador :
* Si somos concientes del apurón y que estamos haciendo las cosas mal es dejar el comentario en dicho codigo diciendo: esto esta feo, y soy conciente de ello, pero hay que sacarlo andando, un HIPER TODO.

* Tener en la cabeza de tratar de desarrollar en capas y en lo posible con Single Responsability como idea principal. Es decir  , si sabemos que estamos metiendo hacks como loco, OK, pero dejemoslo en una clase aparte. Que esa clase / esa capa contenga nuestro desman.

* Testing: Como no señores!! testear!! nada como un par de test conteniendo la funcionalidad, que de última nos quede , sobre la funcionalidad hackeada, un test que nos contenga la validez de la funcionalidad. Esto nos permitirá luego que ????... Si.. Refactorizar!. Y si usaste TDD, ya tenes acotado al menos parte del escenario con problemas.

A nivel de Equipo:

* Code Review : Hay herramientas que son increibles, tuve la suerte de trabajar con esta metodología y no tengo cons en este aspecto. Es un mito totalmente falso el hecho de la perdida de tiempo. Si estan las cosas bien pautadas. La calidad y aprendizaje del equipo en general es simplemente impresionante. Y nada mejor que arreglar las cosas cuando las intencionalidades e ideas estan frescas.

* Que el equipo acepte y lo incluya en las estimaciones el testing y code-coverage. El Code Coverage, sin ton ni son , no tiene sentido, pero al menos si rompemos algo que al menos sepamos, por medio de los test y esta herramienta , que puede ser útil , inteligentemente aplicada, hay una contención sobre nuestras falencias. 

La deuda tecnica existe , y lo mas complicado para repararla es encontrar el tiempo para repararla. El tiempo invertido en testing, es nuestro cheque al futuro para poder hacer refactors que mejorarán el proyecto. Los mismos, aceptemoslo, son inevitables.

Cómo conclusión es responsabilidad de los desarrolladores con más experiencia y el team leader hacerse cargo de esta deuda, de estar atento de más alla de la implementaciones, tener regulado este problema tiene como recompensa una lista acotada de bugs, y que un cambio de requerimiento no sea un miedo a tirar abajo un castillo de naipes. Esto sobre todo en proyectos grandes . Los test son nuestros seguros contra la deuda, pero ella indudablemente existirá. Cómo la gestionemos , que sepamos concientemente que existe es nuestra responsabilidad para con el proyecto y para con nuestros pares

miércoles, 9 de julio de 2014

Rumiando sobre TDD; Cuando arranco con el “Refactor” ?

Luchando contra la última tentación


Ufa; Otro artículo sobre TDD. Si, hay un mucho en la web al respecto de esta técnica de desarrollo. Pero te invito a leer el artículo hasta el final, prometo tratar de no defraudar, al menos te voy a invitar a pensar. Para plantear posturas desde un incio, soy una persona que apoya esta metodología. Requiere maduración y horas. Pero soy un converso. Ahora que sabemos en que vereda estamos , continuo.

Si leiste lo mínimo al respecto sabemos del Mantra:



Es decir empezar por el test; hacer la implementación mínima para lograr que funcione y luego empezar a dejar el mundo más bonito, ó en una primera instancia empezar a hacer un diseño que te deje conforme, con lo que nosotros consideramos “ Por esto Uncle Bob no me odiaría tanto..”

Mi experiencia me ha demostrado un par de cosas:
* Hasta que aprendes a testear te lleva un tiempo.
* Que una vez que aprendes y te dejaron de llamar por que se cayeron las cosas el fin de semana empezás a creer que testear es bueno. ( para vos y tu projimo! el que te llamó odia despertarse por alarmas de gente que no probó las cosas! )
* Si te gusta diseñar , vas a ver como tus modelos van adquiriendo mejores formas, se vuelven más simples y lograste una mejora en la calidad de tus aplicaciones.

Oiga! El punto que pretendes encarar en este artículo todavía no lo tocaste!  ahi voy.. ahi voy

Cual tentación ?

Uno tiene conceptos de patrones, leiste aunque sea un par de veces al GOF, y entendes de lo que hablamos de SOLID ( si no ocurrió esto, que estas esperando ? una invitación de Messi ? )
Pero TDD ataca el problema por otro lado, te dice que tenes un problema , que arranques en la parte del  testeo y que en función de eso, con lo poco que comprendes (bien) el problema ( al menos entendes que se pretende dilucidar ; este sería el paso 0 de la metodología) , que empieces a implementar una solución para lo que sabes con seguridad, fehacientemente, que debería ocurrir y que luego de ello, empieces a ver como eso que resuelve el problema empiece a ser algo mejor de lo que es ( Colaboradores, responsabilidades, estrategias, etc ). Aquí aparece la tentación.

La tentación de  empezar a diseñar  “ en el mientras “ estamos queriendo hacer funcionar  los test. Todavía no logramos el green , pero ya pretendemos saber donde, con detalles,  vamos a poner un Strategy.
Uno esta haciendo la solución para el problema planteado, y uno se tienta en decir “bueno aca hago esto por si esto, y acá hago aquello por si aquello” entonces, a menos que sea una demanda de la funcionalidad, uno empieza a meter manos en un diseño que , creanme por favor en este punto , LEJOS esta de ser el definitivo.

TDD nos invita a una forma de resolver problemas mediante capas de pensamiento, de etapas estamos hablando.

Uno empieza a resolver rudimentariamente la funcionalidad planteada, a propósito en este punto (es muy importante esto),  y en un momento nos darnos cuenta que algo que vamos a hacer necesariamente estará encapsulado en un componente cuyo punto de entrada será un simple metodo.

Aquí es donde arrancamos un nuevo test, sabiendo un poco mejor en este punto , de manera más puntual,  que escenarios cubrirá el nuevo componente. El anterior test que veníamos haciendo no se resolverá hasta que este nuevo punto no este cubierto. Esto se puede dar iterativamente n veces. Estas son las capas, estas son las Etapas. Pero sepamos que cuando resolvamos el último eslabon de esta cadena, de a poco  iremos resolviendo las capas superiores , hasta llegar a tener ese test MAIN, principal, muy cerca de ser solucionadas una buena parte de las ideas que teníamos que resolver , y muchas mas surgirán para poder plantear a la persona que nos solicitó este pequeño desafio.

Es en este punto donde nuestra paciencia tiene su recompensa, y el premio de soportar la tentación tiene su recompensa. En este punto donde nuestra etapa de diseñador comenzará a actuar. Y acá es donde superamos la tentación

Ahora tenemos el Big Picture del problema. Es entonces en este punto en donde podemos jugar con clases Abstractas e interfaces, con resolución de problemas por partes a nivel de diseño y donde veremos focos reales de mejoras, más abarcativos y depurables.

De esto salen dos cosas que deseo destacar:

* TDD es efectivo si entendemos y testeamos el negocio, no la implementación

* El caramelo para los desarrolladores solo lo podremos disfrutar en todo su aspecto si
Sacrificamos nuestra ansiedad de diseñar en función de resolver la foto completa de la funcionalidad a implementar. Luego si, a saborear las ideas.

Estoy plenamente convencido que para comprender TDD mas nutritivamente, para enfocarlo y sacar el máximo jugo de esta metodología (y no hablo solamente del gusto del desarrollador, hablo también de los tiempos y objetivos del proyecto en el que estamos involucrados ), debemos comprender que redactamos nuestros tests para solucionar un tema de negocio y no , y quiero ser explicito con esto, NO debería ser para testear una implementación de esa solución (no esta mal del todo a mi entender si lo consideramos muy necesario ). Comprender esto nos lleva a crear test que solamente se focalizan en escenarios puros y claros dentro del contexto del problema de negocio  a desarrollar.

Ser rudimentarios al principio nos proporciona la claridad de ver el codigo y la implementacion de manera explicita de cómo solucionamos tal situación. Esto nos permitirá luego, si la situación lo demanda , claramente ver cuando se requiere Clases Abstractas, Interfaces, Factorias , DI y externalización de configuración  ( valioso no ? )

Como corolario , con estas dos premisas cumplidas , obtendremos test robustos, que cambien relativamente poco con cada nuevo feature. TDD no apunta que hagamos muchos test, o test futiles, sobre getters y setters; esta es una visión simplista. La idea principal es simplemente hacer los test necesarios, y que no estemos desarrollando código innecesariamente que ataque escenarios que no fueron pedidos.

Esto que estoy promoviendo, invito a que lo prueben, lo desarrollen con algún kata para algun lenguaje que se sientan cómodos.

Gracias por leer hasta acá ! sean pacientes! y gracias por la brindada!

viernes, 4 de julio de 2014

Usando Merge y Rebase en Conjunto para Ordenar Commits


La idea de este primer ayudamemoria para mi, y tutorial para quien este buscando resolver el mismo problema que yo encontré, que es como dejar lo mas prolijo y consistente la historia de commits una vez que deseamos mergear branches, en general el escenario entre una nueva funcionalidad a desarrollar y el master. Esto implica el uso de los comandos Merge y Rebase en su conjunto. NO me voy a ir por las ramas de que significan cada uno ; hay mucho en google. La idea es un ejemplo simple y practico de cómo:

1.- Entender como se resuelven dudas de uso con git , es decir con Sandbox y jugando , como cualquier cosa en desarrollo
2.- Con el mismo ejemplo evidenciar el problema la solución propuesta y el alcance del mismo


Atención ! los de svn se sentirán afuera un poco , esto es para los que usamos git, pero en fin, mi recomendación , aun con lo dificil que puede parecer al principio, traten de aprender esta poderosísima herramienta de versionado. Redunda en una forma de trabajar mas prolija, ordenada, y de hecho al día de hoy pienso que mas standard con el modelo de desarrollo internacional.

Vamos al Ejemplo!

Creo una carpeta y la inicializo como repositorio (esto va a ser nuestro SandBox):
~ user$ mkdir a1
~ user$ cd a1/
~/a1 user$ git init
Initialized empty Git repository in ~/a1/.git/

Ahora creo un archivo , lo adiciono y lo commiteo:
~/a1 user$ touch c1;git add . ;git commit -m "c1"
[master (root-commit) 1eb77d0] c1
0 files changed
create mode 100644 c1

Vemos que se creo nuestro primer commit, para este ejercicio no importan los push, es simplemente ver como ordenamos los commits
~/a1 user$git log --oneline
1eb77d0 c1

Creamos un nuevo branch, donde vamos a implementar nuestras nuevas funcionalidades
~/a1 user$ git checkout -b otro
Switched to a new branch 'otro'

Creamos un archivo en este nuevo branch, pueden ser los n commits necesarios
~/a1 user$ touch c2;git add . ;git commit -m "c2"
[otro aacf167] c2
0 files changed
create mode 100644 c2

Ok ,volvamos al master
~/a1 user$ git checkout master
Switched to branch 'master'


Ahora , estoy creando algo nuevo , pero la idea es la misma que si hiciesemos un pull del repositorio, es decir aparece un commit nuevo que seria el úlitmo del master:
~/a1 user$ touch c3;git add . ;git commit -m "c3"
[master 969be85] c3
0 files changed
create mode 100644 c3


Si vemos el master vemos que tenemos el original, c1 y el nuevo , c3
~/a1 user$ git log --oneline
969be85 c3
1eb77d0 c1


Aca es donde empieza lo que suele confundir; hacemos un merge con nuestro branch de nuevas funcionalidades:
~/a1 user$ git merge otro
Merge made by the 'recursive' strategy.
0 files changed
create mode 100644 c2


Al hacer un merge con lo que teniamos de nuestro branch , genera un commit nuevo de Merge, que lo podemos ver en un editor vim; al guardarlo , veremos esto si pedimos ver los logs:
~/a1 user$ git log --oneline
d2ee2d1 Merge branch 'otro'  → este es el crea la herramienta y nos molesta!
969be85 c3
aacf167 c2
1eb77d0 c1


Como sacamos ese commit molesto de Merge? 
Queremos dejar la historia como debería ser, es decir el commit que vino del 'supuesto' pull (el c3 ) dejarlo atras para sumar nuestra nueva funcionalidad

Bueno aqui es donde hacemos un rebase contra el id de commit que es anterior a los cambios, en este caso el c1, que como podemos ver su Id , reducido ( ver git log , para ver el completo ) es eb77d0
~/a1 user$ git rebase -i 1eb77d0


Al ejecutar el comando anterior nos aparecerá una nueva pantalla de vim ( ó el editor de consola que tengamos seleccionado en su bash ) indicándonos que queremos hacer con los commits en adelante; Aquí surgen varias posibilidades ( squash , borrar , etc ) pero no me quiero meter en eso; no es a lo que apunto, lo importante es que en este caso particular , no hacemos nada ; simplemente guardamos lo que el editor nos propone y aparecerá el siguiente mensaje:


Successfully rebased and updated refs/heads/master.


Si pedimos ver nuevamente como quedo la historia veremos
~/a1 user$ git log --oneline
f8bfa0a c2
969be85 c3
1eb77d0 c1


Notar que c2 ahora posee un nuevo Id, esto es porque squasheo nuestro cambio con el merge, pero dejo la historia como queríamos es decir nuestro cambio como último de la lista.  
y si hay conflictos ? ufff

Bueno en este caso deberemos ir editando a mano para solucionar los conflictos, haremos git add  para agregar los cambios y git rebase --continue; hasta lograr el final de la historia.
Esto ultimo se escapa de la idea del tutorial; pero estimo que con la idea de armar sandbox, podrán ir jugando y practicando hasta emular el escenario que desean resolver .

Gracias por leer hasta acá ! sean pacientes!