Jul 26

Jugando con PreparedStatement

 Hace tiempo que he oido que los PreparedStatement de java son más eficientes que los Statement, así que me he puesto a jugar con el tema y verlo por mi mismo.

Mi primera prueba un pequeño fracaso. Cogí una base de datos MySQL e hice 1000 inserciones seguidas con Statement, componiendo la SQL y luego otras 1000 con PreparedStatement. Por igualdad de condiciones, en ambos casos partía de la base de datos vacía. Pues bien, no solo no había diferencia apreciable, sino que además en ocasiones las Statement tardaban menos.

Me puse a investigar y descubro que hay dos requisitos indispensables para que los PreparedStatement sean más efectivos:

  1. El servidor de base de datos debe soportar los Prepared Statement, que realmente no son cosa de java, sino del servidor de base de datos.
  2. El conector/driver que se use también debe soportarlos.

Así que a ver si mi versión de driver y de servidor MySQL lo soportan … pues sí, lo soportan. Sigo investigando y descubro que al conector de MySQL hay que decirle en la configuración que use PreparedStatement del lado del servidor, cosa que por defecto no hace. Esto se consigue poniendo en la cadena de conexión algo como 

conexion = DriverManager.getConnection(
   "jdbc:mysql://localhost/basedatos?useServerPrepStmts=true", "usuario", "password");

Pues nada, pruebo otra vez y esta vez sí que es ligeramente más rápido el PreparedStatement, pero no tanto. El tiempo que tarda cada vez el programa en correr es distinto y aunque el PreparedStatement suele tardar algo menos que el Statement, a veces no ocurre así. Estamos hablando de entre 15 y 18 segundos, en el que el PreparedStatement apenas le saca un segundo al Statement y no siempre.

No puede ser que eso sea así. Algo debo estar haciendo mal. Sigo leyendo y encuentro un sitio (no recuerdo cual) que dice que algunas bases de datos no mantienen los PreparedStatement después del commit. No veo nada en MySQL que indique esto, pero me decido a hacer la prueba. Hago que la conexión no sea auto-commit y pongo el commit fuera del bucle de inserción. Las mil inserciones en cada caso quedan "en el aire" hasta que se hace un commit al finalizar cada bucle.

Esta vez el PreparedStatement sigue sacando su aproximadamente un segundo sobre el Statement … pero el tiempo total se reduce drásticamente, tanto para Statement como para PreparedStatement, a unos 3 ó 4 segundos. El hecho de no hacer commit hasta el final, independientemente del tipo de Statement usado, hace que el tiempo total baje de 15 segundos a 3. Y el segundo a favor de PreparedStatement se convierte ahora sí, en algo apreciable. Seguramente, todo lo que estaba midiendo antes eran los accesos reales a disco duro para realizar realmente las inserciones de una en una con el auto-commit. En el segundo caso, la medida ya sí debe ser mejor comparativa enrtre PreparedStatement y Statement.

Pero … ¿y en una aplicación real?. ¿Podemos permitirnos el lujo de no hacer commit hasta que hayamos hecho un conjunto más o menos grandes de inserciones?. Yo creo que normalmente no, así que ¿realmente merece la pena el uso de PreparedStatement por temas de eficiencia?. Pues supongo que depende entonces de los casos.

Por ejemplo, se me ocurre que si una sola inserción es más compleja que la mia e involucra varias tablas, podemos dejar el commit para cuando se haya hecho la inserción en todas las tablas implicadas. Esto tiene cierta lógica, la inserción se completa totalmente o no se completa en absoluto y el commit confirma varias inserciones, una en cada tabla. La diferencia de velocidad entre PreparedStatement y Statement será mayor cuantas más tablas haya implicadas.

También se me ocurre, aunque sólo sea una tabla, que si tenemos garantía de que van a ir insertándose muchos registros con mucha frecuencia, como para comprometer la velocidad con la que somos capaces de insertarlos en base de datos, podemos usar PreparedStatement y un pequeño Timer que haga commit cada cierto tiempo. Una idea rebuscada, pero sí se de casos donde podemos aplicarla. A veces tenemos equipos hardware "escupiendo" información a toda velocidad, información que necesitamos almacenar en base de datos.

