viernes, septiembre 30, 2011

Review del libro La calidad del software y su medida

El libro hace un repaso sobre cómo fueron los primeros intentos de medir la calidad en los productos, y se va introduciendo en cómo se comenzó a aplicar los conocimientos adquiridos en los procesos de fabricación tradicionales en el desarrollo del software.

Aunque me parece bien estructurado, no creo que me aporte ningún conocimiento sobre cómo mejorar la calidad de mis desarrollos. Más bien me ha servido para reafirmarme en mis "teorías" sobre cómo cuidar los desarrollos que hago y procurar que estos lleguen a buen puerto en las mejores condiciones posibles.

Me ha reafirmado en que las metodologías ágiles posiblemente no sean ninguna panacea, pero hoy por hoy, son las únicas que mediante su aplicación pueden ofrecer resultados más que satisfactorios.

Se trata mucho en el libro de fórmulas y aplicaciones matemáticas sobre procesos de construcción del software, pero en ningún momento se tiene en cuenta al "engranaje" principal en un desarrollo... el programador.

Resulta que el programador es una persona, y como tal, no se la puede medir ni aplicar fórmulas a base de constantes y número de miles de líneas que, teóricamente, tendrá la aplicación a desarrollar. Las metodologías ágiles saben muy bien que es la persona la que importa realmente en un desarrollo y por eso hacen girar todo en torno a ellas.

En definitiva, creo que está bien para tener un conocimiento histórico sobre la calidad y cómo a lo largo del tiempo se ha intentado medir, pero no creo que, actualmente, aporte soluciones para aplicar.

Módulo de login personalizado para Tomcat (II)

Hola de nuevo a todos.

En una de nuestras entradas del año 2009 (Módulo de login personalizado para Tomcat), comentábamos cómo modificar el modo de autenticar y autorizar a nuestros usuarios en aplicaciones para Tomcat, para adaptarlo a nuestras necesidades concretas.

Si leéis dicha entrada, veréis que lo último que teníamos que hacer es crear un archivo de configuración (jaas.config) e indicar la ubicación de dicho archivo, pasándola como parámetro a la máquina virtual
(por ejemplo: -Djava.security.auth.login.config=C:"/jaas.config").

Este parámetro se incluiría en el archivo catalina.bat o catalina.sh, dependiendo del sistema operativo.

El problema es que a veces es complicado manejar este archivo de configuración, sobre todo en sistemas en producción, ya que se requieren permisos, reiniciar el servidor, etc...

Bien, pues existe un modo de saltarse estos problemas con el archivo de configuración. Básicamente, lo que tenemos que hacer es:


  • Añadir un context listener (o usar uno que ya exista).
  • Incluir el archivo "jaas.config" en el mismo paquete que el context listener.
  • Obtener la ruta física del archivo en el despliegue de la aplicación. Esto se hace recuperando el archivo empaquetado como un recurso de la clase, y pasando el URI del recurso al constructor de un objecto File. Finalmente, la ruta física del archivo se obtiene mediante el método getAbsolutePath() del objeto File.
  • Pasar la ruta física del archivo como propiedad del sistema. La propiedad en concreto es "java.security.auth.login.config".
Puedo asegurar que lo he probado y funciona. Os pongo un ejemplo sencillo:

Supongamos que creamos un context listener (MyContextListener) el el paquete "com.test.listeners".
Creamos o copiamos el archivo "jaas.config" también en el paquete "com.test.listeners".

La clase MyContextListener quedaría de esta forma:


package com.test.listeners;
import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
 * Web application lifecycle listener.
 * @author pedrop
 */
public class MyContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        File jaasConfigFile = null;
        try {
            jaasConfigFile = new File(getClass().getResource("jaas.config").toURI());
            System.setProperty("java.security.auth.login.config", jaasConfigFile.getAbsolutePath());
        } catch (Exception e) {
            Logger.getLogger(MyContextListener.class.getName()).log(Level.SEVERE, null, e);
        }
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

