Oct 29

Más sobre la cabra

Bueno, ando un poco cabreadillo con la cabra -google-. Me entero en el blog de Max Glaser que google, después de seis meses, ha actualizado los page rank. También veo ahí que parece que esta vez han sido un poco rácanos y han bajado el page rank de muchas páginas. Y lo peor de todo, veo en mis propias páginas que varias han pasado de page rank 4 a page rank 3.

Al menos tendré la oportunidad de ver si el page rank sirve o no para algo. Tendré que mirar en las siguientes semanas si se aprecia un cambio brusco de tráfico o todo sigue igual.

¿Os ha pasado algo parecido en vuestros respectivos?

Y ya puestos a meterme con google, no me gustan ahora los resultados de las búsquedas. Aunque si están más o menos claramente diferenciados, hace algún tiempo han metido propaganda o enlaces patrocinados o como quieras llamarlo entre los resultados de la búsqueda. Ya tienes que andar con más cuidado en lo que pinchas.

Oct 28

A favor de los test unitarios

Hace unos días me dediqué a implementar en java una funcionalidad para un proyecto. Me puse a ello haciendo los test unitarios en paralelo al código que iba desarrollando, incluso un poco antes, de forma que pasaba el test, veía que fallaba y me ponía a arreglar.

Para hacer el código, me basé en una librería que estaba desarrollando otro compañero. Dicha librería estaba muy avanzada, pero no acabada, por lo que tenía algunos bugs e incluso código faltantes. Durante mi desarrollo y mis test, encontré algunos de esos fallos y faltantes, así que avisé a mi compañero, pero corregí o completé yo el código, por supuesto, haciendo adicionalmente otros test unitarios.

Por fin terminé la funcionalidad. Con los test encontré algunos fallos en mi propio código que también corregí y lo metí todo en CVS.

Al cuarto de hora de meterlo me aparece otro compañero y me dice … "revisa esos test que acabas de meter, que fallan….". ¡Vaya!, me quedé extrañado. Acababa de pasarlos y funcionaban todos. Los vuelvo a pasar en mi directorio de trabajo … y funcionan. Reviso que no me he olvidado de meter nada en CVS y todo correcto. Hago update, salen unos fuentes, paso el test … y falla. Revisando, revisando, compruebo que otro compañero más -el tercero-, ha tenido un despiste en una clase común y mi test ha fallado. Hablo con este compañero, que tiene el cambio reciente y en dos minutos queda solucionado el problema.

En total, algo menos de una semana codificando y otra semana larga que "perdí" haciendo los test. Queda además un "chivato" por si mi primer compañero decide más adelante cambiar su librería de forma que afecte a mi código.

Todo un poco aburrido hasta aquí y nada que se salga de lo normal, pero …. ¿qué podría haber pasado si no hubiera hecho test y hubiera hecho simplemente una prueba manual de mi código?. Veamos el posible futuro que posiblemente ya no es posible -espero-.

Si no hubiera hecho tests automáticos de prueba, sino simplemente unas pruebas manuales de mi código, habría visto igualmente los fallos y faltantes de la librería de mi primer compañero. Habría igualmente corregido y completado su código, pero sin hacer test unitarios. También habría encontrado mis propios errores al codificar. Una vez terminado todo lo habría metido en CVS.

Un cuarto de hora después NO habría venido mi segundo compañero a decir que los test fallan. El despiste de mi tercer compañero habría pasado desapercibido. Puede que él mismo se hubiera dado cuenta más adelante o no. Seamos tremendistas, supongamos que ese error no "canta" hasta bastante más adelante.

Seamos más tremendistas aun. Mi primer compañero, el de la librería, sigue su desarrollo de la librería y decide modificar o reorganizar el código que yo le hice y aunque el código sigue funcionando, ya no hace exactamente lo que yo quería que hiciera.

Mi código, que ya fue probado y no se ha probado más, ya no funciona. Hay un fallo por ahí que lo impide y una librería que se comporta algo distinto. Pero no hay tests unitarios que se pasan automáticamente en todos los compilados que lo indiquen.

El código llega al entorno de integración y pruebas. El responsable me reporta un "bug" varias semanas o meses después, cuando ya no tengo fresco el código que he hecho. Cuando consigo "turno", meto el debugger, miro y acabo encontrando el fallo que metió mi tercer compañero. Se lo comento. No se acuerda de por qué hizo ese cambio ni para qué servía. Tiene que revisar su código. Al día siguiente me viene con que no puede deshacer ese fallo, ya hay mucho código hecho basado en eso y si lo arregla, igual deja de funcionar. Meto en mi código una "ñapa" para que pase con el fallo de él. Compilo y decido recuperar la prueba manual que hice en su día.

