martes, 28 de febrero de 2012

Orden y formato al código PL/pgSQL


“Any code of your own that you haven’t looked at for six or more months might as well have been written by someone else.”
Eagleson’s Law

Leer y entender un trozo de código de unas pocas líneas es fácil, aunque haya sido escrito como si se hubiese caído al suelo y esparcido por toda la habitación. Ahora bien, si tenemos que leer unos cuantos cientos o miles de líneas, la cosa cambia bastante. Es fundamental tener un código ordenado y bien identado para facilitar la legibilidad.

Existen muchas herramientas que facilitan o realizan directamente esta tarea. Son las llamadas herramientas de embellecimiento o formato ("code beautifiers/formatters tools"). La mayoría de los IDE's y editores tienen herramientas para una gran variedad de lenguajes... salvo para PL, donde me he encontrado bastantes carencias.

Si necésitáis una herramienta de este estilo, una de las mejores que me he encontrado es Pl/Sql tidy. Algunas de sus características son:
  • Identación por bloques
  • Compactación
  • Ajuste de mayúsculas/minusculas
  • Alineamiento vertical en asignaciones
El uso de la herramienta es a través de línea de comando, pero también podéis usar la interesante versión online disponible.

Funciona con PL/pgSQL.


Referencias y más información:

miércoles, 1 de febrero de 2012

Apache Commons DbUtils: sencillo, rápido, ligero


“Controlling complexity is the essence of computer programming”
Brian Kernigan

Hoy traigo aqui otra de las joyas de Apache Commons: DbUtils. Ya comenté en el artículo anterior "Librerías imprescindibles en Java" que, en cualquier projecto, antes de pensar en hacer nuestras utilities, debemos pasar por la página de Commons para ver las librerías existentes antes de ponernos a reinventar la rueda. Pues bien, Commons tiene otra pequeña joya que he descubierto y aplicado recientemente con éxito.

Hay ocasiones en las que no usamos un framework de mapeo tipo ORM (JPA/EclipseLink, Hibernate, Mybatis -antiguo iBATIS-) por varias razones: modelo muy cambiante, proyecto muy pequeño, necesitamos un control más fino de las consultas, generación dinámica, etc... En estos casos, no nos queda más remedio que usar directamente JDBC. Sin embargo JDBC es un API muy engorroso que requiere mucho código de limpieza de recursos y mucha fontanería a través de sus capas. Más del 80% de nuestro código JDBC es la instanciación de objetos del API, establecimiento de parámetros, liberación y cierre.


DbUtils es un pequeño conjunto de clases diseñadas para hacer mucho más fácil el trabajo que hacemos con JDBC centrándonos en lo que queremos: consultar, actualizar, insertar. Especialmente nos ayuda en:
  • Se encarga automáticamente de la fontanería previa (conexión y preparación) y de la limpieza, evitando posibles errores de liberación de recursos.
  • Rellena las propiedades de JavaBean automáticamente a partir de ResultSets. No es necesario copiar manualmente valores en instancias de beans.
Por todo la anterior, el uso de DbUtils reduce drásticamente la cantidad de código que necesitamos con JDBC. Por hacer una comparativa, yo díría que DbUtils es a JDBC lo que JDOM a javax.xml.

Usar DbUtils es muy sencillo. Hay dos clases/interfaces principales que constituyen el corazón de DbUtils: QueryRunner y ResultSetHandler. QueryRunner se encarga de realizar todo el trabajo: abre la conexión, ejecuta la consulta o actualización y devuelve el resultado. Para devolver el resultado de diferentes formas se usan las distintas implementaciones de la clase ResultSetHandler, que permite devolver el resultado en una lista de  POJO's, lista de arrays, lista de Map, etc...

A continuación pongo un ejemplo simple de una pequeña DAO de una aplicación que tuviese que acceder a una base de datos PostgreSQL y a un AS/400 simultáneamente. En el ejemplo se pueden observar características muy importantes de ahorro de código y, por tanto, de su consecuencia más valiosa, ahorro de tiempo:
  • No hay declaraciones de Connection, Statement y ResultSet.
  • No hay liberación de recursos (DbUtil lo hace automáticamente)
  • No es necesaria la engorrosa recolección de campos a través de la iteración del ResultSet. Podemos devolver las consultas en un Map<String, Object> (NombreCampo, Valor) o en un JavaBean cuyas propiedades coincidan con los campos que devuelva nuestra consulta.


