Mostrando entradas con la etiqueta calidad de codigo. Mostrar todas las entradas
Mostrando entradas con la etiqueta calidad de codigo. Mostrar todas las entradas

lunes, 18 de abril de 2011

Calidad III : La Relatividad del concepto

En los comentarios del post sobre la Calidad del Desarrollo de Software II tanto Walter Risi comoErnesto Kiszkurno aportaron un par definiciones distintas y muy interesantes de la calidad de software.

El concepto de la calidad de Software, en general, es decir Que hace que un software sea de calidad es uno de los temas que más discusión ha causado dentro de la comunidad de sistemas desde hace décadas.

En los 2 posts anteriores sobre Calidad del desarrollo hemos evitado justamente este tema ateniéndonos nada mas (pero nada menos) que al concepto, bastante más concreto, de que es lo que hace que un desarrollo sea de calidad. Es decir, para usar la metafora-que-odio-de-la-fabricación, que calidad tiene su construcción, su Calidad Interna.

Pero para no esquivar el bulto al problema más general, podemos plantearnos entonces , Que determina que un software sea de calidad?

El Juego

Uno de los sistemas que más utilizamos en nuestra época de estudiantes en Exactas (UBA) fue un juego (como no podía ser de otra manera) de estrategia en tiempo real llamado Dune II. Fue un juego que nos apasionó y en el cual podíamos pasarnos horas jugando hasta terminar las misiones. No obstante ese juego tenia un par de bugs molestos, uno de ellos con la Inteligencia Artificial de la maquina que justamente en determinadas situaciones no respondía bien en la defensa y el otro con el manejo del gusano de arena que ha veces se tildaba y quedaba ciclando en algún loop escondido.

Si nos hubieran preguntado allá en el tiempo pero incluso ahora que opinabamos de la Calidad de ese desarrollo, creo no exagerar en decir que era Sobresaliente, excepcional.
Hubiera agregado algo si la empresa dueña del juego arreglaba esos bugs? Probablemente hubiera sido lindo, quizás un poquito mas interesante pero....eso no hubiera cambiado la percepción de la Calidad del producto que teníamos, era sencillamente de Calidad.

Entonces, que es lo que determina que un producto de software sea de Calidad....y bueno... si no queda otra, ensayemos algunas respuestas habituales:

1) que sea utilizado por mucha gente?

Windows es el caso arquetípico de software utilizado por mucha gente que no obstante....digamos que jamás ha sido famoso por su Calidad (piensen sino en el caso cercano del Vista y ni que hablar de otros...ejem fallidos como ....alguien se acuerda del Milleniun?)
El software de Mac en general tiene asociado una fama de mucha mayor Calidad y es utilizado por muchisima menos gente.

2) que sea fácilmente usable?

El problema para determinar aquí que tal sistema es de Calidad por su usabilidad, más allá de los recientes libros y normas sobre usabilidad de Diseñadores gráficos, es que los usuarios tienden a encariñarse poderosamente con la interfaz de usuario que conocen. Siempre prefieren lo conocido por sobre lo novedoso.
Piensen sino en lo que diría un usuario de WordStar o WordPerfect si tuviera que usar el Word actual o, viceversa, si un usuario de Word tuviera que usar el Wordstar y para ambos la usabilidad de la herramienta que usan/usaban era formidable. Ni que hablar de la pelea entre los amantes de Vi versus Emacs versus editores de linea tradicionales.
Para los amantes de linux cualquier linux es totalmente fácil de usar pero si le damos una consola de comandos a una persona que siempre uso Windows...bueno...inmaginense su juicio.

3) que Tenga cero defectos?

Permitan me una sonrisa irónica, Jeje, no se conocen casos de software que se alegue que sean de Calidad por no tener Defectos sencillamente porque todavía no ha habido un software que no tenga defectos.

4) Que tenga muchísima funcionalidad y features?