En resumen, PreparedStatement posiblemente sí es más eficiente, pero para sacarle realmente rendimiento, no basta con usarlo sin más. Hay que tener en cuenta más cosas, como si tenemos el auto-commit a true o con qué frecuencia necesitamos hacer los commit. Si se investiga un poco, también ser verá que hay otras variables a tener en cuenta, como temas de caché en la configuración del servidor de base de datos o del conector, pero soy demasiado vago para investigar eso sin necesidad real.

Aparte de todo esto, a favor de los PreparedStatement, también está el tema de seguridad. Con PreparedStatement evitamos tener que chequear y "escapar" los caracteres conflictivos en las cadenas de texto que vamos a insertar en base de datos. Si vamos a insertar un nombre de usuario que pedimos al usuario y a este se le ocurre poner una comilla simple, por ejemplo "O’Donnell", podemos meterla tal cual en un PreparedStatement, pero necesitamos "escapar" la comilla antes de usarla en un Statement.

Jul 22

¿Dos es más del doble? ¿Quién se atreve a probarlo?

Pongámonos en situación. Supongamos un grupo de dos desarrolladores que tienen que hacer dos tareas. Las tareas no tienen nada que ver la una con la otra, incluso son de proyectos distintos. Lo único que tienen en común es que tienen que estar para ayer, es decir, el tiempo para que estén acabadas es demasiado corto y es muy probable que se llegue por los pelos o no se llegue.

Ante esta situación tenemos dos soluciones:

  1. Solución tradicional, estándar, típica y la más habitual. Cada desarrollador se pone con una tarea y hasta donde lleguen. Esto da tranquilidad aparente, puesto que ambas tareas están haciéndose y se acabarán o no dependiendo de si los desarrolladores se acordaron de traerse el gorro de dormir a la empresa.
  2. Solución ágil, moderna y a la moda. Los dos desarrolladores se ponen juntos a hacer una de las tareas. Cuando la acaban, se ponen con la otra. Desde luego, parece muy arriesgado y a algún jefe se le pueden poner los pelos de punta – ¡¡ Pero !! ..  ¿cómo?¿no estais haciendo nada de la tarea B? -

Supuestamente la solución ágil es la correcta, pero eso sólo es cierto si dos desarrolladores trabajando juntos avanzan el doble de rápido que uno solo. Pero no queda ahí la cosa. Si la solución ágil es la correcta, es porque es mejor que la solución tradicional. Eso quiere decir que dos desarrolladores juntos deberían trabajar más del doble de rápido que si trabaja uno solo.

¿Y es esto cierto? ¿dos desarrolladores juntos trabajan más del doble de rápido que uno solo?. Si tú eres uno de los desarrolladores y es a tí al que van a caer los capones si las tareas no están acabadas a tiempo, ¿te atreverías a desarrollar una en conjunto con tu compañero y abandonar temporalmente la segunda? Y si tú eres el jefe de esos dos desarrolladores y es a tí al que caen los capones ¿les animarías a trabajar juntos en una tarea dejando abandonada temporalmente la otra? ¿Y a mitad del tiempo límite darías el tipo cuando tengas que decir -La tarea B no está porque ni siquiera la hemos empezado-?

Decisión difícil que requiere valor.

Jul 08

¿Por qué elegí Scrum?

 

Este comentario de ilcavero al post Se nos va relajando Scrum… y los siguientes comentarios me han dado bastante sobre lo que reflexionar, si Scrum es o no adecuado para nuestro caso.

Nuestros sistemas llevan muchísimos equipos hardware de distinta índole (GPS, Receptores de radio, Grabadores digitales, etc, etc) que nuestro software debe controlar. Algunos de esos equipos se compran, pero otros se fabrican en otros departamentos de nuestra empresa. Además, todo el montaje de esos equipos en los armarios correspondientes, con su cableado entre ellos y con los ordenadores, es también cosa de otro departamento más de la empresa. De hecho, los costes de los equipos, de los armarios y su montaje son mayores que los del software que hacemos nosotros.

Dichos equipos y montaje no suele estar completa hasta fases finales del proyecto, de hecho, los plazos de entrega se miden más por el tiempo que se puede tardar en comprar/fabricar los equipos y montarlos que en lo que se va a tardar en hacer el software, que se supone que es menos. Por ello, no podemos probar en condiciones reales nuestro software hasta casi el final del proyecto.