Por si a alguien le interesa, existe otra solución en la que no es necesario usar un archivo "jaas.config". Para dar alguna pista, os diré que requiere extender el objeto LoginContext.

Saludos

martes, agosto 16, 2011

Cómo eliminar definitivamente una cuenta en facebook (actualización)

En un post del año 2010 ("Cómo eliminar definitivamente una cuenta en facebook") explicábamos como darse de baja en Facebook (no confundir con desactivar la cuenta).

En dicho post se indicaba una url que -previamente logueados en Facebook- nos permitía borrar la cuenta.

Esa url ha cambiado (y probablemente volverá a cambiar). La nueva url es la siguiente:

https://ssl.facebook.com/help/contact.php?show_form=delete_account

Espero que os sea útil.

miércoles, agosto 03, 2011

Directorios de usuario en Tomcat

Los conozco desde hace ya tiempo, pero nunca tuve la necesidad de usarlos. Estoy hablando de una funcionalidad que los servidores web tienen y consiste en hacer "visible", a través de un navegador Web, el contenido de un directorio de usuario del sistema.

Esta configuración se hace a nivel del elemento host del fichero server.xml, por lo que la configuración aplica para todo el servidor. En este fichero se añade una de las siguientes configuraciones:


<Listener className="org.apache.catalina.startup.UserConfig"
    directoryName="public_html"
    userClass="org.apache.catalina.startup.PasswdUserDatabase" />

El atributo className debería ser org.apache.catalina.startup.UserConfig y el atributo userClass, una de las clases que Tomcat tiene de asignación.

Si usamos un sistema Linux y se dispone de un archivo estándar /etc/passwd legible por la cuenta que ejecuta Tomcat, y ese archivo especifíca el directorio de inicio del usuario, se puede utilizar la clase PasswdUserDatabase.

Se puede cambiar el nombre del directorio (atributo directoryName) por cualquier otro, pero entonces el nombre del directorio debe ser el mismo para todos los usuarios dentro del mismo servidor.

También podemos establecer un directorio base del que colgarán el resto de directorios de usuario. Esto es muy útil para entornos que usan sistemas operativos Windows (donde seguramente colgarán de c:\home):


<Listener className="org.apache.catalina.startup.UserConfig"
    directoryName="public_html"
    homeBase="/home"
    serClass="org.apache.catalina.startup.HomesUserDatabase" />

Una vez arrancado el servidor, deberíamos poder acceder al directorio de los usuarios definidos en el sistema a través de la url:

http://nombre_servidor/~nombre_usuario

Más información en el libro Tomcat 6.0 La guía definitiva.

jueves, julio 28, 2011

Los cánceres de la profesión de informático

Llevo trabajando como informático unos 14 años... De hecho, no sólo trabajo de informático, sino que soy informático, cosa que no todos mis compañeros pueden decir.

Durante todo este tiempo he podido darme cuenta que nuestra profesión no está muy bien valorada ahí fuera. Siempre tenemos una mala fama, que por desgracia, en muchos casos está justificada. Sólo tenemos que ver qué aplicaciones (empresariales) usamos y los problemas que estas tienen.

Si me pongo a pensar en los motivos me vienen a la mente una serie de estereotipos que he podido ver cómo se repetían a lo largo de mi experiencia en los clientes por donde he pasado. Y creo que podría enumerarlos:

Gollum
Es el programador que, muy corto en conocimientos y más aún en ganas de adquirirlos, se aferra a un conocimiento del negocio para hacer que su presencia en el equipo sea imprescindible.
Son personajes poco sociables y nada dados a trabajar en equipo, ya que esto último provocaría que su conocimiento se repartiese en este, cosa que vaciaría totalmente el sentido de su vida.

