Encuesta

Mi telefono móvil es un...

01-09-2010 - 206 votos

Destacados Agenda

Más eventos |

(2)

JavaHispano Podcast - 071 - Analizadores estáticos del código

28/01/2010 23:19 JorgeRubira

Publicado un nuevo número del podcast de javaHispano. En esta ocasión hablaremos de los analizadores estáticos del código presentado por Alfredo Casado, Francisco Morero Peyrona y Raúl Exposito. En esta ocasión hablaremos de los analizadores estáticos del código y enumeraremos algunos de ellos comentando sus características:

Links de interés:

Links de los invitados:

ACTUALIZACION: Subidas las reglas de PMD que comenta Peyrona. Pulsar aquí para descargar.

Volver a actualidad

Etiquetas: otro, podcast, pmd, cpd, checkstyle, firebug, sonar

Comentarios: 39

  • Anónimo 29/01/2010 00:24

    Aca les dejo un ejemplo donde se incluyen esos reportes y algunos mas en el POM de un proyecto Maven para generar un sitio con toda esa informacion del proyecto.

    http://code.google.com/p/quickdb/source/browse/trunk/java/pom.xml 

    Diego 

  • Anónimo 30/01/2010 16:30

    A raíz de este PodCast, he instalado el plugin para Netbeans y viola, sensacional, funciona bien. Pues, no me queda más que felicitarles por este trabajo...gracias.

  • Anónimo 30/01/2010 16:32

    UPs...se me olvido decir que plugin, me refería a PMD.

  • Marioko 30/01/2010 16:51

    yo uso Hudson + SVN + Maven + Sonar = power killer combination :D

    Hudson se descarga el codigo usando svn, maven lo compilia y lo testea y sonar lo analiza y puff mucha info de donde tomar para mejorar los proyectos.. 

    PD: ya sobre decirlo, pero excelente podcast :D 

  • raulexposito 30/01/2010 17:32

    Marioko, esa combinación que comentas es de las que más normalizan el desarrollo del software, pero sin tanta infraestructura también se puede conseguir automatizar el análisis estático del código. Lo comento por si alguien sin tanto soporte también quiere hacer estos análisis.

    Podríamos usar sólo maven y configurarlo como indica Diego en el primer comentario, crearnos metas para ant o usar los plugins de nuestro IDE como también comentan más arriba. Lo importante de hacer estos análisis es poder detectar problemas antes de darles la posibilidad de ejecutarse y que se manifiesten.

    Saludos 

  • jcesarperez 30/01/2010 19:48

    Enorabuena. Me ha gustado mucho.

    Un par de cosas:

    @peyrona: genial tu idea de ese demonio que analiza los resultados del analizador y crea issues en el issue manager del proyecto. Tienes algo de código publicado o conoces algun proyecto existente?

    Respecto a Checkstyle. Tiene un juego de reglas completísimo. No es sólo para temas de formateo de código. La ultima vez que lo comparé cubría al de PMD y también tiene detector de duplicidad de código. Yo en su día cuando los comparé, me quede con Checkstyle porque me gustaba mucho más su plugin para Eclipse que el de PMD. Para Netbeans no sé cómo serán.

  • Anónimo 30/01/2010 22:45

    Magnifico podcast. Me ha encantado.


    Y aunque estoy de acuerdo en la mayoría de vuestras opiniones, hay un par de puntos en concreto en el que estoy totalmente en desacuerdo. Los comento a continuación con el anímo de abrir un pequeño debate.


    El primero de los puntos es referente a lo que comenta Alfredo sobre en número de lineas de un método y la complejidad ciclotomatica. Desde mi punto de vista, lo característica más importante que tiene que tener el código (a parte obviamente que funcione y cumpla las necesidades del cliente) es que siga el Principio KISS (me quedo con la aceptación de Mantenlo Simple Estúpido). Las herramientas de análisis de código estático ayudan a cumplir el principio KISS.

    Un método debería tener el número de lineas que sea necesario para cumplir el Principio KISS, o como comenta Peyrona, el número mínimo de lineas necesario para que sea simple. Las cosas tienen que estar en el lugar donde un tercero esperaría encontrarlas. A mi parecer, las sorpresas (y la mágia) en el código es un grave error. Dividir un método largo en varios métodos solo para reducir el número de lineas puede no ser buena idea, pues dificulta seguir que exactamente (nos obliga a saltar de un lado a otro), y además dificulta su mantenimiento, al no tener todo el código junto.

    Soy de los que creo que un programador sin experiencia con un libro de patrones en la mano es como un pinguino con dinamita, y del mismo modo un programador novel al que le digamos que sus métodos tienen que tener como máximo X lineas es como un mono con una escopeta, y al menos a mi, no me gusta tanto el riesgo como al el del coche del anuncio.

    Los códigos más absurdamente complejos que me ha tocado mantener han sido desarrollados usando patrones innecesarios y multitud de métodos cortos que se podían haber evitado. Por poner un ejemplo, hace años en un proyecto en el que participé, un desarrollador para evitar duplicar código en los Action de Struts se le ocurrió una jerarquía de Actions donde unos heredaban de otros con varios niveles. Consiguió que no hubiera nada de código duplicado, pero tras dejar la empresa, no había hijo de vecino que metiera mano a su código, y tuvimos que tirarlo todo a la basura y programarlo de nuevo, con código duplicado si, pero fácil de entender y mantener.

    Además, aunque reduzcamos la complejidad ciclotomática del método, realmente no conseguimos nada, pues la complejidad sigue estando hay, aunque en otro método. Lo que a mi me importa es la complejidad pero de una funcionalidad completa.

    Relacionado con esto también se ha comentado que el Copy&Paste es malo. Tampoco estoy de acuerdo. Lo que es malo es no seguir el principio KISS y el Copy&Paste será malo si y solo si lo que estamos haciendo va en contra del principio. Imaginaros si lo llevamos al extremo: Si no hacemos ni un Copy&Paste, todo a funciones reutilizables, el resultado puede ser miles de métodos inmantenibles. 

    El otro punto en el que no estoy de acuerdo es en el de hacer código pensando en los test. Se ha comentado sobre todo en el Podcast de testing y en este de pasada, que hay que hacer código pensando en los teses, y que para ello hay que seguir una serie de reglas. Creo que sacrificar la arquitectura de una aplicación para que los test sean más faciles de pasar es una muy mala política. Me ha pasado en alguna ocasión manteniendo código de terceros, encontrarme cosas raras, hechas de forma excesivamente enrevesada y muy poco intuitiva, y descubrir más tarde que la razón de que ese codigo se hiciera asi era porque si no el test quedaba muy complejo o no se podía hacer. Soy fan de los test, pero desde mi punto de vista, si no se puede hacer test, que no se haga, pero el código debe ser facil e intuitivo.

    Espero que nadie se tome estos comentarios a mal. Me gustaría que sirvieran para abrir debate.


    @peyrona: ¿Podrías decirnos que subconjunto del reglas del PMD has considerado que son las más importantes? Me encantaría saber que reglas ha elegido una persona con tan experta y con tanta experiencia como tu.

  • JorgeRubira 30/01/2010 23:18

    Buenas

    Anonimo, pues muy interesante tu post! y abre un buen debate que será muy fructifero. Yo te puedo dar solo mi opinión y mi punto de vista, pero no es la gran verdad :)

    En cuanto al primer punto. No sé si es mania mía o no pero muchas veces entiendo más leer un texto similar a este:

    CalculaTotalVentasParaClientesActivos(parametros...)

    Que leer las 50 líneas que podría tener este método. Ahora bién!. Este código tiene que ser bastante independiente y no basarse o basarse en pocas variables de resultados anteriores. Cuando un método se hace muy grande al menos intento facilitar la lectura creando métodos con nombres muy descriptivos. No se reduce código, pues ese método no se va a reutilizar pero el nombre me ayuda a tener en una misma ventana más "objetivos" o "conceptos" que escribir todo el código. Así que de un vistazo veo más funcionalidad. Sería como hacer un resumen de un libro. Está claro que para entender el libro hay que leerse todo, pero para buscar una página en concreto, es mejor tener un buén indice y claro.

    En cuanto al problema del copy/paste, el hacer copy paste tiene como consecuencia que si tienes que cambiar algo en un método en el que has hecho copy/paste 10-100 veces, tendrás que cambiar esto tantas veces como copy/paste hayas realizado. Por lo demás estoy totalmente deacuerdo que utilizando la herencia se pierde un poco la compresión y el seguimiento del flujo del código. Yo soy mucho más partidario, quizá porque vengo de C, de utilizar invocaciones bién definidas (incluso aunque sean static) de manera que leyendo el código fuente sin ejecutarlo puedas entender la aplicación. Es una cosa que en otro podcast le comenté a Alfredo de la perdida de compresión sobre un código que no has hecho tu. Alfredo nos comentó que en ese caso hay que tener diagramas que te expliquen como funcionan las cosas.

    Sobre lo del test, no puedo opinar...

    Saludos, Jorge

  • remoh 31/01/2010 04:14

    Lo más importante de estas cosas es precisamente abrir debate, así que este de acuerdo o no con algunos planteamientos nadie se toma nada a mal, todo lo contrario!. Mi opinión sobre los 3 puntos que mencionas:

    Limite en el número de lineas y CC: Estos limites me gustan porque aunque los limites son arbitrarios (hay que poner un número) la forma de interpretar los errores en estos casos no lo es. Quiero decir con esto que estos avisos del analizador estático sirven como alarmas, pero siempre la opinión del experto sobre si la complejidad del método o su número de lineas prevalece sobre lo que dice la herramienta. Lo que ocurre es que por lo general si quieres cumplir con el principio KISS la mejor forma de hacerlo es mediante métodos simples (complejidad baja) y clases cohesivas (clases pequeñas de nuevo). Contaba Robert Martin en Clean Code una "anecdota", trabajando unos días con Kent Beck (el que se invento esto del XP y el termino KISS) que lo que más le llamo la atención de su forma de trabajar era lo pequeños que eran los métodos que escribía y lo claro que quedaba el código luego. Pero por supuesto la longitud y CC de los métodos es sólo una pequeña parte de la historia, para escribir código claro hay que poner buenos nombres (quizas lo más importante) y no mezlcar niveles de abstracción, lo que ocurre es que los analizadores estáticos no pueden determinar estas cosas, sólo darnos avisos cuando la complejidad de algo se dispara, un AE no nos dice que nuestro código es limpio pero si al menos nos avisa que algo se esta haciendo muy complejo y hay que darle un vistazo.

    El copy&paste: Hay que si que no "hay piedad", código duplicado es SIEMPRE un error de diseño. Lo cual no quiere decir que para solucionar ese error alguien no pueda cometer otro aún mayor y hacer el código ilegible, es lo bonito de esto de programar que no es fácil. El propio kent beck define el código simple como aquel que cumple 4 reglas (en orden de importancia):

     

    • Pasa todos los test
    • revela sus intenciones
    • no contiene duplicaciones
    • menor tamaño posible

     

    Que te puedas encontrar con un diseño que por eliminar la duplicación sobrecomplique las cosas no quiere decir que este mal eliminar la duplicación, simplemente que no se ha eliminado la duplicación de la forma adecuada. Incluso un diseño con duplicaciones puede ser mejor que otro sin ellas si revela mejor sus intenciones, pero siempre existe un diseño mejor aún que este que además de revelar sus intenciones igual de bien elimina la duplicación, la cosa es saber encontrarlo, y normalmente la herencia no suele ser el mejor camino... pero eso es otra discusión jeje.

    Hacer código para test: El código se debe poder testear, sino no podemos saber si lo hemos echo bien, por eso KB coloca "el código pasa los test" como la característica más importante del código simple. Esto es así porque si no se puede testear no se puede cambiar con seguridad, y por tanto no es simple de mantener, aunque sea simple de entender. Dicho esto, hacer el código fácil de testear consiste básicamente en hacer clases cohesivas, poco acopladas y en depender de interfaces en lugar de en clases concretas, todos estos principios no son más que principios OO de buen diseño, un test no exige nada más que lo exigirá cualquier otro usuario de nuestra clase. El test al final no es nada más que un usuario de nuestro código, y como tal la "única" exigencia de diseño de los test es que el código sea fácil de usar. En mi experiencia te puedo decir que siempre se cumple que el código fácil de testear es mejor código que el que no es testeable. 

    De nuevo esto no quiere decir que alguien por hacer el código testeable no lo convierta en menos legible, pero esto es porque se esta diseñando mal, a mi me ha pasado en el pasado, por ejemplo cambiando la visibilidad de algún método para poder testearlo. En realidad lo que esta pasando en estos casos es que los test te dicen que tu código es complejo, y en lugar de rediseñalo adecuadamente (por ejemplo separando esa funcionalidad en nuevas clases) tomas un atajo para poder testearlo y estropeas el diseño. 

    En resumen, que se puede cometer errores de diseño por querer eliminar duplicidad o hacer el código testable, pero que ninguna de estas dos cosas son incompatibles, más bien todo lo contrario, con un buen diseño, y el verdadero buen diseño es el que incluye estas caracteristicas (no duplicidad y testabilidad) y además revela sus intenciones y es simple. Por supuesto es difícil llegar a estos diseños, pero quien dijo que nuestro trabajo fuese fácil jeje? 

  • JorgeRubira 31/01/2010 13:38

    Sorry: "utilizando la herencia se pierde un poco la compresión y el seguimiento del flujo del código". quería decir: "utilizando la herencia se pierde un poco la comprensión y el seguimiento del flujo del código". :).

  • peyrona 31/01/2010 18:41

    @jcesarperez

    Lo tengo, lo hice para un cliente, pero lamento decirte que no puedo hacerlo público.  :-(

    Sí te puedo decir que es muy simple: vete a la documentación de tu Issu-Tracker  (en mi caso fue Jira) y tendrás ejemplos de cómo crear una nueva entrada. Luego cada vez que saques un report (hazo en XML para facilitar las cosas), le pasas la utilidad que has creado y ella se encarga de recorrer el XML e ir dando entradas en el Issu-Tracker. De verdad que no vas a tardar más de 5 o 6 hrs en tenerlo implementado e integrado.

  • peyrona 31/01/2010 18:45

    @anónimo

    Nadie se va a tomar nunca a mal una opinión razonada.

    Estoy de acuerdo contigo en el nº max de líneas de un método y en el copy&paste, en lo que concierne a los test y el diseño, simplemente creo que mis compañeros y yo no nos explicamos bien, porque no creo que ninguno esté de acuerdo en crear una arquitectura o hacer el diseño de una app. pensando en los test. 

    Has creado debate y me encantaría participar más, pero de verdad que estoy muy, muy liado estos días (como podéis imaginar con todos los cambios que se están produciendo en Sun/Oracle).

    Gracias por las alabanzas. 

    Saludos para todos.

  • peyrona 31/01/2010 18:46

    @abraham

    Me han pedido y además lo ofrecí en el podcast, enviar mi conjunto de reglas de PMD.

    ¿Cómo lo hago? 

    Gracias y un saludo, presi. 

  • JorgeRubira 31/01/2010 19:46

    @Peyrona, podemos modificar la noticia e incluir más links. Si nos lo haces llegar bién a través del correo o contestando en este hilo, lo modificaremos.

    Saludos, Jorge

  • jcesarperez 31/01/2010 20:13

    @peyrona: La idea es tan sencilla como genial y es cierto que todos los issue-manager decentes tienen su api para integración. Gracias. Voy a intentar sacar tiempo y hacer algo.

     

  • raulexposito 31/01/2010 22:02

    @anonimo

    Algo de razón llevas, me ha gustado tu comentario. Estoy de acuerdo contigo en una cosa: se me han dado casos donde he preferido hacer un copypaste cortito que montar algo complejo, pero también he detectado con CPD copypastes de miles de tokens en códigos de terceros. Hacer un copypaste en un sitio concreto por algo determinado que no haga daño no me parece mal, pero que copiar y pegar sea la norma no me parece sensato, al igual que tampoco me parece sensato montar jerarquias y jerarquias de clases por no copiar y pegar 4 líneas. Estoy de acuerdo contigo en que no hay que llevar al extremo el que no haya ningún copypaste.

    Sobre lo que comentas de que partir un método en otros métodos no es eliminar la complejidad sino repartirla, me parece verdad a medias, y me explico. En vistas a mantenibilidad y testing no me resulta igual tener 1 método de complejidad 14 que 7 métodos de complejidad 2. Puede que tenga el código dividido en 7 métodos, pero me resulta bastante más sencillo comprobar que los métodos funcionan y olvidarme de ellos, pudiendo centrarme mejor en qué es lo que tengo que resolver. Hacer tests y mantener métodos de complejidad 14 a mí me parece complicado.

    De todos modos aquí nadie tiene la verdad absoluta, unos se sentirán más cómodos trabajando de unas maneras y otros de otras. Lo que está claro es que tenemos que tratar de eliminar la deuda técnica mejorando la base de nuestro código.

  • peyrona 01/02/2010 10:37

    @jcesarperez

    Me alegro que te haya gustado la idea: lo cierto es que cuando me tengo que poner a hacer algo, siempre intento reutilizar lo más posible cosas existentes.

    Si vas a hacer algo, ¿por qué no lo haces como proyecto OpenSource en java.net y así puede colaborar más gente?

    Un saludo. 

  • jmarranz 01/02/2010 10:59

    Al Anonimo de las 22:45

    Me has dejado con los pelos de punta. Llevados tus planteamientos a la práctica significa que el mejor modelo de programación es meter todo el código en JSPs y punto pelota.

    Consiguió que no hubiera nada de código duplicado, pero tras dejar la empresa, no había hijo de vecino que metiera mano a su código, y tuvimos que tirarlo todo a la basura y programarlo de nuevo, con código duplicado si, pero fácil de entender y mantener.

    ¿Hicisteis el esfuerzo de entenderlo?

    La capacidad de gestionar adecuadamente la complejidad es en mi opinión el principal valor de un programador, no el número de frameworks ylenguajes que conoce. Y si un problema es complejo, el resultado es complejo, pero complejo no implica (no debe implicar) incomprensible, y si un problema es complejo y es resuelto en 1000 líneas, con toda probabilidad esa solución será más mantenible que el mismo problema en 5000 líneas. El problema está en la pretensión de querer ver "el todo" mirando una parte.

    Una diferencia en mi opinión entre un buen programadory un mal programador es que el buen programador ve el programa como un organismo con elementos que se interrelacionan cada uno con una función pero dependientes en cierta medida unos de otros. El mal programador sólo ve los elementos sueltos a los cuales les obliga a hacer todo tipo de funciones.

    peyrona: porque no creo que ninguno esté de acuerdo en crear una arquitectura o hacer el diseño de una app. pensando en los test. 

     Umm no des por supuestas estas cosas, teniendo en cuenta que hay mucho TDD por ahí fuera :)

     

     

  • jcesarperez 01/02/2010 11:45

    @peyrona: lo estaba pensando sí, pero no en java.net. Estoy intentando definir el alcance, no sé si orientarlo a un plugin de Maven o quizás de Hudson y también tengo que estudiar un sistema de plugins para conectar con diferentes issue-managers.

    Respecto al debate en plan conozco 1 caso de mala utilización de X, luego no hay que utilizar X. Sólo voy a entrar a la parte de testing por las alusiones al podcast donde participé.

    Los principios para diseñar software facilmente testeable, que intentamos transmitir entonces, son los de cuidar el acoplamiento y la cohesión. Principios básicos de la POO que en ningún momento equivalen a incrementar la complejidad, sino al contrario. Un software bien diseñado, es un software que se puede probar de forma efectiva. No al revés.

    Igual que ocurre en el resto de industrias donde están haciendo grandes avances para probar sus productos de forma efectiva. Hasta cuando se va a montar una batidora, cada una de sus partes ha sido probada por separado y pasado una serie de tests de calidad. Cuando arranca cualquier ordenador, lo primero que hace es probar el funcionamiento de sus partes. El interfaz del ordenador del coche permite conocer el estado de sus componentes. Los tuneles de viento de coches y aviones. Etc, etc,...

  • JorgeRubira 01/02/2010 14:35

    Buenas, Hemos subido las Reglas de PMD que comenta Peyrona. El link es: http://www.javahispano.org/podcasts/Reglas_base_PMD_1.0.xml

  • peyrona 01/02/2010 14:53

    Gracias, Jorge.

  • Anónimo 01/02/2010 17:02

    WOW, Peyrona pone:

     < rule ref="rulesets/codesize.xml/ExcessiveMethodLength" message="Evite métodos demasiado largos. La violación de esta regla, normalmente indica que el método está haciendo cosas de más." >
     < priority > 5 < /priority >
     < properties >
     < property name="minimum" description="El valor umbral mínimo para activar la regla." value="300"/ >
     < /properties >
     < /rule > 

    Esperaba encontrarme con un 20-30

    300???? ya con 100 iría 'corriendo' a ver que corno está haciendo ese método!!!!

    Salute, Diego

  • Anónimo 01/02/2010 17:05

    Sé que llego un poco atrasado al debate, pero he aquí mi experiencia por si aporta algo.

    1) Los métodos largos nunca me ha parecido buenos (no los considero ni óptimos, ni elegantes, ni estéticos, ni mantenibles, etc), en general, cuesta seguirlos y encontrar un error es un lío. Además, que después el mantenimiento lo hace otra persona, que agrega otras tantas líneas, y es más díficil mantener el código coherente.

    2) El copy/paste sólo lo justifico por términos cortoplacistas (no hay plata, no hay tiempo, etc), que imponen "desde arriba", pero al menos cuando me toca pongo un comentario indicando el porqué y el origen del copy/paste para que si alguna vez puedo volver sobre dicho código "tratar de hacer algo para remediarlo".

    3) Escribir código pensando en el testing no se me había ocurrido hasta que llegue a la siguiente url (http://misko.hevery.com/code-reviewers-guide/) y la verdad es que funciona. El código resultante es mucho más simple (volvemos a KISS), y sobre todo reutilizable. De hecho, la configuración para test es muy parecida a la de para producción, no hay que cambiar casi nada, pero para ello es necesario pensar un poco y ojala evitar las sábanas de código.

    Finalmente, como comentario, siempre he tratado de escribir código reutilizable (aún antes de saber que existía el testing automático) en PL/SQL (con y sin POO), JAVA, etc. y para ello no hay nada como las clases abstractas donde programas las generalidades, y si hay algo que cambia lo sobrecargas en las clases concretas. Mi experiencia indica que agregar una clase y reescribir las particularidades es mucho más provechoso que hacer copy/paste o escribir clases con 100 métodos y 5000 líneas cada uno.

      Kr!

    P.D: Finalmente (sin querer ser autoreferente ni vanidoso), donde trabajo hay areas de desarrollo y soporte por separado y, la gente de soporte que le ha tocado mantener mi código, ha dicho que es super claro, casi no tiene bugs y es fácil de entender y extender. Esto a pesar de tener métodos abstractos y/o con pocas líneas, para tratar de evitar el copy/paste. Luego, creo que me puedo ir tranquilamente de la empresa (al menos sin cargos de conciencia), porque no van a tener que botar los miles de doláres que costo el software que programé porque no lo entiendan.

  • peyrona 01/02/2010 17:32

    @Diego.

    Sólo puedo decir que quizás lleves razón. También es cierto que depende mucho del tipo de proyecto que se esté haciendo.

    Ten tb en cuenta que se cuentan todas las líneas (incluidos comentarios): un método que tiene sólo 20 o 30 líneas me preocuparía porque casi seguro que no se ha comentado apropiadamente y eso sí que es malo.

    A mi me parece que las alarmas deben saltar cuando algo es alarmante, no cuando todavía está en el umbral de lo sensato.

    Pero insisto, son pareceres muy personales.   :-)

  • jcesarperez 01/02/2010 17:33

    Yo para las longitudes (no sólo de método, tb de clase e incluso de linea) uso 2 reglas.

    Una primera de gravedad media, con las longitudes que suelen entrar en la pantalla. 40 para método, 100 para línea y 500 para clase.

    Y luego otra de gravedad alta, con más o menos el doble de los valores anteriores.

    Aclarar que en mis proyectos, reglas de gravedad alta no dejamos ninguna, pero algunas -pocas- reglas de gravedad media sí suelen dejarse sin corregir.

    Los valores fueron consesuados con el equipo de desarrollo. De hecho tenemos pendiente una revisión de las reglas después de 2 años trabajando con el mismo juego.

  • peyrona 01/02/2010 18:19

    @Anónimo   01/02/2010 17:05 

    Gracias por el link, me ha encantado, sobre todo por lo breve:

    http://misko.hevery.com/code-reviewers-guide/ 

  • peyrona 01/02/2010 18:25

    @Diego

    Por cierto, ya poniéndonos finos con lo de la longitud de los métodos/clases, aquí van mis números (y animo a todos a que den los suyos) incluyendo comentarios y documentación (quitando líneas en blanco):

    Umbral de alarma para métodos:  80

    Umbral de alarma para clases: 400

    Insisto: estas magnitudes hablan de warnings, no errors.

    Y como dije antes, a mi me parece que las alarmas deben saltar cuando algo es alarmante, no cuando todavía está en el umbral de lo sensato.

     

     

  • Anónimo 01/02/2010 18:34

    Soy en anónimo de las 22:45

    Que de réplicas!!! Creo que lo mejor es que conteste uno por uno.



    @JorgeRubira 
    En cuanto al primer punto. No sé si es mania mía o no pero muchas veces entiendo más leer un texto similar a este:
    CalculaTotalVentasParaClientesActivos(parametros...)
    Que leer las 50 líneas que podría tener este método....
    Tienes toda la razón. Lo que he querido expresar en el anterior Post no es que haya que hacer los métodos largos, sino que hay que hacer los métodos sencillos. En ocasiones, dividir el método en submetodos más pequeños será la mejor opción. Creo que el objetivo debe ser hacer métodos sencillos, no hacer métodos de menos de 50 lineas, esto es, que los métodos sean cortos es el medio de conseguir que el código sea sencillo, no el objetivo. En cuanto al lo del copy&paste, también de acuerdo contigo. En este aspecto me refiero al extremos de que no haya nada de código duplicado. Por ejemplo, en las plantillas de una página web seguramente habrá codigo repetido. Lo que puede cambiar habrá que dejarlo en un lugar comun, pero sacar todas las lineas repetidas fuera haría que mantener las plantillas sea un infierno.

    @remoh
    Totalmente de acuerdo con lo que dices respecto al número de lineas. Como comento arriba, en lo que no estoy de acuerdo es en usar el número de lineas de un método como norma u objetivo, sino como herramienta. Respecto a lo que comentas del copy&paste, como he comentado antes, me refiero al extremo de no tener nada de código duplicado.
    Con respecto al tema de hacer código para test, lo que yo me refiero a casos como el del siguiente ejemplo ficticio. Supongamos que estoy desarrollando una funcionalidad requerida por el negocio. Supongamos que la manera más natural y sencilla para resolver un caso de uso dado es dejando un mensaje en una cola y usar MDBs, pero que casualmente, no conozco ningun mecanismo para testear el código si lo hago asi. Entonces, me desarrollo un sistema a medida basado en ficheros o base de datos para simular la funcionalidad de las colas, evidentemente mucho más complejo, pero que si se testear. Este caso en concreto no, pero si que he visto casos similares. Mi opinion es que hay que mantener el código simple, y si no puedes testearlo (quizas por desconocimiento), no lo testees, pero no compliques el código innecesariamente.
    Por supuesto es difícil llegar a estos diseños, pero quien dijo que nuestro trabajo fuese fácil jeje?
    El problema que veo es que en un pais como este, donde cuando alguien tiene la sufiente experiencia, para subir de sueldo, tiene que dejar de programar, quizas haya que conformarse con tener diseños peores pero más faciles de implementar.

    @raulexposito
    Totalmente de acuerdo contigo

    @jmarranz
    No me refiero a hacer toda la aplicación con JSP, entre otras cosas porque eso generalmente hará que la aplicación no sea ni simple ni mantenible. Cuando diseñamos una aplicación tenemos siempre unos requisitos no funcionalies que cumplir (mantenibilidad, escalabilidad, etc...) que hacen que las aplicaciones tengan cierta complejidad. Lo que yo me refiero es a la complejidad extra que añadimos sin necesidad, como en el ejemplo del test y jms que he comentado más arriba. Este exceso de complejidad puede darse por muchos motivos, como el desconocimiento, el deseo de lucirse técnicamente o ir al limite de nuestros conocimientos (creo que esto tiene nombre) o confundir los objetivos de la arquitectura (ej: los métodos tenen que tener como máximo 20 lineas, por lo que corto los métodos por donde surja y asi cumplo)
    Sobre el ejemplo de los actions que puse en el primer post, era solo un ejemplo un poco exagerado. El modulo lo tuvimos que mantener durante unos meses, y la persona que le toco, buenisimo programador por cierto, alucinaba con el código, pues el que lo hizo había conseguido hacer dificil y raras las cosas más triviales. Cuando llegó un cambio de cierta relevancia, se aprovecho la excusa para reprogramar y conseguir algo más sencillo y uniforme con el resto de la aplicación.
    En la replica que le haces a peyrona si que estoy en desacuerdo (aunque creo que más bien es problema del lenguaje), y opino como más bien como él: si que hay que hacer test, pero sin obsesionarse y sin perjudicar la arquitectura de la solución.
    Por lo demás totalmente de acuerdo contigo. Tambíen creo que la capacidad de gestionar la complejidad es el mayor valor de un programador. Por eso digo que el objetivo debe ser que las aplicaciones ha de ser la sencillez, o dicho de otro modo, evitar complejidades innecesarias. Parece mentira como dos personas pueden resolver el mismo problema, uno de manera corta y sencilla y otro de manera larga y compleja. En concreto, lo que yo opino es que prefiero un método de 1000 lineas al método de 5000 lineas dividido en 50 submetodos de 100 lineas cada uno


    @jcesarperez
    Totalmente de acuerdo contigo

     


    Muchas gracias por vuestros comentarios

  • JorgeRubira 01/02/2010 19:12

    Anonimo. Sobre el Copy/Paste no hay que irse a los extremos. El problema de la reutilización es no preveer casos particulares. Este podría ser un extremo donde el copy/paste fastidia:

    Yo tengo:

    Metodo 1: Ejecuta A B C D

    Metodo 2: Ejecuta A B C E

    Metodo 3: Ejecuta A B C F

    Lo cual esto lo reutilizo por 

    Metodo Z: Ejecuta A B C

    Metodo 1: Ejecuta Z D

    Metodo 2: Ejecuta Z E

    Metodo 3: Ejecuta Z F

    Esto estaría bién, pero si tuviesemos

    Metodo 1: Ejecuta A B D C

    Metodo 2: Ejecuta A B E C

    Metodo 3: Ejecuta A B F C

    Si lo convertimos a:

    Metodo Z: Ejecuta A B IF(caso1) D else IF(caso2) E else IF(caso3) F end C

    Metodo 1: Ejecuta Z(caso1)

    Metodo 2: Ejecuta Z(caso2)

    Metodo 3: Ejecuta Z(caso3)

    Esto no estaría mal del todo, pero si lo llenasemos de más casos particulares en vez de reutilizar lo que hacemos es centralizar la lógica en un método muy complejo lleno de casos particulares diversos dificil de mantener y de comprender.

    Anonimo, Imagino que te refieres a este tipo de casos. En ese caso, hay que ver el caso en concreto para evaluar si es legible o no.

    Saludos, Jorge

     

     

     

     

  • remoh 01/02/2010 20:31

    Un apunte jorge:

    Metodo Z: Ejecuta A B IF(caso1) D else IF(caso2) E else IF(caso3) F end C

    Metodo 1: Ejecuta Z(caso1)

    Metodo 2: Ejecuta Z(caso2)

    Metodo 3: Ejecuta Z(caso3)

    En este caso una forma más conveniente de reutilizar es haciendo uso de polimorfismo. En lugar de pasar un String o un enumerado con el "caso" a ejecutar y luego hacer un if para ver a que función llamar en cada caso ¿porque no le pasas directamente la función a ejecutar en ese momento?. Como en java no hay punteros a funciones ni closures (todavía) lo puedes solucionar simplemente creado una interfaz y luego usando clases anónimas. (otra opción es usar clases abstractas redefiniendo el método en los hijos, pero es más feo en mi opinión que ya sabéis que no soy fan de la herencia precisamente). 

    el metodo Z seria:

    public void metodoZ(IOperacion op) {

       ejecutoA()

       ejecutoB()

       op.ejecutar();

       ejecutoC()

    }

    luego el metodo 1 seria por ejemplo:

    public void metodo1() {

         metodoZ(new IOperacion() {

               public void ejecutar() {

                      ejecutoD(); 

               } 

          }); 

    Así evitas la duplicación y de una forma más elegante, más extensible (esto cumple el principio open-close), y en mi opinión perfectamente legible, mucho más que con un if, aunque mucho menos que con una closure en ruby, python, groovy, js o cualquier lenguaje dinámico de estos de modernos :P

    Anonimo:

    En este aspecto me refiero al extremos de que no haya nada de código duplicado. 

    Soy extremista :P, sin piedad, ni una linea, ese es el objetivo que hay que marcarse, cualquier otra cosa es un fallo de diseño, un punto de mejora, algo que no hemos podido/sabido hacer mejor. Pero por supuesto hay que eliminar esa duplicidad manteniendo los otros atributos que debe tener el diseño (simplicidad etc,etc), si no se nos ocurre una forma de eliminarla que no se cargue otras cosas entonces mejor dejarla y vivir con ella, pero nos apuntamos un -1 y investigamos más sobre diseño OO para ver como solucionar el problema para la próxima.

    Una cosa que últimamente he aprendido con respecto a eliminar la duplicidad, es que simplemente eliminando pequeñas duplicaciones (de dos o tres lineas) el código queda mucho claro y emergen buenos diseños, incluso hace poco lei un post de un experto en TDD y diseño OO (no tengo el link) que decia que al final el había reducido todos los patrones de diseño a dos reglas simples:

     

    • Elegir buenos nombres
    • Eliminar toda duplicidad.

     

    El tio afirmaba que simplemente siguiendo estos dos principios era capaz de hacer emerger mejores diseños que de ningún otro modo. Este es más extremista que yo todavía, y no tengo muy claro que eso sea cierto o aplicable en muchos casos, pero con lo que si que estoy de acuerdo es que el acto de ir eliminando toda pequeña duplicidad produce un efecto fantástico en el código, no hace falta pensar en grandes diseños para reutilizar desde un principio, simplemente eliminar cada pequeña duplicidad que se presente de la forma más sencilla posible, y es sorprendente como siguiendo esta regla mejora el diseño y la legibilidad del código, te animo a probarlo. 

  • jmarranz 01/02/2010 20:48

    Anonimo: Parece mentira como dos personas pueden resolver el mismo problema, uno de manera corta y sencilla y otro de manera larga y compleja.

     Hombre yo tambien estoy de acuerdo en eso, pero lo habitual es "largo y código sencillo" (es decir código plano y copy/paste a saco) frente a "corto y código más complejo" la segunda opción a medio largo plazo siempre es la mejor porque es la de mejor calidad (suponiendo que esté hecho con sentido común).

     

  • peyrona 01/02/2010 21:40

    Señores, está empezando a encantarme este post... 

    Además hemos conseguido interesar al ínclito jmarranz...   ;-)

    Vamos con ello:

    Me gusta leer, me encanta la literatura y aunque desde hace años no dispongo de mucho tiempo, mi afición sigue  intacta, así que abogo (como muchos (que no todos) buenos escritores) por textos sencillos, si son largos mejor, no me gusta un libro de 600 capítulos de 8 párrafos cada uno, prefiero una novela de 6 u 8 capítulos con 80 páginas por capítulo.

    Defiendo por tanto los métodos autocontenidos, que incluyen una porción completa y explicativa de su funcionalidad y sobre todo que se lean bien: todo algoritmo debe poder leerse de arriba a abajo sin saltos (lo dice el teorema Böhm-Jacopini (http://en.wikipedia.org/wiki/Structured_program_theorem), con el que estoy totalmente de acuerdo).

    Yo personalmente me pierdo con demasiados métodos muy cortos, es más, ahora me siento con el deseo de abogar por incluir una regla más en el PDM: sospechar de aquellas aplicaciones que sólo contienen métodos cortos, son demasiado complejas.

    Quisiera terminar con una cita de anónimo anterior (coñe, compañero, regístrate, que es gratis  :-)), me parece que es una de las máximas verdades (y no creo que haya muchas) que se pueden decir en nuestra profesión:

     

     creo que la capacidad de gestionar la complejidad es el mayor valor de un programador 

     

    Después de un duro día de trabajo en Sun/Oracle, estas charlas son las que animan a uno a prepararse para la cena...   :-)

    Saludos y gracias a todos. 

     

  • JorgeRubira 01/02/2010 22:13

    Remoh, ¡has picado! Estaba esperando que alguien me contestase esto...

    Pues bién, imaginate que tienes este caso menos evidente:

    Metodo 1: Ejecuta A B C D

    Metodo 2: Ejecuta A E B C

    Metodo 3: Ejecuta A B F C

    Aquí tendrías que estar enviando varios parámetros metodoZ(postA, postB, postC) ... ¿Como resolverías esto? :)

    Saludos, Jorge

     

     

  • Anónimo 01/02/2010 22:17

    Pues yo prefiero los casos como "Yo, Robot" de Asimov, en que un conjunto de relatos (relativamente cortos), se ensamblan para formar una "novela" coherente, con opción de ampliarse para incluir preludios y continuaciones , e incluso interactuar con otras sagas (como las Fundaciones), que también se construyen con la misma filosofía (e incluso obras de otros autores que "reusan" las partes más interesantes: como las leyes de la robótica o la Psicohistoria).

     

    Kr!

  • jcesarperez 01/02/2010 22:48

    @peyrona: la clave está en el nivel de abstracción. Tu puedes tener muchos métodos pequeños, si cada método guarda su nivel de abstracción será facil de leer, pero si lo mezclan será un caos. No hay nada más horrendo que mezclar lógica de negocio con preparedstatements, resulsets y control de excepciones.

    Comentas lo de los algoritmos, precisamente a la hora de presentar un algoritmo suele haber una primera versión en pseudocódigo con un tamaño más reducido que la versión implementada con un lenguaje concreto.

    Esa es la estrategia correcta a la hora de reducir el tamaño de un método. Mantener en el método original el mayor nivel de abstracción y usar métodos pequeños con un nivel de abstracción más fino. De modo que el nuevo método original se entiende facilmente y si necesitas examinar más detalles sobre alguno de los submétodos puedes usar el Ctrl+Click y luego la flecha atrás :-)

    También por ejemplo, en cualquier algoritmo de ordenación verás que llaman a un típico método intercambiar. Fijate en estas implementaciones del Quicksort, yo encuentro más dificil de leer las que no usan el método auxiliar intercambiar.

  • peyrona 01/02/2010 22:58

    @jcesarperez

    De nuevo estoy de acuerdo contigo, compañero.

    Mi post anterior iba más por el camino de la controversia que por otros derroteros, de todos modos de verdad que refleja en gran medida mi opinión, que al fin y al cabo no es más que eso, una opinión... 

  • JorgeRubira 03/02/2010 00:31

    Remoh, me contesto a mi mismo ... la solución es muy compleja. De hecho, aun me la planteo.

    El problema de la herencia es que te dá solución en lo que hay que hacer, pero no en cuando hay que hacerlo. Habría que inventar algún framework que te permitiese crear comandos y poder establecer prioridades o dependencias en el orden de ejecución de las cosas. No sé aún la respuesta ... 

  • jpedro 08/02/2010 04:01

    Espectacular Podcast de principio a fin muy bueno!

  • Anónimo 29/03/2010 21:18

    Gracias por el podcast, super interesante, estas herramientas no las conocía y sin duda me acompañaran como apoyo en adelante, saludos para todos desde Chile!

Escribe tu comentario

Sun Microsystem Logo NHT-Norwick Logo

© 2002-2007 Asociación javaHispano