Más allá de los casos conocidos como los productos de Office y para que vean que no la tenemos en contra de Microsoft ambos autores de este blog hemos utilizado un par de productos de GIS (Sistemas de Información Geográfica) de una empresa anglosajona que se podrían definir como el paraíso de la acumulación de funcionalidad y features. Uno de ellos se focalizaba en plotear mapas, el otro para hacer carga, procesamiento y consultas en sistemas de información Geográfica.
Cada uno de los productos tenia cientos de features y comandos, muchas veces con funcionalidad superpuesta que creaban una especie de frankestein gordo y pesado, un mamotreto de distintas funcionalidades mezcladas adonde nada se hacia realmente bien o perfomante porque todo era una solución de compromiso para poder hacer muchas cosas que casi nunca se necesitaban.

5) que Sea de bajo Costo y termine dentro de la planificación?

Seguramente son requisitos para el Gerente de un proyecto, el de Marketing o Ventas e incluso los interesados o StakeHolders pero...y los usuarios?

6) Que tenga buena calidad de desarrollo?

Esto justamente es lo que hablamos en el post anterior, y así como creemos profundamente que es un requisito indispensable por el mismo motivo que un edificio sin buenos cimientos se derrumbará, no es suficiente para que todo el producto, el sistema sea de Calidad. Es decir, podemos tener un sistema de una calidad de desarrollo excepcional pero que no sea útil para el o los usuarios en cuestión.

La raíz del problema

Justamente el problema que tiene cada una de las definiciones que intentamos y que han sido intentadas alguna vez, es que la CALIDAD es un término relativo. La calidad que es adecuada para una persona o tipo de persona puede ser totalmente inadecuada para otra.

Jerry Weinberg en su libro "Quality Software Management: System Thinking" habla justamente sobre este tema, y en particular como este concepto de "relatividad" se esconde incluso en
algunas de las definiciones más famosas de Calidad de Software.

Por ejemplo la de Crosby: "Calidad es el cumplimiento y satisfacción de los requerimientos", es decir que un sistema es de calidad si cumple con sus requerimientos.

El tema, o kid de la cuestión y que deberíamos preguntarnos es:
"Requerimientos de Quien o para Quien?", entonces, para ser más precisos deberíamos decir:

"Calidad es el cumplimiento y la satisfacción de los requerimientos de algunas personas"


Para cada persona el mismo producto tendrá distintas "calidades" y de hecho entonces cada sentencia que alguna vez se ha hecho o se hará acerca de la calidad del un sistema es una sentencia acerca de lo que consideran que es la calidad un determinado conjunto de personas.

Por ello, la próxima vez que estés desarrollando software, siempre, siempre preguntate:

"Quien o quienes son las personas detrás del concepto de calidad que están pidiendo para este sistema en particular"

viernes, 18 de marzo de 2011

Calidad del desarrollo II - Breve Historia

La definición de Qué es la calidad del desarrollo de software ha ido cambiando, como la moda en ropa y peinados, a lo largo del cortísimo tiempo (si lo medimos en eras geológicas) desde que en este planeta comenzamos a escribir programas para indicarle a ese merengue de transistores (antes) y circuitos (después), llamado Computadora u ordenador, como realizar una determinada tarea llamada cómputo.

Ha ido variando, deciamos, un poco como la moda, en tren de determinada corriente, modificada por los distintos paradigmas de programación, y metodologías en boga en cada momento.

70's - Programación Estructurada

Primero tenemos la definición típica de la Programación Estructura, si bien tuvo posteriormente un "aggiornamiento" durante los 80's con la aparición de la Programación Orientada a Objetos. La misma dice que un sistema tiene una buena calidad de software si todos sus módulos tienen una Alta Cohesión funcional y un bajo acoplamiento. Con la aparición de la POO lo que se hizo fue redefinir como interpretar lo de cohesión y acoplamiento no ya en módulos sino en clases de Objetos.

80's - 90' - Las leyes y patterns de POO

Desde la aparición de la POO en el Mainstream (es decir, como paradigma de desarrollo aceptado masivamente) a lo largo de los 80 y 90's se redifinió como obtener una buena calidad de desarrollo a través de un conjunto de leyes, principios y patrones de diseño que especifican que un diseño de un sistema programado con objetos es bueno (la calidad por lo tanto es "alta") si cumplen con estas leyes, principios y utiliza, cuando se debe, estos patrones. Ya hemos hablado aqui de algunas de estas leyes y principios en la-ley-de-demetrio-y-otras-yerbas-oo y en ejemplos-de-la-ley-de-demeter.

