No es un bug, es una característica no documentada

viernes, 28 de julio de 2017

Tutorial Maven en Eclipse

12:02 Posted by Jose Ignacio Claver Paules No comments
Apache Maven Java Logo
De normal, cuando realizamos un proyecto Java si es pequeño nosotros mismos podemos hacer las actividades típicas de la construcción de software.
  • Instalar las librerías necesarias para nuestro proyecto en el classpath
  • Correr los casos de test
  • Crear la documentación del código fuente
  • Compilar código fuente
  • Empacar el código compilado en JAR
Pero, ¿qué sucede conforme nuestro proyecto va creciendo y se va agregando más gente a él? Pues que podemos perder el control del mismo y es más plausible cometer errores humanos en la construcción del programa. Para eso está Maven.

miércoles, 19 de julio de 2017

Resolver sudokus en Java

13:07 Posted by Jose Ignacio Claver Paules No comments
El otro día estaba haciendo el sudoku del periódico y me plantee la siguiente duda. ¿Cómo sería un programa que te resolviese el sudoku automáticamente?

Para el que no lo sepa, un sudoku es un pasatiempo japonés consistente en rellenar un tablero de 9x9, que a su vez está divido en secciones de 3x3, con números del 1 al nueve de tal manera que ninguno de ellos puede estar repetido en ninguna fila, columna o secciones.
Como curiosidad, sabed que el problema de un sudoku sólo se considera bien planteado si su solución es única, consiguiéndose esto sólo si, como mínimo, hay ya preestablecidas 17 cifras dentro del tablero (Wikipedia insified).

Dicho esto, vayamos a la resolución del problema.
La idea que se me ocurrió, y que luego he ido leyendo que es la más sencilla de implementar, es la del algoritmo de marcha atrás.

domingo, 16 de abril de 2017

Cómo leer ficheros CSV con Java

19:53 Posted by Jose Ignacio Claver Paules No comments
Un CSV es un fichero de texto plano que consta de varios valores separados por comas (o punto y coma, según el caso), de modo que para procesar este tipo de ficheros en Java en principio debería bastar con leer el archivo línea a línea y partir las cadenas de texto por el separador correspondiente.

Por ejemplo, si tenemos la siguiente línea, sería bastante sencillo de procesarlo:
Programando, a, pasitos
Pero sin embargo, si nos encontramos alguna de las siguientes entradas:
"Programando a pasitos", "Claver, Inazio", "CSV, Java"
ya es más complicado, al formar las comas parte de la cadena de texto que queremos extraer. Y si además tenemos en cuenta que las comillas también pueden ser parte de ese valor, se complicaría, teniendo que poner dobles comillas para indicar que es parte del valor de una cadena.
"Programando a pasitos", "Claver, Inazio", """Leyendo CSV"" en Java"
Vamos a ver como procesar los dos tipos de CSV anteriores, el sencillo y el complejo.

domingo, 26 de febrero de 2017

Configurar Virtual Host Apache en Ubuntu

21:39 Posted by Jose Ignacio Claver Paules , No comments
Hace poco tiempo se estropeo mi ordenador y decidí que era el momento idóneo para dar el salto a una plataforma Linux. He tonteado mucho con ello pero nunca lo había tomado realmente en serio y, por considerarme 'primerizo' opté por la última versión LTS de Ubuntu, la 16.04.

El cambio no ha sido muy grande en rasgos generales, pero cuando te orientas a algo más especializado, como la programación web por ejemplo, si que he tenido ciertas dificultades para dejar todas las configuraciones como yo quería. Aquí voy a explicar como hacer una de ellas, los host virtuales de Apache.

Apache es el servidor web más popular actualmente y permite una flexibilidad asombrosa a la hora de realizar sus configuraciones. Como tengo varios proyectos en mente, me interesa poder emular varios dominios desde mi propio portátil directamente, trabajando como si de la raíz de la página web se tratase. Ahí es donde entran los virtual host.

Un host virtual es un mecanismo que permite tener funcionando más de un sitio web en una misma máquina. Estos sitios web podrán estar basados en diferentes direcciones IP o bien en distintos nombres de dominio. Ésta segunda manera es la forma con la que quiero trabajar.

martes, 20 de diciembre de 2016

Envío de mails en Python

10:53 Posted by Jose Ignacio Claver Paules No comments
Ésta será una entrada rápida.

Os pongo en situación. A partir de hoy en el trabajo debemos fichar diariamente a base de enviar un correo electrónico cuando empecemos cada jornada, tanto por la mañana como por la tarde. Los mails deberán llevar como cabecera nuestro nombre de usuario, la fecha actual en formato DDMMAA y la letra M o T dependiendo si es por la mañana o por la tarde, y en el cuerpo del mensaje deberá llevar un texto en concreto.

Bien, el caso es que soy un poco perro y, como pretendo quedarme bastante tiempo en esta empresa, no me apetece mucho tener que estar escribiendo todos los días, dos veces al día, el mismo correo. Es una tarea repetitiva que se puede automatizar fácilmente.

Y aprovechando que estoy intentando aprender Python, ¿qué lenguaje mejor para programar ese script que el de la serpiente? Leyendo un poquito vi que enviar mails con Python es tremendamente sencillo, enseguida lo veréis.

El script debía constar de dos partes, una que extrajera la fecha del sistema y la formateara como yo quisiera, y la segunda que creara un mail y lo mandase.

El código completo es el siguiente:
# -*- coding: utf-8 -*-
import smtplib
import time

'''
Calcular la hora
'''
if (time.strftime("%p") == "AM"):
 tipoHora = "M"
else:
 tipoHora = "T"

'''
Crear datos de envío
'''
remitente   = "Inazio <remitente@mail.com>"
destinatario  = "destinatario@mail.com"
asunto    = "xxxxxxxxxx" + time.strftime("%d%m%y") + tipoHora
mensaje   = "Aquí va el contenido de nuestro mensaje"

'''
Preparo el mail y agrego campos
'''
email = """From: %s 
To: %s 
MIME-Version: 1.0 
Content-type: text/html 
Subject: %s 
 