/**
   Suponemos una clase DAO cualquiera de acceso a datos
*/
public class ASDao {
   
   private AS400JDBCDataSource asDataSource;
   private PGSimpleDataSource pgDataSource;
   private QueryRunner qr;

   public ASDao() throws Exception {
       // El datasource puede instanciarse...
       asDataSource = new AS400JDBCDataSource("host4.cestel.es","asuser","xxxxxx");
       // U obtenerse a partir de un JNDI de un contenedor
       pgDataSource = new InitialContext().lookup("java:comp/env/jdbc/pgDS");
       qr = new QueryRunner(asDataSource);
       qrp = new QueryRunner(pgDataSource);
   }


   /**
       Realiza una consulta parametrizada (que debe devolver una sóla fila) y 
       devuelve un Map<String,Object> con el nombre del campo
       y su valor. Se asume que la consulta devuelve una sóla fila.
       Son apenas dos líneas.
   */
   public Map<String,Object> findData(String clientCode, String debtCode) 
                                                                throws SQLException {
       MapHandler result = new MapHandler();
       return qrp.query(
               "select c.id, c.code, de.id, de.customer_debt_id, dos.id, dos.code\n" +
               "from debt de join dossier dos on de.dossier_id = dos.id \n" + 
               "join customer c on dos.customer_id = c.id\n" +
               "where customer_debt_id = ?\n" +
               "and c.code=?\n" +
               "and end_process_date is null", result,debtCode, clientCode);
   }

   /**
       Realiza una consulta parametrizada y devuelve el resultado como una lista de 
       JavaBeans "TablaAS". La creación de la lista y "llenado" de los objetos corre 
       por su cuenta. Lo único que tenemos que hacer es crear la clase TablaAS con 
       propiedades (getter, setter). Las propiedades de los POJO (JavaBeans) que 
       se "llenaran" serán aquellas cuyo nombre coincida con el campo devuelto.
       Dos líneas (más la clase)
   */
   public List<TablaAS> findByClient(String clientCode) throws SQLException {
       ResultSetHandler<list<TablaAS>> blh = new BeanListHandler<TablaAS>(TablaAS.class);
       return qr.query("select * from  CESQ.TABLA_AS where CODCLTE = ?", blh,clientCode);
   }

   /**
       Ejemplo de la misma consulta devuelto como un array 
       o como una lista de POJO's (JavaBean)
   */
   public void test() throws SQLException {
       ArrayHandler ah = new ArrayHandler();
       ResultSetHandler<list<TablaAS>> h = 
                       new BeanListHandler<TablaAS>(TablaAS.class);
       
       Object[] resultArray = 
           qr.query("select * from  CESQ.TABLA_AS FETCH FIRST 2 ROWS ONLY", ah);

       List<TablaAS> result = 
           qr.query("select * from  CESQ.TABLA_AS FETCH FIRST 2 ROWS ONLY", h);

   }
}

Como todas las cosas, obviamente DbUtils tiene un target concreto de aplicación, no es una bala de plata para todo. Ahora bien, si no devolvemos conjuntos de datos grandes, podría usarse como perfecto sustituto de JDBC con un mínimo impacto en el rendimiento y con una importante mejora en legibilidad y mantenibilidad.

Puedes ver más ejemplos en el sitio de DbUtils.


Referencias y más información:

miércoles, 18 de enero de 2012

Expo NASA: La aventura del espacio


Todo lo que una persona puede imaginar, otras podrán hacerlo realidad.
Julio Verne (1828-1905).


La exposición itinerante que la NASA ha traído a Europa está en Madrid desde el pasado Diciembre. Es una visita obligada para curiosos y amantes de la astronáutica y una ocasión excepcional para poder contemplar instrumentos, maquinaria y réplicas de la tecnología actual y la que llevó al hombre a la luna hace casi 43 años.