2000's - Visión desde TDD Con la aparición de las metodologías ágiles en general y en particular con la práctica de TDD surge una definición muy interesante de que debe cumplir un código para tener buena calidad, a partir de los tests de unidad:

Un sistema tiene buena calidad de desarrollo si el código de todo el sistema (sean Clases o módulo) es el el más simple posible que ofrezca la solución al problema determinado. Y, cuando un código es el más simple posible? Cuando

  1. Corre todos los tests de unidad correctamente.
  2. Expresa cada "idea" del modelo que se necesita expresar (para resolver el problema).
  3. El código modela cada "idea" una y sola una vez.
  4. Tiene el mínimo número de clases y métodos para lograr los puntos anteriores.

Más allá del 2000 y pico - Dos Calidades

En los últimos años, junto en parte a la explosión de aplicaciones web, tanto Kent Beck como Martin Fowler vienen marcando un punto válido (y bastante obvio si uno se para ha pensar) de porque es tan difícil para un equipo de desarrollo hacer entender que la Calidad del desarrollo importa y es fundamental.
Lo que dicen es que los usuarios no entienden la importancia de la Calidad del desarrollo porque hay 2 dimensiones de la calidad, digamos 2 calidades distintas.

La Calidad Interna: Es la calidad del desarrollo propiamente dicha, el como esta construido por dentro, si cumple con la cohesión-acoplamiento, con las leyes de objetos y con la definición de TDD y buena refactorización de código. Es como la conocemos nosotros, la gente de sistemas.
El problema es que esta calidad no es directamente perceptible por los usuarios. Solo ven los efectos. Y por lo tanto, a priori, no les importa.

La calidad Externa: Es la calidad del sistema que puede ser percibida directamente por el usuario. Es cuan agradable y efectivo es el uso del sistema para el usuario, cuan buena es la usabilidad de su interfaz de usuario, de sus reportes, cuan rápido y perfomante responde el sistema ante su uso.

Este concepto bastante obvio, siempre ha existido, desde que los sistemas tuvieron usuarios, pero es interesante notarlo porque ha veces lo hemos pasado por alto o lo olvidamos.

Así, para esta concepción mas completa la calidad de un desarrollo de software es alta si tiene tanto calidad interna como externa.

Calidad Negociable


El punto más interesante aquí, como explica Martin Fowler en este articulo aqui es que la calidad externa de un sistema es algo negociable por tiempo y costo mientras que la calidad interna no.

"Deseas agregar una grilla que muestre a los clientes con fotos, con efecto esfumado y que roten 3D? Perfecto pero eso lleva más tiempo y dinero, si el usuario lo acepta no hay problemas pero mientras tanto, la grilla 2D que tenés (sin fotos) te sirve para comenzar a utilizar el sistema? Fantastico".

No tomen prisioneros


La calidad interna por otro lado no es negociable porque nosotros como programadores tenemos la responsabilidad profesional de preparar el sistema para ser mantenible a lo largo del tiempo y modificable (a los cambios de alcance). De la misma manera si vamos a la metáfora del arquitecto sería lógico que el usuario nos plantee que la construcción que estamos haciendo para que vaya a vivir le demos prioridad a las habitaciones y cocina antes que a la pileta de natación. Pero por otro lado si quieren que vayamos más rápido y eliminemos columnas o cambiemos el material de los cimientos nos negaríamos rotundamente, porque somos profesionales responsables y eso no es sustentable en el tiempo. No es, para cerrar el circulo, mantenible.

Costante universal


Intuitivamente todas sabemos que es la calidad de desarrollo de software y desde este blog hemos machacado una y otra vez con el concepto de que es fundamental toda vez que una buena calidad de desarrollo de sofware permite la màs importantes de las "ilidades" como es la Mantenibilidad, fundamental porque es la actividad que uno mas realiza sobre un sistema. A la vez una buena calidad ayuda tambien a la reusabilidad .
Por último es importante como vimos en el post anterior porque ayuda a aceptar cambios de alcance y de definición del usuario (que como ya explicamos son ineludibles) y permite incorporarlos al sistema de una manera menos costosa y con mucha menos perdida de tiempo que con un sistema de calidad baja.