Valdanito
Gente que a base de palabros técnicos mezclados sabiamente con anglicismos bien administrados, es capaz de convencer al jefe que puede hacer funcionar un Windows'95 en su calculadora.
Son sumamente peligrosos y muy difíciles de evitar, ya que, aunque faltos de conocimientos, los argumentos que dan cuando se les presiona no son descabellados y mezclados estos con sabiduría da la sensación de conocimiento real.
Suelen estar siempre paciendo junto a otro tipo de elemento también muy peligroso... el Suscriptor de PCWorld.

Suscriptor de PCWorld
Este figura suele ser alguien con años en la empresa. Un recauchutado de otro puesto al que, no se sabe muy bien porqué, le acabaron asignando un lugar de mando (o semi-mando) en un equipo de desarrollo.
Esta gente suele ser muy aficionada a llevarse al baño su revista favorita (PCWorld o similar), empaparse de todo lo que allí se suelta y salir de aquel mágico lugar cagando EJBs.
Sip... suele querer poner en práctica cualquier cosa que haya leído, sin importar lo más mínimo la idoneidad de la idea o los conocimientos del equipo, al que compromete y hace caer en grandes faltas en las entregas del producto.

El vegetariano
Este suele ser una consecuencia del anterior. Un personaje que, aunque a veces es un profesional muy válido, le da por alimentarse únicamente de nabos.
No importa lo desmedido del trabajo a realizar en el ridículo tiempo asignado, simplemente se limitará a su dieta y a pasar horas en la oficina tratando de llegar en fechas a la entrega del producto. Eso sí, en las tertulias cafelínas pondrá a parir a su jefe y asegurará por la gloria de su madre que no volverá a quedarse más tarde de las 6.


El jarrón chino
Es un personaje que habita en la oficina. Habita porque en realidad, no hace nada más... salvo adornar y dar ambiente. Llega por las mañanas, atiende su correo, su facebook, su twitter... pasa las horas hasta las 17,30. 
Es en ese momento cuando parece despertar de su letargo y comienza a mandar correos con disculpas peregrinas o solicitando cosas sin sentido. Todo esto lo adereza con un correo (desde casa) a eso de las 23 horas, en el que pone en copia hasta al portero, diciendo todo lo que (supuestamente) ha hecho.
Los auténticos jarrones chinos tienen gran mérito, ya que no ser descubierto es todo un arte.

Estos son los que yo tengo catalogados... ¿cuáles son los tuyos?

viernes, julio 22, 2011

Review SQL Antipatterns


Hace unos días terminé de leer SQL Antipatterns, un libro que desde ya recomiendo y que considero de imprescindible lectura.

El autor hace un repaso a las picias más comunes a la hora de crear los modelos de datos de las aplicaciones.

El libro está dividido en cuatro grandes secciones: Antipatrones de diseño lógico, físico, antipatrones de consulta y lo que él llama Application Development Antipatterns (esto es, higiene general).

Sin duda, la parte más jugosa del libro se encuentra en los antipatrones de deseño lógico. Aquí he de reconocer que, aunque en la actualidad ya no caigo en estos errores antipatrones (mi trabajo me ha costado), sí que en algún momento llegué a usar alguno... como el Jaywalking (evitar los "cruces" de tablas mediante campos que contienen listas de identificadores) y el Entity-Attribute-Value... vamos, el famoso cajón DEsastre. La juventud, que nos hace temerarios.

El libro está escrito en un lenguaje que no usa términos demasiado técnicos que podrían llegar a despistar al lector. Se ha preferido obviar ciertos conceptos (se explican luego, en uno de los apéndices) de bb.dd. para centrar la atención única y exclusivamente en cómo evitar el error.

Los ejemplos están construídos a través de una aplicación de control de bugs. Aunque normalmente no hacen falta para conseguir transmitir el mensaje, están bien enlazados y trabajados. Incluye también una gran cantidad de código SQL.

Lo dicho, esencial para poder construir modelos de datos robustos.

miércoles, junio 29, 2011

Problemas con JDBCRealm en Tomcat6 sobre Ubuntu