Pensaba ir a verla de todos modos, pero he tenido la suerte poder de ahorrarme los 16€ de la entrada entrada por ser uno de los ganadores del concurso promovido por amazings.es y la organización de la exposición, así que fui a verla el pasado domingo.

Yuri Gagarin afirmó en una ocasión que su decisión hacia la astronáutica se la debía al excepcional Julio Verne. Y no es para menos. Él es uno de los personajes destacados en la primera sala que nos encontramos en la exposición, la de los soñadores, tras pasar una réplica de la pasarela de acceso a la parte superior del Saturno V y que daba acceso a la nave Apollo.

No voy a detallar aquí el contenido de la exposición, que podéis encontrar en el propio dossier de prensa y en abundante información en la red, sino más bien mi impresión subjetiva y crítica de la misma.

Lo más fascinante de la exposición es poder contemplar in situ y a tamaño real muchas de las cosas que me han fascinado y de las que he visto fotos cientos de veces. Constatas que, hasta que no lo ves con tus propios ojos, no te haces una idea del aspecto y tamaños reales de ciertos artefactos. Por ejemplo, el interior del módulo de ascenso del L.M (Módulo Lunar), tan pequeño, tan frágil... con un aspecto más parecido a un batiscafo que a una nave espacial. Una cosa es que sepas que pilotaban de pie y otra cosa es que lo compruebes con tus propios ojos. Llama la atención especialmente el minúsculo tamaño de ciertas cápsulas espaciales, especialmente la Mercury, que cabría en una furgoneta: meterse ahí dentro sobre un misil Redstone modificado era realmente como estar dentro de la cabeza de un misil balístico. A medida que recorría la exposición reflexionaba sobre el tremendo esfuerzo tecnológico que se realizó en tan pocos años, partiendo totalmente de cero.

Cuando entras en la exposición, te ofrecen unas audioguías (iPod touch) que te presentan varias audiciones/videos por cada sala con información acerca de la misma en una cantidad claramente insuficiente y desproporcionada a las necesidades de información que requieren los objetos expuestos. Y aquí entramos en la parte más inacabada y decepcionante de la exposición: la información. Los objetos expuestos tienen unas etiquetas numéricas que puedes consultar en unos pequeños paneles (sobre los que nos agolpamos los visitantes), cuya brevísima y exigua descripción apenas te satisface y que, por si fuera poco, van apareciendo lentamente en presentación continua (no caben todos en las pantallas) en una desordenada mezcla entre inglés y español. Ya que ofrecen los iPods, la organización podría (por el mismo coste) haber añadido mucha más información multimedia de cada sala e incluso de cada artefacto, evitando así los corros que se forman sobre las pantallitas esperando que aparezca la descripción (que no información) del número que estamos buscando. En definitiva, el problema es que, salvo que sepas lo que estas viendo, me temo que la mayoría de la gente no puede "conocer" lo que está viendo, porque nadie se lo explica.

Por otro lado, los iPod touch cuentan con una excelente pantalla de 3,5 pulgadas que ni siquiera se ha aprovechado para hacer más accesible la exposición a personas con discapacidad auditiva añadiendo subtítulos a los audios y vídeos que ofrece. Vamos, aquí parece que tras todo el esfuerzo, parece que la parte más importante, la de la información, la hubieran dejado a medias. No hacen falta más carteles, ni más grandes. Hubiera bastado con cargar suficiente material en los iPod's. Por otro lado, si en información están suspensos, tienen un cero absoluto en accesibilidad, y no por falta de medios, sino más bien por pura desidia, cosa que me parece totalmente imperdonable, tratándose de una exposición de este calibre.

De hecho, la ausencia de información incluso en temas básicos es tan patente que la organización está constantemente respondiendo en twitter a la pregunta "¿Hasta cuándo está la exposición?", ya que esa información no está disponible ni siquiera en la web oficial. Por cierto: es hasta el 15 de Junio.