Por ello, para terminar, como diría Stephen Hawking, la Calidad del desarrollo de software mas que una de las 4 variables del desarrollo debería ser una Constante Universal.

jueves, 10 de marzo de 2011

Calidad del desarrollo I - El Pato de la boda

Volviendo de un periodo de inactividad en este blog a causa de vacaciones varias, algún que otro viaje y temas de trabajo de variada indole vamos a retomar nuestra habitual lucha entre bits, bytes, tuits, posts y lo que toque en suerte.

Hay un tema que siempre ha sido muy caro (por querido, no por el costo, aunque tiene que ver) a mis sentidos y es el tema de la Calidad de un desarrollo de software.

El tema, específicamente para este post es el siguiente:

Cuando comienza un proyecto somos todos buenos, las mejores intenciones son puestas en la mesa, y las buzzwords y palabritas fashion del momento vibran en el aire. Se escucha a programadores, funcionales, testers y lideres decir frases como por ejemplo:

"Vamos a trabajar con OOP bajo arquitectura SOAP y BRMS" "Utilizaremos CEP, BDD, MDD y TDD.", "Aplicaremos los mejores Design Patterns, el GOF, AOP y la madre que me pario."

y así en esas primeras reuniones todo es redondo y bonito, el papel lo soporta todo, así que el diseño de alto nivel cierra y reunidos ante la mesa redonda todos juramos proteger la Calidad del desarrollo cueste lo que cueste, verdad?

Bueno ahi entran a tallar el circulo de presiones de las 4 variables de todo proyecto (de sistemas por lo menos, que es lo que uno ha trajinado bastante):

Como todos sabemos las decisiones y acciones que realizamos durante un proyecto afectan constantemente a estas cuatro variables que están interrelacionadas y uno no puede manejar las cuatro a la vez (y eso de poder definir siquiera dos ya es de por si bastante difícil). Simplificando bastante (y lo que sigue si hilamos fino ni siquiera es totalmente cierto) o bien definimos el costo, alcance y la calidad y eso hace que el tiempo no pueda fijarse y será el tiempo que tome realizar ese alcance con ese costo y calidad. O bien definimos el alcance, tiempo y costo, y la calidad será la calidad que se pueda obtener con ese alcance, tiempo y costo.

Entonces, lo que sucede habitualmente es que un proyecto comienza con un alcance dado, un tiempo mas o menos definido de finalizacion, un costo fijo y determinado hasta los centavos y la promesa de una calidad altísima. Si, por si no se han dado cuenta empezamos casi queriendo violar las leyes de la física y manejar las 4 variables!

A continuación sucede algo conocido como "la realidad". Es decir, el alcance cambia. Siempre. De verdad. Siempre.

O bien el usuario se da cuenta que lo que pidió no es lo que quería, o se da cuenta que le falto pedir funcionalidad im-pres-cin-di-ble, o lo que era un simple linea en un documento termina siendo una funcionalidad clave cuyo desarrollo implica 3 módulos nuevos o bien el negocio o las leyes cambian o lo que sea pero lo cierto es que cambia. De cuando se de cuenta de esto depende en parte de la metodología de desarrollo que se utilice, no quiero entrar en detalle pero digamos simplemente que la tradicional en cascada suele hacer que el usuario se entere cuando ya no puede cambiar nada.

Uno puede tomar ante esta realidad dos caminos. O bien congela el alcance rechazando los cambios o bien permite los cambios. No vamos a discutir aquí que pasa si uno rechaza los cambios obligando al usuario a aceptar que desarrollemos un sistema que no necesita.

Al permitir los cambios sabemos que como el alcance ahora es mayor las otras variables se verán afectadas. El tiempo para terminarlas crecerá , saldrá mas caro terminarlo o..... o la calidad del producto sufrirá.

El costo en general es casi un taboo tocarlo. Implica decisiones políticas. Implica que el gerente del proyecto hable con el cliente o el gerente interesado (el que deberá "pagar") y blanquee la situación para asumir un cambio en el presupuesto. Todo lo cual es....complicado.

