sábado, noviembre 03, 2007

Una razón algo más técnica para no escribir métodos largos

sábado, noviembre 03, 2007 por Martín

Hoy en día creo que más o menos todo el mundo tiene claro que escribir métodos muy largos es una mala práctica. Nos lo dicen en la universidad, nos lo dicen en los libros de programación, de ingeniería del software, de patrones o de refactorización. Los paquetes de métricas y de detección estática de errores nos avisan de que nuestros métodos son demasiado largos y el jefe nos echará una buena bronca si ve que hacemos un método de 5.000 líneas.

Aún así, cuando uno está programando siempre hay esos momentos en que se siente un poco vago con algún método al que va añadiendo cosas y cosas, porque total, estamos haciendo sólo un boceto, ¿no? El problema es que esos bocetos se convierten en la versión definitiva (doy fe, que tengo un par de métodos grandes por ahí que verguenza me dan) y ahí ha quedado. Pero bueno, funciona, ¿no?. Y no lo va a tocar nadie nunca jamás de los jamases, ¿no?, ¿qué hay de malo entonces?. Pues sí, incluso creyéndonos que nadie verá ese código nunca, hay algo que puede ser malo:

Hoy en día los lenguajes populares se ejecutan en máquinas virtuales. Estas máquinas virtuales disponen de optimizadores que traducen el bytecode de nuestros programas en código máquina, pero que además realizan numerosas optimizaciones sobre el mismo para obtener mucho más rendimiento. Estas optimizaciones no sólo se limitan a reordenaciones, inlining y todas estas cosas sino que en algunos lenguajes como Java (no sé si en otros, supongo que sí) se almacenan mapas de objetos en los que se especifican donde se encuentran los objetos a los que apuntan las referencias: la referencia A está en un registro, la referencia B está en la pila, etc.

Dicha información se utiliza durante la recolección de basura para acelerar la ejecución. Si no se dipone de esos mapas de objetos en el momento de la recolección, el recolector los tendrá que crear por si mismo. Para crear estos mapas, el recolector trata de simular la ejecución del método en relación a la posición de la referencia que se pretende recolectar. A métodos más grandes, simulaciones más complejas. Por cierto, que además la simulación depende de en que línea salte la GC así que aunque los mapas se guardan, ésto no sirve de mucho si el método es grande.

¿Y qué tiene que ver esto con el tamaño de los métodos? Pues resulta que Java tiene un límite para el tamaño de los métodos a los que el JIT aplicará optimizaciones. Si los métodos sobrepasan ese límite no pasarán por el JIT, y por lo tanto estos mapas de objetos no se generarán, y por lo tanto la recolección de basura será mucho más larga de lo que debería ser. Más concretamente el límite son 8000 bytes de bytecode. Para deshabilitar este límite en la máquina virtual de Sun, se puede usar la opción "-XX:-DontCompileHugeMethods". Pero ojo, esto no es una buena idea ya que lo más probable es que el JIT también sufra a la hora de optimizar, a fin de cuentas si el límite lo han puesto así será por algo. Así que mejor refactorizar y hacer más métodos y más pequeños.

Bueno, ahora igual he engañado a alguno que estará pensando. ¡Qué listo es Martín, cuanto sabe! Pues no. Todo esto no me lo he encontrado, ni lo he vivido, ni nada de nada. No es más que un resumen, bueno más bien una traducción porque me ha quedado bastante largo, de lo que cuenta el genial Jon Masamitsu en su blog, en el que ha publicado una entrada en la que explica algunas experiencias que le han pasado con clientes, relacionadas con parámetros raros de la máquina virtual. Entre estas experiencias está la de un cliente que veía que los tiempos de GC eran enormes y que no sabía por que, pero que de pronto descubren que comentando el código los tiempos de GC son mucho menores.

Pues ya sabéis, ahroa si alguna vez habláis con alguien sobre esto de los métodos largos, y os dice que eso de la refactorización no son más que chorradas, os podéis sacar de la manga esta explicación que es de las de dejar con la boca abierta.

comments

0 Respuestas a "Una razón algo más técnica para no escribir métodos largos"