Para compensar esta falta de información, recomendaría leer algo sobre la carrera espacial y las misiones de la NASA, ver documentales al respecto, o ver la mini-serie "De la tierra a la luna" antes de ver la exposición, si tenéis ocasión, para poder disfrutar la exposición al completo conociendo lo que se está viendo.

Finalmente, me hubiera gustado llevarme algún recuerdo como alguna serie de maquetas de lanzaderas (titan, atlas, saturno, sts, etc...) oficial. De nuevo, absolutamente decepcionante: apenas algunos carísimos y atroces juguetes de goma, torcidos, que ni siquiera estaban a escala. No había forma de llevarse la famosa serie de lanzaderas o alguna maqueta más o menos decente de un Saturno V o de una lanzadera salvo pequeños pisapapeles metálicos monocolor con poco detalle.

Una excelente exposición mal rematada y poco cuidada en los detalles. En todo caso, una exposición totalmente recomendable por única y excepcional.


Referencias y más información:

domingo, 18 de diciembre de 2011

2011: 50 años en el espacio, 30 "peceando"


640K ought to be enough for anybody.
- Bill Gates, 1981 (*)

Una cosa es segura: en tecnología no se deberían realizar aseveraciones del tipo "nunca jamás" porque más tarde o más temprano, el tozudo paso del tiempo te acabará poniendo en el ridículo más espantoso.

Hace 30 años, se lanzó el IBM PC, predecesor de los actuales ordenadores personales que hay en la mayoría de las casas y oficinas. Curioso nombre el que le pusieron, ya que difícilmente se podría llamar "personal" a algo científico que podía costar hasta casi $20.000, aunque mira tú, ironías del destino, sus equipos sucesores si han acabado siendo "personales".

Con respecto a los temas de tecnología que vertebran este blog, de este año destacaría otro suceso trascendental aparte de la curiosa efeméride anterior: un fallecimiento. Este año nos dejó una de las personas que más relevancia tiene en prácticamente toda la tecnología que uso diariamente en mi profesión y de la que deriva la esencia de casi todo lo que usamos: Dennis MacAlistair Ritchie, más conocido como Dennis Ritchie, o simplemente dmr (muchas veces escrito así, "dmr", en minúsculas, con un tremendo respeto, y con la solemnidad con la que uno escribe la más valiosa contraseña). El azar ha querido que el año de su muerte sea también el 40 aniversario de la publicación del primer manual de UNIX "UNIX Programmer’s Manual" que él escribió conjuntamente con Ken Thomson.

Poco puedo añadir yo a lo muchísimo publicado sobre quién fue dmr. La mayor parte de los que visitáis el blog con asiduidad, conocéis su enorme y extensísima contribución al mundo. Tan enorme, como igual de decepcionante la poca repercusión que la noticia ha tenido en la prensa no especializada, que sin embargo ha dado extensa cobertura a otro lamentable fallecimiento contemporáneo, de un personaje más público y notorio, más cool, aunque su legado no pueda ser comparable en absoluto ni por transcendencia ni por importancia. El tiempo pondrá a cada uno en su sitio.

La significación en el mundo de la tecnología de dmr es comparable a la de Marie Curie a la física nuclear o la de Ramón y Cajal a la neurología... y aún así, hay una diferencia extrema: mientras éstos "descubrieron", dmr creó. dmr puso las dos semillas de los llamados entonces Sistemas Abiertos con la creación de UNIX y C. De la misma forma que no podríamos hablar del ADN sin la adenina, guanina, y citosina, tampoco podríamos hablar de Windows, Linux, Mac OS X, Java, Ruby, PHP, o .NET sin C, ya que C ha sido y sigue siendo la base de la creación tecnológica a partir de la cual se han construido tecnologías más complejas.

Por otro lado, Internet (correo electrónico, facebook, Google, twitter, etc), Android, Mac OS X, iPhone y su iOS, Linux... todos tienen en común su procedencia y su esencia, su corazón: el UNIX que creó dmr. Actualmente, desde los Sistemas Operativos de los más grandes e importantes Data Centers y de los equipos financieros del mundo, hasta los smartphones más pequeños siguen usando algún tipo de UNIX o una derivación de éste. Sobre UNIX y C está construido el mundo tecnológico que conocemos. Este es el enorme legado de dmr.