El tiempo para hacerlo también es parte de los "Intocables". En reglas generales hay deadline y fechas comprometidas dentro de los proyectos que implican determinadas promesas a clientes o sectores externos, promesas que de no cumplirse pueden traer problemas. En otras casos las fechas sirven como puntos de coordinación con otros eventos (lanzamiento de productos, de campañas de marketing, de instalación y capacitación para el nuevo sistema, etc.) que hacen que sea oneroso o muy impactante su prorroga.

Ni que hablar del costo.

El pato de la boda termina siendo siempre siempre la calidad.

El problema en este caso, material de otro post que publicaremos posteriormente, es que es, para seguir con las metáforas de patos y cazadores, como dispararse en el propio pie.

Cuando uno afecta a la calidad afecta fundamentalmente(el detalle, como dije, para un post próximo) a la velocidad para cambiar el sistema, a su estabilidad y mantenibilidad, es decir afecta en una espiral ascendente al tiempo y al costo.

Es decir que....porque cambio el alcance o nos estamos atrasando, para tratar de cumplir con la fecha y el presupuesto inicial dejamos de lado justamente la Calidad lo cual hace que vayamos MAS LENTO y terminamos no respetando ni el tiempo ni el costo. Y para colmo nos queda un sistema inmantenible!!.

Y ni que hablar que todavía no definimos que entendemos exactamente por calidad de desarrollo! Otra tarea para el próximo post!.





Nota de autor: "Ser el pato de la boda" es una expresión utilizada al menos en Argentina refiriéndose a alguien que carga con las responsabilidad de algún suceso sin ser el culpable y que debe pagar por ello.

lunes, 20 de septiembre de 2010

"Pasos de Bebe", El fin del Debugging?

Baby Steps

Mirando a nuestro hijos aprender a caminar es fascinante. En un momento están agarrados de un sillón, una silla o de nuestras piernas y de repente comienzan a dar el primer paso, pequeño, muy cercano, y luego otro, tanteando con un pie hasta estar firme y luego , tambaleantes, llevan el otro pie al lado. Y así. Con el instinto que la madre naturaleza les dio, nunca intentan empezar a correr o dar zancadas.

Alla Lejos y hace tiempo

Hace muchos años, en nuestros primeros trabajos (en esa época teníamos que fabricar nuestros propios bytes :), nuestra forma de trabajo, a grandes rasgos, era algo asi:

1. Escribir un montón de código.
2. Compilar el código escrito y corregir los errores (no, no habia intellisense).
3. Probar y debuguear el código una y otra vez hasta que funcione.

Cada una de estas etapas tomaba días o incluso semanas. Cuando nos preguntaban como venía el proyecto, la respuesta típica era "ya terminé de escribir el código, me falta probarlo". Si tenías suerte, nadie te preguntaba cuanto tiempo de trabajo te faltaba...

El problema justamente es que luego de incluir en el proyecto una cantidad de lineas de código producida durante varios días, no hay forma de predecir cuanto tiempo llevará terminar el punto 3. Y ni siquiera estamos hablando de que este punto implicaba realizar "casos de prueba" exhaustivos, este punto solo significaba que lograbamos hacer que el código funcionara en los escenarios más comunes (con suerte).

Esta forma de encarar el desarrollo es un resultado natural de toda la corriente de Waterfall muy en boga en esos días. Si lo más productivo es primero hacer todo el análisis, después todo el diseño y después toda la codificación, tiene sentido dividir este último paso en etapas también.

Con el tiempo, y luego de muchos golpes, y algunas pesadillas, empezamos a trabajar de una forma bastante distinta:

1. Escribir 3 o 4 líneas de código.
2. Compilarlo.
3. Probarlo.

La gran diferencia es que generalmente los pasos 2 y 3 no llevan nada de trabajo, ya que somos capaces de escribir 3 líneas de código sin equivocarnos o cometiendo sólo errores obvios y luego probar que funcionan esas 3 o 4 lineas nuevas es algo manejable y en general muy sencillo de realizar(de hecho, programando así casi no se usa el debugger, vale la pena remarcarlo: Casi no se usa el Debugger, y ni les cuento si esas 4 lineas de código se escribieron a partir de un test, haciendo TDD).