Y esa es la duda que plantea ilcavero sobre si es adecuado o no usar Scrum en estas condiciones. Nosotros (los del software), al principio del proyecto podemos pensar en un sprint de un mes (por ejemplo), una serie de historias de usuario y hacer el sprint. Pero no podemos garantizar que esas historias de usuario están completas sin pruebas con los equipos reales que todavía no están disponibles. Nuestra única opción para hacer una prueba del software es hacer simuladores de los equipos. Esto hace que el producto "entregado" al final de cada Sprint no sea el producto real.

Por ello y siendo consciente del asunto, al elegir Scrum, tuve en cuenta que no se probarían los sprint en el sistema real. La condición de "historia terminada y funcionando" debería relajarse un poco y ser "historia probada y funcionando con simuladores, pendiente de prueba real en cuanto haya equipo".

Y de esta forma, aunque se pierden parte de las ventajas de Scrum relativas a entregas frecuentes, si nos aporta el resto de ventajas:

  • La reunión diaria hace que tengamos más sensación de equipo. Anteriormente, cada desarrollador se dedicaba a su tema y trabajaba aislado de los demás, salvo que su código tuviera comunicación con el código de otro. Aunque no llevamos mucho tiempo con Scrum y no lo estamos haciendo bien, algunos desarrolladores empezaban a coger tareas que no eran suyas, símplemente para ayudar a un compañero o porque creían que ellos podían hacerlo mejor o más rápido que el compañero novato.
  • La demo al final del Sprint no es como debiera ser, pero sí se llama a la gente (jefes de proyecto principalmente y otros desarrolladores de otros grupos que tengan que hacer algo parecido). Todos son conscientes de que hay cosas "simuladas" y que habrá que depurar al final, con equipos reales.
  • La retrospectiva ayuda a mejorar la forma de trabajo, independientemente de que el producto de la demo sea real o no.

Las pegas, hay dos importantes:

  • La fase final del proyecto (en la que estamos ahora en uno de ellos), puede durar uno o dos meses en los que el código está prácticamente hecho al 100%, pero no probado con todos los equipos reales. Esta parte de integración es muy compleja de llevar con Scrum (al menos, no se me ocurre como), ya que los errores no son conocidos y sabes que vas a dedicar el día a probar y corregir lo que vayas encontrando. Imposible hacer un sprint-planning, demos o incluso en el día a día, contar que vas a hacer ese día. Nuestro "Scrum" actual es sin sprints y se basa símplemente en reunirse a diario, contarnos los bugs encontrados y corregidos el día anterior, los encontrados y no corregidos, así cómo que problemas tenemos con las pruebas.
  • Esta fase absorbe el 100% del tiempo (es la fase final del proyecto que está a punto de cumplir hito) y las pruebas son lentas, ya que no sólo es el software el que tiene fallos, también hay cables mal hechos o equipos con bugs en su firmaware. Cualquier prueba necesita gente de varios departamentos. En un post anterior comentaba que estaba de Scrum master de dos equipos de scrum simultáneamente. Pues bien, uno de esos equipos es el que está integrando ahora … y el otro se ha quedado sin Scrum master.

En cualquier caso, otro punto importante a tener en cuenta es que hay muchos post en muchos blogs en los que se critica a los que dicen "Nosotros no podemos aplicar Scrum". Las condiciones no son las ideales, pero es cuestión de intentarlo y estoy convencido de que si logramos sacarlo adelante, aunque sea con pegas, vamos a mejorar nuestra forma de trabajo. Todo es cuestión de insistir y para eso están las retrospectivas al final del sprint, para ver cómo mejorar.

Jul 03

Se nos va relajando Scrum…. por decirlo suavemente.

 

Hace tiempo empezamos a intentar hacer Scrum un grupo de cuatro para atender seis proyectos, con sprints de una semana. Los sprints tan cortos eran necesarios para poder reorganizar el product backlog mezclado con historias de varios proyectos y poder cambiar de unos proyectos a otros en función de sus prioridades. Pero esos sprints tan cortos nos hacían perder mucho tiempo, ya que organizar todos los viernes una o dos demos, era demasiado para enseñar un pequeño incremento de funcionalidad.

