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

miércoles, 20 de abril de 2011

Lecciones reaprendidas

Hoy tuve unas de esas peleas con el código que te hacen reconsiderar el pasarte a Management :). No fue muy sangrienta, sólo un bloqueo de media hora, pero cometí tantos errores repetidos que cuando finalmente logré hacer lo que quería no sentí satisfacción sino bronca.

Mi objetivo era hacer una subclase de una clase básica del entorno, para agregarle cierta funcionalidad. Estaba apurado porque tenía poco tiempo y quería terminar esta tarea hoy. Intenté el camino obvio: crear la subclase y utilizarla en lugar de la clase del sistema. Esto no me funcionó y como estoy en un entorno bastante nuevo (Objective-J/Cappuccino), decidí que la herencia no debía estar funcionando bien (??). Entonces me puse a buscar maneras de lograr mi objetivo de otra manera: intenté con un wrapper de la clase que quería modificar, con modificar el comportamiento de la clase que llamaba a la nueva clase y con unas cuantas maneras más, sin resultado. Busqué un rato en Google, pero no encontré ninguna referencia a mi problema. Estaba atascado. Ya perdido, volví a intentar el camino inicial, y funcionó!!. Revisé lo que había hecho en mi primer intento y por supuesto, encontré un problema en mi implementación inicial.

Los errores que cometí fueron los siguientes:

1. Asumir que la herencia no funcionaba. El compilador nunca está roto!!! Bueno, si, a veces está roto, pero en 20 años de programar sólo he descubierto 2 o 3 de esos errores y me he equivocado muchas veces. Es siempre mucho más probable que el error este entre el teclado y la silla.

2. Trabajar apurado. Quería terminar hoy y dejé que el apuro dominara mi forma de trabajar. Al final me llevó más tiempo que si lo hubiera hecho tranquilo.

3. No hacer un experimento. Si sospechaba que la herencia estaba andando mal, tendría que haber armado una clase sencilla y probar las cosas ahí. Si no lograba reproducir el problema, probablemente hubiera sospechado la verdad...

4. Insistir en arreglar el código que había hecho. Cuando uno no encuentra un error que obviamente tiene que estar ahí, lo más sencillo es borrar las modificaciones y empezar de nuevo. Tengo la costumbre de hacer commits muy frecuentes, así que volver atrás mis cambios no hubiera sido costoso. Además, estoy usando git, asi que también hubiera podido volver atrás temporariamente con un git stash.

5. Trabajar sólo. Este fue exactamente el tipo de problema que haciendo Pair Programming no me hubiera pasado.

Bueno, ahora que lo escribí se me pasó un poco la bronca... la próxima vez que sospeche del compilador espero acordarme...

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, 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!"

jueves, 22 de julio de 2010

¿Cuántos libros técnicos leiste este año?

"Tenes que leer este libro y presentarlo"

El primer libro técnico que leí por motivos laborales fue "Code Complete", de Steve McConnell, en el año 1996. En el trabajo en que estaba en ese entonces me dieron la asignación de leer el libro y presentar partes de el a mis compañeros. Empecé la tarea con pocas ganas, pero pronto me di cuenta de que la lectura de este libro iba a cambiar mi vida profesional para siempre. La posibilidad de "pararme en los hombros de un gigante" al aprender de alguien con tanta experiencia como McConnell me fascinó y a partir de ese momento he intentado siempre leer la mayor cantidad de libros técnicos posible.

Libros y capacitación

Un libro es probablemente la manera más económica de capacitarse. "The Pragmatic Programmer" de Andy Hunt y Dave Thomas (un libro excelente, si van a leer un sólo libro este año, lean este) cuesta 40 dolares en Amazon. Tomando en cuenta el envío probablemente el costo total debe rondar los 200-250 pesos. ¿Qué curso se puede tomar por ese precio, aun suponiendo que fuera posible encontrar uno que valga la pena?. Si se comparan las versiones electrónicas de los libros los costos son aún menores, ya que cuestan menos y además no hay que pagar envío.

Por lo tanto para una empresa que le de importancia a la capacitación, es posible lograr muy buenos resultados invirtiendo unos $1000 por mes. Por supuesto hay que tomar en cuanta que con sólo comprar los libros no alcanza y que hay que buscar maneras de lograr que los libros sean realmente leídos y aplicados. Una práctica que da muy buenos resultados es que los miembros de un equipo se compromentan a leer un libro y armar almuerzos quincenales o mensuales donde todos puedan discutir algunos capítulos o armar presentaciones y resúmenes.

¿Sigue valiendo la pena invertir en libros con toda la informacion disponible en la Web?