Me ha costado encontrar el código de prueba manual que hice, porque no sé dónde demonios lo tenía. Lo paso otra vez a mano y veo que aquello no "furrula". Debugger al canto y veo, con mucho esfuerzo porque no tengo el código reciente, que la librería del primer compañero no hace lo que yo espero. Se lo comento y el, que tampoco tiene el código reciente, me dice que va a mirarlo. Al día siguiente me viene con que no va a cambiar ese código, porque está mejor así y además tiene mucho código hecho que se basa en eso. Le digo que me está haciendo la puñeta, me acabo peleando con él, no nos hablamos más y meto otra segunda ñapa en mi código para que funcione, que básicamente consiste en hacer una copia de su antigua librería en otro sitio.

Si hubiera hecho los test y mi compañero más adelante hubiera tocado la librería, el test hubiera "cantado" en el momento en el que él la toca. Hubiera sido más fácil llegar a un acuerdo cuando él está todavía haciendo el código y no tiene demasiado hecho basándose en ese cambio. Hubiera sido más receptivo a un "por favor, no me toques eso, que si no me deja de funcionar a mi".

La consecuencia de no hacer tests podría haber sido más agobio en la fase de pruebas, más tensión con los compañeros y soluciones más chapuzas en el código. Y posiblemente más tiempo perdido, ya que mi semana de hacer test es bastante menor que el tiempo que habría dedicado a : hacer unas pruebas manuales + debugger en el entorno de pruebas de un código que no tengo reciente + discusión con un compañero + recuperar el programa de pruebas manuales y volver a probar + debugger para el segundo fallo + discusión con otro compañero + tiempo de ñapear otra vez el código + tiempo que pierden otros compañeros mientras yo tengo ocupado el entorno de pruebas con el debugger.

Se que es difícil y que a veces es un poco pesado, pero viendo los fallos que ya han saltado por los test y lo que posiblemente hubiera pasado más adelante -excepto la pelea con el compañero, que en realidad estamos bien avenidos y no creo que la sangre hubiera llegado al rio-, creo que merece la pena. Siempre es mejor detectar un fallo y corregirlo con tu compañero en la tranquilidad de tu mesa de trabajo, cuando ambos teneis el código reciente y todavía no habeis hecho demasiado código basado en el fallo, que corregirlo en un entorno de pruebas, con la presión de un hito con el cliente cercano, con código del que ya no te acuerdas y sobre el que ya has construido muchas cosas y por tanto no puedes tocar con facilidad.

Y aunque siempre hay excepciones, también estoy convencido que un mismo código puede ser totalmente imposible de testear o se pueden hacer los test en una tarde dependiendo de cómo esté hecho el código.

Oct 27

¿ nepotismo ?

Desde que empecé a trabajar, veo como cuando entra un nuevo gran jefe casi lo primero que hace es cambiar a los jefes que tiene por debajo y estos a su vez a los suyos. Casualmente, los nuevos jefes que pone por debajo son sus amigos, con los que va a tomar café, compañeros de proyectos y despachos, etc.

Ves como al torpe del despacho de enfrente, que lleva el mismo tiempo que tú pero es un desastre, le suben de cargo, porque el nuevo jefe es con quien suele ir a comer. La conclusión a la que llegas es que para ascender, más que méritos propios, necesitas ser amigo de alguien.

Sin embargo, el otro día se me ocurrió, en plan ejercicio mental, ver cómo organizaría yo el departamento. Qué grupos haría, a quienes pondría de responsables de esos grupos y en definitiva, cual sería la mejor organización desde mi punto de vista. ¡Sorpresa!. Las personas a las que pondría de responsables son ni más ni menos que las personas con las que he estado trabajando desde que entré. Entre esos responsables de grupo, no había ni una de las personas a las que conozco menos.

¿Cómo es posible?. Pensé la organización intentando encontrar la forma de que funcionara lo mejor posible, no intentando ascender a mis amigos.