Así que intentamos aproximarnos a algo más como Kanban. Teníamos nuestras historias, nuestras reuniones diarias, nuestras tareas, planificación por poker, pero no haciamos las demos.

Y ya no queda ni eso. Uno de los proyectos ha entrado en sus fases finales, así que estamos los cuatro liados con ese proyecto. Nuestro trabajo día a día consiste en probar, encontrar incidencias y corregirlas. Nuestro product backlog es "probar tal tema y corregir". Planificar eso es complejo, una incidencia nunca se sabe cuánto se puede tardar en corregir y menos una semana antes, cuando todavía no la has encontrado.

Así que nada, consideraremos este periodo como un descanso de Scrum, seguiremos con nuestras reuniones diarias (han gustado a todos los miembros del equipo) y a la vuelta de vacaciones retomaremos el Scrum/Kanban.

Jul 02

Chuletas a mogollón

 

En Cheat Sheet hay un montón de chuletas de temas de informática. Pequeños pdf de una o dos páginas para imprimir en el que se resumen comandos de un montón de temas: subversion, git, vi, ada, ajax, apache, etc, etc.

Ideal para bajarse, imprimir y tener a mano las de las herramientas que más usemos día a día, sobre todo cuando empezamos con ellas.

Jul 01

Ser o no ser héroes

 

Imagínate que caes en un equipo de desarrollo con gente competente, que saben lo que hacen y lo hacen bien. Tienes además la suerte de que el jefe de proyecto para el que trabajas también es un buen jefe de proyecto. Sabe lo que quiere, se lo cuenta al equipo con claridad y trata de resolver todos los problemas que se presenten. ¿Qué pasa en esta situación?. Lo normal. El proyecto va bien, sin problemas graves, llega a tiempo a sus fechas de entrega con unas incidencias razonables y sin fallos graves.

Suponte ahora lo contrario. Un proyecto en el que el jefe de proyecto no tiene claro lo que quiere, no te especifica nada, no te dice como lo quiere, pero sí te dice cuando ya los has hecho que así no lo quería. Además, el grupo de desarrolladores es más bien de la media para abajo, el poco código que sale está lleno de errores y si funciona, es de casualidad. ¿Qué pasa en esta situación? Pues lo normal, que el proyecto va mal, que no llega en fechas, que cuando se pasan las pruebas con cliente todo es un "efecto demo" gigante.

Entre los dos proyectos hay además una consecuencia interesante. En el primer caso, los jefes del jefe de proyecto apenas saben que existe ese proyecto. Es un proyecto que no da pegas, que no gasta más dinero de la cuenta, que no se retrasa y que no recibe quejas del cliente, así que la cosa "no sube" hacia arriba, así que para ellos no es más que una cifra bonita en alguna tabla de Excel.

En el segundo caso, empiezan a dispararse las alarmas, los jefes del jefe empiezan a recibir los problemas de dinero, fechas y quejas del cliente. Empiezan a saber que ese proyecto existe y empiezan a hacerle un seguimiento exhaustivo día a día. Se empieza a hacer presión y los desarrolladores y jefe de proyecto empiezan a echar horas como locos y se olvidan de que tienen casa.

En el primer proyecto, el buen jefe de proyecto y los buenos desarrolladores han hecho estupendamente su trabajo, pero no se les ha notado ni los jefes los van a valorar en lo que merecen. En resumen, "no son héroes".

En el segundo proyecto, si después de echar muchos fines de semana y horas a tope se consigue que el proyecto pase como se pueda, con un listado interminable de incidencias y cosas pendientes, con el cliente descontento, pero pasa, entonces los que han participado en él son la leche, han hecho un esfuerzo sobrehumano y han conseguido sacar adelante un proyecto que era un caos. Gracias a esto, los jefes de proyecto ya conocen las caras de los desarrolladores y del jefe de proyecto. Por supuesto, se han creído todas las excusas que el jefe de proyecto y los desarrolladores les han dado para justificar que el proyecto va mal. En resumen, "Sí son héroes".

Desgraciadamente, es la realidad. Se valora más al desarrollador que echa horas y horas resolviendo problemas en un proyecto caótico, que al desarrollador que no resuelve problemas a horas intempestivas de la noche, símplemente porque no ha generado esos problemas.