Depende del tipo de libro. Los libros de referencia probablemente no sean una buena inversión: es mucho más sencillo usar Google (y más barato, una vez compramos un libro de referencia sobre Java, llamado "Java Bible", fue muy útil....como soporte de la pata de una mesa). Sin embargo los libros que tratan sobre un tema desde una perspectiva más completa, si lo son. Por poner un ejemplo, no tiene sentido buscar como hacer paginación en Rails en otro lado que no sea Google (o Bing!, ;) pero si uno quiere entender realmente como funciona Rails solo lo va a poder hacer desde un libro, donde los conceptos van a estar presentados de una manera mucho más integral (y al respecto recomiendo el excelente "The Rails Way"). Esto tiene que ver con lo que contábamos en "cargo cult programming": para buscar una solución rápida a un problema probablemente el mejor recurso es la Web pero para entender realmente por qué funciona esa solución lo mejor es un libro (o un curso, claro que tomar un curso en EEUU o Europa no es para cualquiera).

Spik in inglish?

Una dificultad adicional que tenemos en países donde no se habla inglés es el idioma. El porcentaje de buenos libros técnicos traducidos al castellano es muy bajo y la calidad de las traducciones es muy mala (nunca voy a olvidar la traducción de buffers como "tampones de memoria" en un libro de redes de la época de la facultad). Esto hace que la incapacidad de leer correctamente inglés sea un escollo insalvable para ser un buen profesional. Si alguien que no sepa este idioma quiere dedicarse al desarrollo de software su mejor inversión (mejor que aprender cualquier tecnología) va a ser dedicarse a aprenderlo.

cuanto$?

Los programadores somos trabajadores intelectuales y por lo tanto nuestros conocimientos constituyen nuestro capital. Si dejamos de actualizarnos nos descapitalizamos y perdemos la posibilidad de conseguir mejores trabajos y ganar más dinero. Dedicar una pequeña parte de nuestro tiempo a leer libros es una manera de aumentar nuestro valor en el mercado y mejorar a la vez profesionalmente.

Entonces, ¿Cuántos libros técnicos leiste este año?

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.

miércoles, 5 de mayo de 2010

Desconfíen de los parámetros booleanos

Este post es el primero de una serie que vamos a hacer con consejos sobre calidad del código y en particular sobre mantenibilidad (algo que consideramos muy importante).

Uno de las primeros consejos de legibilidad de código que uno recibe cuando empieza a programar profesionalmente es que no se deben usar "números mágicos" y que todos los valores literales con significado especial para nuestro programa deben ser reemplazados por constantes. Esto se hace para protegernos de posibles cambios pero sobre todo para mejorar la legibilidad de nuestro código (después de todo se suele usar la constante PI, cuyo valor es dificil que cambie).

Sin embargo, este criterio no se sigue en el caso de parámetros booleanos y entonces es común ver métodos con definiciones como esta:

public FileWriter(File file, boolean append) {
 
}
 

Este es un constructor que es parte de la biblioteca standard de Java. Si se mira el código del lado del método la cosa no parece tan fea. Si uno elige un buen nombre para el parámetro el código queda claro:

public FileWriter(File file, boolean append) {
    if( ! append) {
            //trunca el archivo
    }
}
Sin embargo, si uno mira el código en la llamada al método el resultado es bastante críptico:
FileWriter writer = new FileWriter(file,true);
¿Qué significa ese true? ¿Significa "truncá el archivo" o significa "hace append al archivo"?. Esto depende del nombre que le hayamos puesto a la variable y la única manera de saberlo es ir a la definición del método y leer el código. Es exactamente lo mismo que nos pasa cuando nos encontramos un "número mágico".
Es interesante ver como este efecto no se da en todos los lenguajes. En aquellos que tienen la posibilidad de parámetros con nombre como Smalltalk (o permiten simularlos como Ruby) el código de la llamada es completamente legible:
writer = FileWriter.new(file,:append => true);
¿Como podemos hacer para solucionar este problema? Lo primero que se nos ocurre es hacer lo mismo que normalmente hacemos con los literales de otros tipos, es decir reemplazarlos por constantes con nombres significativos:
public enum {
  Append,
  Truncate
} CreationMode;
 
public FileWriter(File file, CreationMode creationMode) {
    if(creationMode == CreationMode.Truncate) {
            //trunca el archivo
    }
}
 
FileWriter writer = new FileWriter(file,CreationMode.Append);

Sin embargo, antes de tomar este camino es bueno revisar si la existencia de este parámetro booleano no nos está alertando sobre un problema más de fondo. Básicamente este tipo parámetros permite al código llamador controlar el flujo de ejecución del método llamado, algo sospechoso no ya desde el punto de vista de la programación orientada a objetos si no desde la óptica de la programación estructurada. Por lo tanto es probable que si revisamos el código del método nos encontremos con que en realidad la mejor solución es tener dos métodos cada uno con uno de los comportamientos que originalmente ocurrían al pasar el flag en true o false.

Como normalmente ocurre con estos consejos, esto no significa que no haya que usar jamás parámetros booleanos, si no que es bueno antes de usarlos considerar otras opciones. Además tenemos que tener en cuenta que cuando escribimos un método no solo importa la calidad del código del método que escribimos si no que su interfaz no lleve a los usuarios de dicho método a escribir mal código (sobre todo sabiendo que muchas veces los usuarios vamos a ser nosotros mismos o quizás un psicopata violento que sabe donde vivimos)