A poco que se piense, es lo normal. Esas personas son con las que llevo varios años trabajando. He aprendido de ellos y ellos de mí. Nuestra forma de trabajar y de hacer código se ha "unificado". Pensamos similar y damos soluciones similares a problemas similares. Dicho de otra forma, harían las cosas de forma muy parecida a como las haría yo. Desgraciadamente, el 99% de las personas pensamos que somos más inteligentes que la media -y al menos el 49% estamos equivocados-. Por ello pienso que mi forma de hacer las cosas es mejor que la de los demás y si ellos hacen las cosas como las haría yo, también las harían mejor que los demás.

También es cierto que el trato más cercano con ellos me hace comprender mejor sus puntos de vista. Si un "ajeno" hace un código chapuza, es porque es un inútil y no hay mucho más donde rascar. Si un "cercano" hace un código chapuza y durante el café me explica que no se lo han especificado bien, que le han dado poco tiempo o que tiene enferma a su madre y la cabeza no está para hacer código, el "cercano" no es un inútil, sino que tiene excusa para haberlo hecho mal. También, en el café, te contará todo eso que ha hecho bien, pero no se ve. Si un jefe de proyecto "ajeno" lleva mal su proyecto, es un inútil. Si un jefe de proyecto "cercano" lleva mal su proyecto, en la comida te cuenta que el cliente es difícil, que le cambia de idea todos los días, que los proveedores no le envían las cosas a tiempo, que tiene dos inútiles programando y que así no hay manera.

Siempre hay casos de gente que ascienden a otros por ser sus amigos o por ser sus parientes aun a sabiendas de que son unos torpes. Pero estoy empezando a ver que normalmente sueles valorar más a la gente más cercana, con la que te llevas bien y con la que trabajas más estrechamente. Por un lado, si sueles ir con ellos a los cafés o a las cañas, es porque sois personas "afínes". Por otro lado, conoces mejor sus excusas, problemas y motivaciones.

Tengo otros muchos compañeros que son perfectamente capaces y que podrían llevar bien un grupo de gente. Sin embargo, son gente que me resulta más lejana. La capacidad de esas personas la conozco por comentarios de otras personas y la intuyo por pequeños encuentros con ellos, en los que ves que sí, que esa persona tiene pinta de ser muy válida e inteligente. Sin embargo no piensas en ellos a la hora de ascenderlos simplemente porque no es gente con la que trabajas habitualmente, no lo conoces suficiente y su forma de hacer las cosas es distinta de la tuya. Ojo, no digo que las hagan mal, muchas veces las hacen mejor que tú, pero lo hacen de forma distinta. No hacen las cosas como las harías tú y por eso no piensas en ello como posibles jefes.

En fin, sigo pensando que determinados responsables de proyectos son unos idiotas y que están ahí porque son amigos del jefe y salen de cañas juntos, pero empiezo a pensar que posiblemente el jefe si cree que ese idiota es capaz de llevar un proyecto. Como he comentado, es porque tienen una "idiotez" similar.

Ahora te propongo que hagas el mismo ejercicio mental. Si estás trabajando, piensa cómo organziarías el departamento y a quienes pondrías de responsables de los grupos. Si eres estudiante, piensa que tu clase es un departamento de una empresa, que teneis que hacer varios proyectos software y que tú eres el jefe de todos ellos. ¿A qué compañeros pondrías de responsables de esos proyectos?

¿Ya está?. Bien, dime cuántos de esos responsables que has puesto son amigos tuyos de trato diario y cuantos son personas con las que apenas tienes trato. No vale hacer trampa .

Ya puestos, dime sinceramente si eres del 99% que cree que es más inteligente que la media y hacemos una estadística. Os animo a contestarlo en el foro.

Oct 26

Alucino con google

Después de la sorpresa de anteayer al buscar DecimalFormat en google, se me ha ocurrido buscarlo hoy otra vez. La sorpresa esta vez sí que ha sido mayúscula.

Esta vez en primera posición de la búsqueda de DecimalFormat sigue apareciendo la página aleatoria de la Chuwiki, pero esta vez, el resumen que aparece en la búsqueda es de "ćomo poner una imágen aleatoria con php".

Y eso no es todo. Si pincho en la caché del resultado de búsqueda, sale "certificados y firmas digitales".

Está claro que el googlebot ha pasado en varias ocasiones por la página aleatoria. En una decidió que DecimalFormat debía ir en primera posición en la búsqueda. En otra ocasión decidió que la imagen aleatoria de php va en el resumen y a la tercera se guardó como caché la de certificados y firmas. A pesar de todo eso, sigue decidiendo que esa página es la primera en DecimalFormat, aunque el resumen ni la caché hablen en absoluto de eso.