Transborador y Estación Espacial Internacional juntas
Fuente: NASA
En otro orden de cosas, de interés también de este blog, damos repaso al año en lo que a temas de astronomía se refiere: 30 años después del primer vuelo orbital de un transbordador espacial (el Columbia), este año se ha puesto fin al programa de transbordadores espaciales, es decir, al programa STS. La sobrecogedora foto a la izquierda, es muy especial. Por lo general se toman fotografías de la Estación Espacial Internacional (ISS) desde el transbordador, o viceversa, pero no es frecuente que una tercera nave esté acercándose mientras las dos anteriores están unidas. Esta imponente imagen, tomada desde una nave Soyuz TMA-20, donde se aprecia el enorme tamaño de la Estación Espacial Internacional, es una preciosa foto que no se podrá volver a tomar nunca más.

Coincide este hecho con la celebración del 50 aniversario del primer vuelo espacial, realizado por Yuri Alexéievich Gagarin, ciudadano soviético, a bordo de la nave Vostok 1. En honor a su viaje y su transcendencia, la ONU decidió declarar el 12 de Abril como "Dia del Espacio". Esa misma noche se celebra la "noche de Yuri". Curiosamente, el día del primer vuelo de un transbordador orbital (Columbia) fue también el 12 de Abril.

Carl Sagan
También el 20 de diciembre de este año se cumplen 15 años sin el divulgador científico más grande de todos los tiempos. El "astrónomo del pueblo" que ilusionó a todas las mentes inquietas a través de una narración elocuente, precisa, seductora y poética en "Cosmos: un viaje personal": Carl Sagan.

Termino con un comienzo esperanzador, una emocionante nueva misión con el robot de exploración espacial más sofisticado lanzado hasta ahora: el Curiosity. Os dejo con una animación de su viaje, su espectacular aterrizaje y operaciones de superficie (ponedlo a pantalla completa en HD porque merece la pena).

¡ Feliz nuevo año 2012 !




(*) La frase ha sido atribuida frecuentemente a Bill Gates, aunque él ha negado decir tal cosa y existe discusión al respecto ya que no parecen existir evidencias firmes.


Referencias y más información:

miércoles, 14 de diciembre de 2011

Copiar y pegar en applets Java

Una de las páginas a las que suelo acceder a menudo es ésta. Se trata de una sencilla página contenedora de un applet para probar expresiones regulares en Java realizada por David Matuszek.

Esta página contiene una de ésas maravillosas utilidades tipo que acaban siendo atemporales (yo diría que hace más de 7 años que lo uso): sencilla, directa, concisa y eficaz. La verdad es que para probar una expresión regular antes de incorporarla en el código no se necesita más de eso... ni menos tampoco, ya que esto permite ahorrar mucho tiempo de depuración. Una pequeña joya muy recomendable.


De un tiempo a esta parte, me di cuenta que ya no podía copiar las expresiones realizadas ni pegar texto de ejemplo. Esto me resultaba tremendamente molesto, pero siempre que usaba la página tenía tanta prisa por resolver el problema que me llevaba a ella que no me permitía detenerme un momento para averiguar la razón del incómodo cambio.

Bueno, pues resulta que desde el lanzamiento de Java Plug-in 1.6.0_24 en Febrero 2011, copiar y pegar desde o hacia el portapapeles del sistema se consideró un agujero de seguridad y, por tanto, se desactivó. Puedes copiar entre applets, pero no entre applet y portapapeles del sistema.

La solución estaría en modificar el fichero java.policy del directorio lib/security del plugin, aunque lo más probable es que este cambio sea sobreescrito de nuevo en la siguiente actualización de la JRE. Así que lo mejor es crear un archivo de usuario java.policy personalizado:
  1. Localiza tu fichero Java Security Policy. Se llama java.policy y debería estar bajo el directoro lib/security de tu instalación Java JRE. En Linux está en /usr/lib/jvm/java-6-sun-1.6.0.26/jre/lib/security/java.policy.
  2. Copialo a tu home y renómbralo a .java.policy (fíjate que debe comenzar con un punto).
  3. Edita el fichero y añade la línea que se indica debajo de los comentarios:
  4. // "standard" properties that can be read by anyone
    permission java.awt.AWTPermission "accessClipboard";
    
  5. Reinicia el navegador