%s
""" % (remitente, destinatario, asunto, mensaje)

try:
 smtp = smtplib.SMTP('smtp.mail.com')
 smtp.login('ignacio.claver@movicoders.com', 'G62iji3@')
 smtp.sendmail(remitente, destinatario, email)
 smtp.quit()
except Exception as e:
 print(e)
Vamos a verlo paso a paso para comprender bien lo que hace.

¿Qué información necesitamos conocer?

Antes de nada, debemos tener claro qué es lo que necesitamos.
  1. Correo electrónico del remitente
  2. Correo electrónico del destinatario
  3. Dirección del servidor SMTP para envíar el mensaje
  4. Asunto y cuerpo de nuestro mensaje
Sabiendo eso, lo primero que haremos será importar las librerías necesarias, que afortunadamente se incluyen en el paquete por defecto. Son time para trabajar con tiempos, y smtplib para envío de correos electrónicos. Además agregaremos nuestra consabida cabecera de utf-8
# -*- coding: utf-8 -*-
import smtplib
import time
Ahora viene la parte en la que trabajaremos con la fecha y hora.
La hora se captura con la función time.strftime() pudiendo pasarle varios parámetros para imprimirla en cadena de texto como deseemos. A saber:

Información extraída de Python Diario.
Por lo tanto, como quiero construir una cadena que sea DDMMAA y si es por la tarde o por el día, primero averiguaré si es AM o PM y luego concatenaré el resultado en un String.
if (time.strftime("%p") == "AM"):
 tipoHora = "M"
else:
 tipoHora = "T"

'''
El asunto debe ser mi nombre de usuario, más la fecha y si es mañana o tarde. Ej: xxxxxxxxxxxx201216M
'''
asunto    = "xxxxxxxxxx" + time.strftime("%d%m%y") + tipoHora
Solo nos queda crear la información que insertaremos en el mail. Lo podemos hacer de la siguiente manera, a través de la sustitución de parámetros indicados en una cadena de texto.
email = """From: %s 
To: %s 
MIME-Version: 1.0 
Content-type: text/html 
Subject: %s
 