Esta forma de trabajar fue descrita como una buena práctica de desarrollo por varios referentes de nuestra profesión, la mayoría proveniente de las metodologías ágiles, y se le dio el nombre de "Pasos de Bebe", "Baby Steps", en ingles. Recientemente se la describió con otro nombre mucho más técnico, "Desarrollo Nano Incremental".

Ahora, cuando nos preguntan como va el proyecto, generalmente la respuesta es del tipo "la aplicación ya puede hacer X e Y, falta que haga Z y terminamos". Además el tiempo total que lleva hacer las cosas es mucho menor, ya que los pasos 2 y 3 llevaban semanas (y a veces un tiempo indeterminado) en la forma de trabajo anterior, llamemosla, para ponerle un nombre igual de rimbombante: "Big Bang de Código".

¿Por qué se da esto?

En primer lugar, porque el desarrollo de software es complejo y nosotros los humanos no podemos manejar toda la complejidad de golpe si no la atacamos dividiendola en "trozos" manejables (Divide y Venceras, dice el dicho). Somos capaces de hacerlo bien para cambios pequeños, pero cuanto más grande es el salto que queremos dar, más probabilidades tenemos de cometer errores, que después llevan mucho tiempo corregir.
Esto se nota mucho cuando utilizamos TDD, donde escribir tests demasiado grandes nos lleva a cometer muchos errores e incluso produce que uno no pueda avanzar (esta fue una de las cosas que notamos en el último Code Retreat).

En segundo lugar, tomar pasos pequeños nos permite aprender de nuestros errores. El conocimiento que obtenemos en cada ciclo es utilizado en el siguiente, que tiene lugar unos minutos después. En cambio cuando se utiliza el "Big Bang de Código", las cosas que se aprenden se pueden utilizar recién en el siguiente proyecto.

Además, tener siempre código compilable y que funciona nos permite obtener feedback de la gente para la cual estamos trabajando. Es un hecho que la mayoría de los clientes no sabe exactamente lo que quiere hasta no ver una aplicación funcionando y si desaparecemos durante meses antes de mostrar algo es probable que terminemos programando algo muy distinto a lo que nuestros clientes necesitan.

Por último, este desarrollo nano-incremental permite justamente ir evolucionando muy despacio el diseño, y sólo con lo que se necesita para resolver el problema en cuestión sin agregar funcionalidad extra que no se necesitara. Justamente al diseño así obtenido se lo llama Diseño Incremental.

Pasen la Palabra

Pese a todos estas razones, y evidencia de muchas fuentes, y entre ellas, nuestra propia experiencia, vemos que la forma de trabajo más común entre los programadores sigue siendo el "big bang" de codigo. Y para ser sinceros, hemos tenido hasta ahora relativo éxito en conseguir convencer a nuestros compañeros de utilizar el "Pasos de Bebe".

Intuitivamente, se sigue creyendo que juntar grandes lotes de código para después probarlo es más eficiente y productivo. Es razonable, porque para muchas tareas de la vida real es así: si uno va a lavar los platos conviene primero ponerle detergente a todos los platos, después enjuagarlos y después lavarlos. No tiene sentido tomar un plato, ponerle detergente, enjuagarlo y secarlo.

Sin embargo, el desarrollo de software no se parece al lavado de platos (ni tampoco a la construcción de edificios para el caso).

Así que si se animan a probar un deporte de riesgo, si les gusta luchar con leones hambrientos y no son débiles de corazón, en su próximo proyecto apliquen esta practica de desarrollar en "Pasos de Bebe". Les aseguramos que van a ver una considerable mejora en su productividad.

Y mucho, mucho, menos debugging.

miércoles, 1 de septiembre de 2010

Inscripcion al Segundo Code Retreat!!

Se viene el segundo Code Retreat!! Para todos los que protestaron (con total justicia) porque el primero fue un sábado muy temprano, esta vez va a ser el Viernes 10/09, de 14:30 a 20 horas, en el MUG (Microsoft User Group), que queda en Rivadavia 1479 Piso 1 Of. A.