Referencias y más información:

sábado, 12 de noviembre de 2011

Los niveles de aislamiento en PostgreSQL (no son 4)



"No. No lo intentes. Hazlo, o no lo hagas, pero no lo intentes."

Cuando ví el Episodio IV de la Guerra de las Galaxias ("El Imperio Contraataca"), aún era un niño impresionable, y me llamó la atención la reprenda que hizo Yoda a Luke y que cito aquí. Era uno de ésos consejos marciales que se enuncian solemnes como un consejo vital.

Con el tiempo te das cuenta que como consejo está bien, y puede ser incluso un buen objetivo... pero en ciertas facetas de la vida no es válido. Por ejemplo, en el mundo científico y en nuestro mundo profesional el consejo es justamente el contrario: inténtalo, pruébalo y compruébalo. Y sólo cuando lo hayas hecho y consigas un resultado repetible, ponlo en práctica, esto es, súbelo a producción.

Gracias a no seguir el consejo de Yoda fui consciente de una (grave) carencia de PostgreSQL con respecto a los niveles de aislamiento. Como ya hice una introducción al aislamiento en otro artículo, no voy a extenderme más en el tema y voy al grano. El caso que me ocupaba es que tenía que hacer una importación transaccional de datos masiva en un sistema en OLTP de producción en el que se están modificando constantemente datos relacionados con los que voy a importar. El resultado de la importación es que la transacción gigante bloquea datos e impide que se efectúen modificaciones en datos relacionados paralizando en la práctica buena parte de las operaciones de producción produciéndose un efecto "bola de nieve" al sumarse cada vez más transacciones en cola a la transacción gigante pendiente. Sin embargo, para lo único que quiero la transacción es para tener atomicidad en la operación, es decir, para que no se quede a medias en caso de algún problema, pero no me importa que se puedan producir eventualmente casos de dirty read, que no afectarían a los usuarios del sistema de producción en su trabajo. Vale, no hay problema. La transacción de inserción la podemos realizar con el nivel de aislamiento más bajo (READ_UNCOMMITED) y problema solucionado. ¿No? No obstante, no hagamos caso a Yoda, y probémoslo en pre-producción. Resultado: exactamente el mismo que si no hubiera especificado nada del nivel de aislamiento.

¿Qué ha pasado?

En la documentación de SET TRANSACTION, en efecto compruebo que PostgreSQL admite los cuatro niveles de aislamiento como la mayoría de las bases de datos (de hecho, la sentencia no dio error)... pero sólo sintácticamente: no están todos implementados. Si contiúas leyendo te das cuenta que no son 4, sino 2 los niveles implementados:
"The SQL standard defines two additional levels, READ UNCOMMITTED and REPEATABLE READ. In PostgreSQL READ UNCOMMITTED is treated as READ COMMITTED, while REPEATABLE READ is treated as SERIALIZABLE."
Lo que viene a decir: "¿Pensabas que eran cuatro, no? Pues no. Son dos". De hecho, ahora (con la versión 9.1) ya son 3. Pero sigue sin estar soportada la lectura sucia (dirty read). En la documentación sobre aislamiento también es bastante claro:
"In PostgreSQL, you can request any of the four standard transaction isolation levels. But internally, there are only two distinct isolation levels, which correspond to the levels Read Committed and Serializable. When you select the level Read Uncommitted you really get Read Committed, and when you select Repeatable Read you really get Serializable, so the actual isolation level might be stricter than what you select."

Un verdadero jarro de agua a mis pretensiones, ya que no puedo conseguir atomicidad sin bloqueo (aunque sea realizando lecturas de transacciones no confirmadas) en PostgreSQL, al menos con la versión actual 9.1.


Referencias y más información:

    Related Posts Plugin for WordPress, Blogger...
    cookieassistant.com