%s
""" % (remitente, destinatario, asunto, mensaje)
Y ahora trabajaremos configurando nuestro servidor, siempre dentro de una sección try / except.
try:
 smtp = smtplib.SMTP('smtp.mail.com')
 smtp.login('ignacio.claver@movicoders.com', 'G62iji3@')
 smtp.sendmail(remitente, destinatario, email)
 smtp.quit()
except Exception as e:
 print(e)
Lo primero es establecer la dirección de nuestro servidor SMTP para posteriormente usar. Después nos loguearemos usando el correo electrónico y la contraseña, y posteriormente usamos la función sendmail pasandole los parámetros de remitente, destinatario y el email a enviar, que establecimos anteriormente.
Nota: Según la configuración del servidor SMTP a veces no es necesario establecer usuario y contraseña.

Con todo eso ya estamos listos para generar el mail. Bastará con lanzar la aplicación desde la consola de Python e ir a revisarlo a nuestro cliente de correo electrónico. Si ha habido algún error se mostrará en la consola desde la que hemos lanzado el programa.


Si a vosotros no os llega a la bandeja de entrada deberíais revisar la sección de SPAM.

martes, 13 de diciembre de 2016

Aprendiendo Python (VII). Docstrings

0:23 Posted by Jose Ignacio Claver Paules No comments
Python es un lenguaje que se considera autodocumentado por su sencillez a la hora de ser leído. Ahora bien, cuando trabajamos en un proyecto que va creciendo en dificultad, los comentarios son dios y nosotros sus fieles y acérrimos seguidores. Nunca se pasa tan mal como cuando heredas un proyecto sin una línea de comentarios, ni un punto y coma de documentación.

Lo ideal es crear una API, que describa que es, que hace, cada objeto. ¿Qué sucede? Que a la larga es difícil de mantener, da pereza, etc.
Y ahí es cuando Python entra con su maravilloso docstrings.

Esta documentación tiene una serie de reglas, a saber:
  • Cualquier clase, función o método puede tener un string Python estándar que tiene que localizarse en la primera línea después de la definición (la línea que termina con dos puntos).
  • Ésta línea deberá estar identada al mismo nivel que el código que contenga la clase, función o método.
  • Debe explicar los parámetros que no queden muy claros
  • En caso de que se retorne algún valor también deberá indicarse
Es decir, que nuestra clase que llevamos trabajando en las anteriores entradas quedaría tal que así:
class NombreDeLaClase:
    '''
    Establece una fecha basada en el día y el mes
    '''
    
    def __init__(self, dia, mes):
        '''
        Inicializa la nueva fecha
        Params:
            - dia. Entero indicando el día de la fecha
            - mes. Entero indicando el mes de la fecha
        '''
        self.nueva_fecha(dia, mes)
        
    def nueva_fecha(self, dia, mes):
        '''
        Establece una nueva fecha
        Params:
            - dia. Entero indicando el día de la fecha
            - mes. Entero indicando el mes de la fecha
        '''
        self.dia = dia
        self.mes = mes
        
    def reiniciar(self):
        '''
        Reinicia la fecha a un valor por defecto
        Params:
            - 1. Entero. Día
            - 1. Entero. Mes
        '''
        self.nueva_fecha(1, 1)
        
    def diferencia_mes(self, otra_fecha):
        '''
        Devuelve la diferencia de meses entre dos fechas
        Params:
            - self. Nuestro objeto
            - otra_fecha. Objeto NombreDeLaClase inicializado
        Returns:
            - Entero indicando la diferencia de meses
        '''
        if (self.mes > otra_fecha.mes):
            return self.mes - otra_fecha.mes
        else:
            return otra_fecha.mes - self.mes
Ahora guardaremos el archivo con un nombre de nuestra elección. En mi caso, ejemploDocstrings.py.
Nos vamos a la consola de comandos y lanzamos nuestro programa en modo interacción con el siguiente comando
python -i ejemploDocstrings.py
Nos aparecerá un prompt esperando nuestros comandos, cosas que indica que nuestra clase ya se ha cargado y, si queremos ver el docstring en formato API que nos genera Python, escribiremos
help(NombreDeLaClase)
y veremos como automaticamente nos aparece un documento con los comentarios que hemos creado


Al poder crearse tan sencillamente, incluso podemos crearnos un script que con cada actualización nos genere la documentación de nuestro proyecto, para tenerlo constantemente actualizado.

Pronto regresare con una nueva entrada

sábado, 10 de diciembre de 2016

Aprendiendo Python 3 (VI). Orientado a objetos (II). Inicialización

18:37 Posted by Jose Ignacio Claver Paules No comments
Python, a diferencia de la mayoría de lenguajes orientados a objetos, no tiene un constructor que cree e inicialice los objetos, sino que los tiene separados, por una parte el constructor que no suele usarse salvo en casos puntuales, y por otra el inicializador.
En este último es en el que vamos a centrarnos en esta entrada.