Me ha llevado unos días el poder desplegar correctamente una aplicación que usaba un realm para la validación de usuarios.

Una vez configurado los ficheros oportunos en el proyecto (podéis ver una entrada sobre esto aquí), al desplegar la aplicación e intentar acceder a los recursos protegidos por el realm, el servidor me redirigía contínuamente a la página de error del login definida para la aplicación.

El problema, aunque simple, me costó más de tres días de trabajo. El servidor era una instalación limpia de un Apache+Tomcat6+MySQL en una Ubuntu. Esta versión de Tomcat para Ubuntu (y supongo que para todas las distro Linux), no se instala con el formato tradicional de carpetas, sino que aparece instalada sobre distintos directorios. Tengo la impresión de que está predefinida para el uso de distintas instancias sobre la misma instalación.

El motivo de que no me validara el usuario cuando accedía a recursos protegidos era que Tomcat no era capaz de encontrar el driver de MySQL. En esta instalación de Tomcat no existe una carpeta TOMCAT_HOME/common/lib (y si la creas, no la tiene en cuenta), y hay que colocar estos en la ruta CATALINA_HOME, que está establecida por defecto en /usr/share/tomcat6 (tomcat6 es el nombre de mi instancia). Ahí hay que dejar los drivers.

Si se quiere cambiar el valor de CATALINA_HOME, deberemos editar el fichero /etc/default/tomcat6. Este fichero también contiene otras cosas interesantes, merece la pena echarle un vistazo.

Bueno... espero que ayude.

miércoles, abril 20, 2011

Botones de submit dinámicos con Struts2

En ocasiones he tenido la necesidad de poder tener más de un botón de submit en un mismo formulario, teniendo estos distintas acciones, claro está.
6
Esto se puede resolver estableciendo el atributo "method" del elemento s:submit con el nombre de un determinado método que se ejecutará en la clase action destino. Tal que así:


<form action="unaAccion">
<s:submit method="ver" value="Ver"/>
<s:submit method="cancelar" value="Cancelar"/>
</form>


Y luego, en la clase action, establecer los métodos ver y cancelar así:


public class UnaAccion {
public String ver() {
return Action.SUCCES;
}

public String cancelar() {
return Action.SUCCES;
}
}


Pero hay otras ocasiones en las que tenemos más métodos de los que, razonablemente, pordríamo mapear y, además podemos complicarlo con que cada médoto debería recibir un dato del submit pulsado.

Para eso podemos usar la creación de submit dinámicos, más o menos sería así:


<form action="borrarEntrada.action">
<s:iterate value="entradas">
<s:property value="titulo">
<input type="submit" name="borrar[<s:property value='id'>]" value="borrar"/>
<br/>
</s:iterate>
</form>


Luego, el valor del botón pulsado se pordría recoger en la clase action de la siguiente forma:


public class BorrarEntradaAction {

private final Map borrar = new HashMap ();

public String execute () {
super.execute ();

for (Iterator i = borrar.keySet ().iterator (); i.hasNext ();) {
String id = (String) i.next ();
System.out.println (id);
}
}

public final Map getBorrar () {
return borrar;
}
}


Evidentemente, en el for solamente tendremos un item cuyo valor será el id que hemos asignado en la JSP.

Espero que, por lo menos, os ahorre el tiempo que a mí me ha costado encontrarlo :)

viernes, marzo 18, 2011

Duke Nukem Forever... ¡¡por fin!!

Más de una década ha pasado. Por fin, cuando nadie lo esperaba, el juego va a ver la luz este mismo año. Podéis ver los detalles en la web oficial. Se prevé que este disponible en mayo y que se distribuya a través de Steam.

No está recomendado para menores de 18 años, ya que aquellos que conozcáis al personaje, sabréis que es aficionado al sexo y a las palabras subidas de tono. En este sentido, el juego no decepciona XD.

Este es el trailer oficial.