Aquí las capturas de la búsqueda de hoy …

Busqueda DecimalFormat

y de la caché

cache busqueda DecimalFormat

Yo creo que no puede estar más claro. Google está un poco cabra.

Oct 25

SWT y JFace

Por cortesía de Blaxter, en la Chuwiki tenemos una pequeña introducción a SWT y JFace. Creo que los comentarios de este post no tienen nada que ver con el asunto …

En serio, muchas gracias.

Oct 24

Las cosas de google

Hace un rato se me ocurrió buscar "DecimalFormat" en google, páginas en español, y curioso, apareció como primera mi página de la Chuwiki. Pero … fijándome en el link, resulta que es la página aleatoria de la Chuwiki, es decir una página cualquiera. Si alguien pincha el enlace, le aparecerá una página aleatoria en la Chuwiki y no precisamente DecimalFormat.

Lo que no deja de ser curioso es que el rastreador de google -el googlebot ese- haya pasado por la página, supongo que una sola vez porque la siguiente vez habrá encontrado otra cosa -el enlace es aleatorio- y haya decidido poner esta página en primera posición de las busquedas. No creo tampoco que haya muchas otras páginas que enlacen a la página aleatoria poniendo "DecimalFormat" en el enlace. En fin, no entiendo por qué google decide poner esta página en primer lugar de la búsqueda cuando no hay ningún motivo.

Supongo que el resultado es transitorio y la próxima vez que visite el sitio y no vea que ese enlace aleatorio es DecimalFormat, lo quitará y pondrá otra cosa.

No sé, google está claro que funciona bien y tiene mucho éxito, pero a veces hay cosas que no me acabo de explicar.

 

Google y DecimalFormat

Oct 22

Burocracia informática

Ultimamente estoy alucinado a los niveles a los que llega el papelo de un proyecto.

Se nos encarga un proyecto. Ese proyecto lleva varios hitos de pago. Un diseño preliminar que hay que entregar en una determinada fecha. Posteriormente, en otra fecha, un diseño detallado con un preliminar del manual de usuario. Más adelante el software entregado y funcionando.

La política -incorrecta- que seguimos es que los programadores, sin apenas especificaciones y sin diseño alguno se ponen "ya" a hacer el código. Mientras, el responsable del proyecto y para el hito va preparando el diseño preliminar para entregar. Llega el hito del diseño preliminar, el código ha llegado hasta donde haya llegado y se entrega un documento que poco tiene que ver con el código real.

Luego llega el momento de entregar el documento con el diseño detallado y el preliminar de manual de usuario. Eso ya es excesivo para el responsable del proyecto. El nivel de profundidad en el código que requiere el documento se va de las manos de un jefe -¡¡cómo va un jefe a meterse en el nivel de las clases!! Si no tiene ni p..a idea-. Así que llega el momento de pedir ayuda.

El jefe coge a los programadores -a todos, incluidos los nuevos- y les pide que le ayuden a hacer el diseño detallado. El diseño detallado que hagan, por supuesto, debe parecerse al código que están haciendo, pero por supuesto también, no puede discrepar con el diseño preliminar que se hizo anteriormente.

Y ahí tienes a todos los programadores, parados dos, tres o cuatro semanas, haciendo ingeniería inversa -a mano o con herramienta- y luego eliminando clases que son de demasiado bajo nivel, cambiando nombres de paquetes para que coincidan con el nombre que se les dio en el preliminar, juntando clases de paquetes separados en uno solo, y haciendo malabarismos varios con los diagramas UML.

Aparte de todos los fallos evidentes de esta forma de trabajo y del caos que salta a la vista, hay dos pequeños detalles que me llaman la atención.

Por un lado, el diseño preliminar se supone que es una fase intermedia del diseño. Cuando se pasa al diseño detallado y se va profundizando más en el problema, el diseño preliminar debería ser perfectamente modificable. Sin embargo, el papelo -las ganas de evitar hacer la versión 2.0 del diseño preliminar- hace que el diseño detallado se haga mal a posta, sin parecido al código real que se está desarrollando en paralelo.

Por otro lado…. si vas a parar a TODOS los programadores varias semanas para pintar unos monos que no valen para nada… ¿no es mejor pararlos al principio, antes de que se pongan a codificar a lo loco, para pensar al menos un esbozo de diseño real?.