Estamos muy contentos porque la pasamos muy bien en el primer Code Retreat que hicimos a principio de año.

Aquí, en el sitio de la comunidad ágil de Argentina se puede ver más información sobre el evento y los interesados pueden anotarse en esta página.

Los esperamos!

lunes, 2 de agosto de 2010

Code Smells

De chiquitos aprendemos que hay que evitar lo que tiene mal olor. La madre que huele el pañal de su hijo sabe que si apesta tiene que cambiarlo, y si apesta mucho, mucho, quizás el bebe tenga algún problemita de diarrea o algo similar. Sentido común universal este que sin embargo no aplicamos frecuentemente en el desarrollo de software.

A lo largo de la corta pero no menos exitosa vida de este Blog hemos mencionado varias veces a los Code Smells, sin aclarar su significado, mea culpa, porque a veces damos por sentado conceptos que son muy útiles. Este post entonces intenta corregir semejante falta:

Code Smells: (Aplicado al arte de la programación) son todos los síntomas que podemos encontrar en el código fuente de un sistema que indican que muy probablemente existan problemas más profundos de calidad de código, de diseño o de ambos.

El termino fue acuñado por Kent Beck y Ward Cunninghan hacia fines de los 90 y su uso se popularizó a partir del libro de Martin Fowler y otros: "Refactoring, Improving the Design of the existing Code" .

Si pensamos las barbaridades que hemos visto en algunos códigos fuentes (siempre de compañeros, nunca nuestros... :O ) y asociamos esa sensación de horror y rechazo con el olor a podrido de algunos ríos contaminados (Nota para los argentinos: Iba a poner Riachuelo pero no se si el resto del mundo conoce la fama "olorosa" de nuestro querido río, querido porque esta en la Boca ;), decía, esa imagen gráfica claramente lo que significa Code Smell, síntoma de que algo Apesta, y como al pañal, hay que cambiarlo.

En la práctica, históricamente, los Code Smells se han usado para identificar partes del código de baja calidad a las que aplicar las técnicas de refactoring explicadas en el libro arriba mencionado. Es decir, el libro describe un conjunto largo de distintas técnicas de transformación de código sin alterar su significado, las asi llamadas "Técnicas de Refactoting" y los Code Smells son los que indican en que parte del código hay que revisar como candidatas para aplicar esas técnicas.

No es la intención de este post describir uno a uno los Code Smells porque eso llevaría demasiada "tinta virtual" pero prometemos ir describiendo los Smells principales ya que consideramos (y bueno, no seria nada nosotros pero también lo piensa la gente más brillante de nuestro campo de la programación) que es uno de los conceptos fundamentales de la programación de estos tiempos, de los más aplicables y útiles, en combinación con los tests de unidad y que mayor impacto tienen tanto para la productividad como para la calidad de los sistemas que generemos.

Los principales Code Smells que se pueden encontrar en el código son :

  1. Código Duplicado
  2. Parámetros Booleanos
  3. Métodos Largos
  4. Clases Largas
  5. Larga Lista de Parámetros
  6. Cambio Divergente
  7. Shotgun Surgery (traducido algo asi como "cirugía a escopetazos")
  8. Feature Envy (textualmente: "envidia de features")
  9. Data Clumps (algo asi como aglomeracion de datos, masa de datos, en sintesis: un bodoque de datos (Arg))
  10. Obsesión por primitivos
  11. Generalización especulativa
  12. Campos temporales
  13. Refused Bequest ( algo asi como Rechazo a recibir parte de una herencia)
  14. Etc. (porque hay muchos mas).

Sigan sintonizando nuestro canal http://trainedchimpanzees.blogspot.com , porque vamos a estar analizando los mismos en sucesivos posts. De hecho ya empezamos a describir los Code Smells, uno de los primeros posts que hicimos fue sobre el Smell "Parametros Booleanos".

Para terminar una frase atribuida a la abuela de Beck, tómenla como consejo:

"Si apesta, hay que cambiarlo!"

lunes, 19 de julio de 2010

POO - Ejemplos de la ley de Demeter

Para dar un poco más de sustancia y aclaración al posteo del otro día sobre leyes y principios de Programacion Orientada a Objetos vamos a ir armando pequeños ejemplos de aplicación de los mismos.