0 A.D. Alpha 4 Daedalus, juego de estrategia open-source

0 A.D. es un juego de estrategia open-source desarrollado por wildfire games. La versión actual se denomina 0 A.D. Alpha 4 Daedalus, indicando su estado de desarrollo.

Es muy similar a otros juegos del mismo estilo a los que ya habréis jugado los aficionados a los juegos de estrategia. El juego está disponible para Windows, Linux y Mac OS. El core está escrito en C++ y como librería gráfica usa OpenGL.

Os muestro a continuación un vídeo sobre el juego para que podáis juzgar si os parece interesante instalarlo.

viernes, enero 21, 2011

Optimizar consultas con iBatis y Joins

Se me ha dado un caso en el que tenía que recuperar una lista con objetos complejos de una consulta. La consulta usaba un join con otra tabla que, además de devolver tipos simples (String) también debía completar un tipo complejo (una lista de objetos).

En concreto, necesitaba conocer las personas activas (con contrato sin finalizar) y los centros de trabajo que estos contratos tenían (1:N persona/contrato y 1:N contrato/centro). Con lo que la consulta me devolvería un registro por cada centro que el contrato tuviera asociado. Es por ello que el bean al que se mapea el resultado contiene objetos simples (Strings con los datos personales) y un objeto complejo (una lista de objetos Centro por cada persona).

Para resolver este "problema", he usado la siguiente "estrategia" (las consultas así como las relaciones entre tablas, se han simplificado para su mejor entendimiento):

<resultmap id="selectPersonasContratoActivoResult" class="persona" groupby="idContrato">
<result property="idPersona" column="ID_PERSONA">
<result property="nombre" column="NOMBRE">
<result property="idContrato" column="ID_CONTRATO">
<result property="centros" resultmap="selectCentrosContratoResult">
</result>

<resultmap id="selectCentrosContratoResult" class="centro">
<result property="idCentro" column="ID_CENTRO">
<result property="nombre" column="NOMBRE">
</result>

<select id="selectPersonasContratoActivo" resultmap="selectPersonasContratoActivoResult"> </select>

<select id="selectCentrosContrato" parameterclass="int" resultmap="selectCentrosContratoResult"> </select>

Lo importante en este código es las siguientes líneas:


<resultmap id="selectPersonasContratoActivoResult" class="persona" groupby="idContrato">

... donde indicamos cuál será la clave por la que agrupemos los resultados que se mapearán a la lista "centros", y esta otra línea


<result property="centros" column="ID_CONTRATO" resultmap="selectCentrosContratoResult">

... ya que aquí se indica que el objeto complejo (lista) "centros" se rellenará atendiendo al resultMap selectCentrosContratoResult.

De esta forma, con una sola consulta conseguimos completar un bean que contiene una lista de otro bean.

Espero haberme sabido explicar bien. Si no es así, siempre se puede consultar esta página

lunes, enero 10, 2011

Convertir a entero un doble redondeando su parte decimal

Hola,

Hoy tenía que redondear un número decimal (double) a un entero teniendo en cuenta su parte decimal y si esta era igual o mayor a 0,5, añadir uno a su parte entera.

Parece simple, pero dar con una solución que se adaptase a mi necesidad me ha llevado un ratín.

Para ello he usado la clase java.text.DecimalFormat.

Esta clase es perfecta para "decorar" nuestra salida de números decimales, pero también funciona muy bien para solucionar el problema de elimiar la parte decimal de un número redondeando su parte entera.

Es simple. Sólo tenemos que pasar un patrón en el constructor de la clase donde no demos opción a mostrar decimales (esta clase, al igual que SimpleDateFormat, nos convierte nuestros números en cadenas). Y después usar su método "format". Un ejemplo:


DecimalFormat df = new DecimalFormat ("##");
int diasVacaciones = Integer.parseInt (df.format ((diasTrabajados) * 30d / 360d));


El resultado será un número entero redondeado en caso de haber sido necesario.