Ya lo dice el refrán, "vísteme despacio que tengo prisa".

Oct 21

Bits en el ring

Una página interesante para los que gusten programar algoritmos de juegos. En bits en el ring proponen un juego y aceptan los algoritmos que les envíe la gente. Luego hacen competiciones entre ellos para ver qué algoritmo es el ganador.

El juego actual, FootSteeps, el realmente simple, pero parece un pequeño reto a la hora de programar el algoritmo. Más que nada, porque si tuviera que jugar a mano en ese juego, no sé cual es la estrategía que tendría que seguir…. Será cuestión de pensar un rato.

Oct 20

Google negro

Hay que ver en qué cosas se entretiene la gente. Ha salido un buscador similar a google, pero de fondo negro, porque dicen que así se ahorra energía. Se supone que un monitor mostrando un fondo negro gasta menos que un monitor mostrando un fondo blanco y como la página de google se visita como varios millones de veces al día, si fuera negra, se ahorraría un montón de energía.

Según comentan, esto no es cierto, hay monitores que pueden consumir más si están mostrando un fondo negro.

Sin embargo, si hay una iniciativa de ahorro de energía a base de apagar todas las luces un día por la noche en San Francisco y google, para promover la iniciativa, en determinadas zonas de USA está mostrando un google negro.

Visto en google.dirson.

Oct 19

Maven properties o parameter expressions

El otro día, por jugar un poco, me puse a hacer un plugin de maven, para ver cómo va el tema.

Pues es mas fácil de lo que parece. Por supuesto, con el mismo maven creamos un proyecto para desarrollar nuestro plugin

mvn archetype:create
  -DgroupId=com.chuidiang.ejemplos.plugin_maven
  -DartifactId=plugin_maven
  -DarchetypeArtifactId=maven-archetype-mojo

o sea, igual que cualquier otro proyecto, pero indicando con -DarchetypeArifactId que queremos hacer un plugin con esa palabreja tan  rara de mojo. Al ejecutar este comando, nos sale un proyecto maven con una clase con el plugin en plan ejemplo ya creada. Sólo tenemos que tocar a nuestro gusto.

Con un simple mvn install, se instala nuestro plugin y ya lo tenemos disponible.

Dentro del código java del plugin, hay atributos declarados así:

/**
* El parametro saludo.
*
* @parameter expression="Hola"
*/
private String saludo;

cuando se ejecute nuestro plugin, maven se encargará de rellenar nuestro atributo "saludo" con la "expression" que hayamos puesto en el @parameter. En nuestro caso, cuando se ejecute nuestra clase plugin, saludo tendrá el valor "Hola":

Es posible en ese @parameter expression poner cosas como esta

@parameter expression="${project.version}"

con lo que nuestro atributo se rellenaría con el número de versión de nuestro proyecto. Estupendo y maravilloso pero, como no, nos surgen problemas. Una vez que ves el ejemplo te dedicas a buscar una lista de posibles expresiones que puedes poner. Sí, sí, la versión del proyecto, pero ¿qué más cosas tengo disponibles?. Pues bien, ahí está el problema. No existe una documentación con esa lista.

Investigando, investigando, he descubierto tres cosas a partir de las cuales sacar estas posibles expresiones.

  • La primera es que si en mi plugin pongo expression="${project}" y el tipo de atributo Object y el código se dedica a investigar qué es lo que obtengo, resulta que tengo una clase MavenProject. Tirando del hilo, descubro que los get de esta clase son el segundo nivel de propiedad. Es decir, existe project.version porque hay un MavenProject.getVersion(). Y existe ${project.build.directory} porque se puede hacer MavenProject.getBuild().getDirectory(). De esta forma, la API de MavenProject nos puede ayudar a sacar posibles expresiones.
  • En este enlace hay una lista de propiedades que la gente ha recopilado.
  • En el directorio lib de donde tenemos instalado maven, tenemos un maven-core-xxx.jar. Ahí dentro, en el directorio META-INF/maven/plugin-expressions tenemos tres ficheros xml en el que se indican los posibles nombres de propiedades y el tipo de dato que pueden contener.

Yo por mi parte y por supuesto, he hecho mi propio resumen de los parámetros maven en la Chuwiki. Si estais interesados en el tema, estais invitados a colaborar ampliando o completando esa lista.