Seguro no tenemos la menos necesidad de repetir porque Toooodoos recuerdan la ley de Demeter que decia:

 Un método m, de una clase C, solo debe invocar métodos:

  1. De la misma clase C (métodos privados)
  2. De un objeto creado en m (Variable local)
  3. De un parámetro, pasado como argumento a m (parámetros)
  4. De una variable de instancia de C. (Variables de instancia de la clase

En otras palabras, un objeto no debe conocer la estructura interna de los objetos directamente relacionados con él, ni obtener a través de ellos a otros objetos para manipularlos o enviarles mensajes.

Para ser no-innovadores vamos a usar un ejemplo clásico de la ley de Demeter, conocido como el ejemplo del chico-Diariero (PaperBoy). La clase en nuestro ejemplo la nombramos simplemente Diariero. El ejemplo se basa en la relación entre El Diariero y el Cliente del diario en el momento en que se quiere cobrar tan solo un diario entregado.

Una posible implementación que viola el principio de Demeter (y que la hemos visto utilizada en código de proyectos reales, con ligeras variaciones, una y otra vez) es :

 
 
public class Diariero 
{
private static final 
double COSTO_DIARIO = 3.5;
 
  public Money cobrarDiario(Cliente cliente) {
    return cliente.getBilletera().extraer(COSTO_DIARIO);
  }
}

Es decir, la clase Diariero usa al parametro Cliente, le pide su billetera y extrae de ahi directamente el costo del Diario (el cual, para simplificar aún mas es una constante).

Aqui se puede ver fácilmente porque se viola el principio de Demeter de una manera bastante gráfica. El diariero está literalmente "metiendole la mano en el bolsillo" al cliente, y sacandole la plata. De una manera coloquial a esto es exactamente lo que apunta a evitar el principio. Que los objetos no "violen" los limites de las responsabilidades asignadas ni generen acoplamientos innecesarios. Que pasaría en este ejemplo si el cliente nos quiege pagar con algún otro medio de pago, por ejemplo, con Cheques? Habría que modificar ambas clases, Cliente y Diariero (y quizás algunas más).

Es interesante ver que el uso de getters tipo getBilletera es muy común y no causa sospechas en nadie (de hecho muchas ides tienen forma de generarlos automáticamente), pero que si en vez de usar un getter usáramos variables de instancia públicas tendríamos inmediatamente a la policía de los Objetos pidiendo nuestra captura. Sin embargo, el acoplamiento causado por este uso de los getters es casi el mismo que si usáramos variables públicas (y ni hablar cuando no solo tenemos getters sino que también tenemos setters!).

Veamos por otro lado una implementación que respeta la ley de Demeter :

 
public class Diariero {
   private static final double  COSTO_DIARIO = 3.5;
 
   public Money cobrarDiario(Cliente cliente) {
     return cliente.cobrar(COSTO_DIARIO);
   }
}
 
public class Cliente {
   private Billetera billetera;
 
  private Billetera getBilletera() {
     return billetera;
  }
 
  public Money cobrar(double costoDiario) {
      return getBilletera().extraer(costoDiario);
  }
 
}

Notar que en este ejemplo, el método getBilletera permanece privado (es algo privado justamente de cada Cliente), y no es accedido directamente. El diariero le pide al cliente que le dé el dinero a través del método cobrar. Luego este método es el que resuelve como obtener el dinero, por ahora extrayéndolo de la billetera, pero si quisiera podria devolver un cheque (deberia ser una subclase de Money, quizás) o algún otro medio de pago, sin necesidad de modificar la lógica de la clase Diariero.

En general se debe seguir la Ley de Demeter pero hay que tener cuidado con hacerlo demasiado al pie de la letra. Demeter apunta a reducir las llamadas del estilo a.b().c().d() (los clásicos "choques de trenes") , que claramente indican un problema, pero también hay que tener cuidado con llenar las clases de métodos que solo funcionan como intermediarios entre objetos. Al respecto Martin Fowler dice que estaría más correcto llamar a esta regla la Sugestion de Demeter, ya que no es algo absoluto.