Tras casi una semana sin publicar nada, toca hacer un post interlinguístico que va a tocar los palos de Java y de Ruby, es más, vamos a ver como podemos hacer aplicaciones configurables en ambos lenguajes.
¿Por qué tener aplicaciones configurables?
Es bastante común tener aplicaciones configurables que nos permitan modificar parámetros de la misma 'en caliente/on the fly' sin tener que recompilar todo el código. No es de recibo tener que recompilar toda una aplicación y parar todo un sistema en producción única y exclusivamente por el hecho de modificar un valor, como puede ser por ejemplo el IVA que se aplica actualmente o la base de datos que estamos usando (ahí habría que preveer otras cosas pero podría hacerse en caliente también).
Properties
A ver si os gusta la solución que os propongo. Introducir todos estos parámetros hard-coded (que están grabados a fuego en la aplicación) y sacarlos para un fichero que más o menos podemos considerar estándar y del que los recogeremos y podremos modificarlos a nuestro antojo.
Para hacer esto, existen en Java unos ficheros que se llaman properties y que el propio lenguaje tiene unas funciones para recoger esta información de ellos y utilizarla.
Éstos ficheros lo único que contienen dentro es una línea por cada campo en forma de pares clave,valor. En el post referido a Log4J definimos un archivo Properties para la configuración de los loggers.
Definición de un archivo Properties:
config.properties
#iva aplicable
IVA=18
#descuento del producto
descuento.producto=2
Uso del archivo:
He creado una aplicación en Eclipse muy sencilla que usa un properties para almacenar el descuento de un producto y el iva que hay en el momento.
Proyecto de Eclipse
Como podemos comprobar en el ejemplo, podríamos cambiar los valores del properties mientras se está ejecutando la aplicación puesto que se carga el fichero cada vez que hacemos una llamada al Helper.
YAML
En el caso de Ruby, existe algo parecido a estos properties, es el lenguaje YAML (YAML Ain't Another Markup Language) y los ficheros .yml donde también definiremos estos pares clave,valor pero además nos permitirán añadir jerarquías que de cara a organizar información que nos vendrá de lujo debido a la facilidad que tienen estos ficheros para crecer.
Definición de un archivo YAML:
config.yml
#iva aplicable
producto:
iva: 18
#descuento del producto
descuento: 2
Uso del archivo:
Para usar el archivo yml, he hecho una mini aplicación (igual que la de Java) donde se ve el uso del yml.
Proyecto en Ruby
Podría ser interesante para aquél que no sepa nada de Ruby, para perderle el miedo que mirara un poco el código y viera que es bastante sencillo.
Otros usos
Como viene siendo habitual en el blog, los ejemplos que se presentan intentan ser lo más sencillos posible para que todo el mundo pueda entenderlo y hacer que le pique el gusanillo a cada uno. En una aplicación un poco más seria, el uso de estos properties estaría relegado a definir en ellos las bases de datos (ip del servidor, usuario, contraseña, base de datos, consultas, ...) , configuración de un servidor jboss, el espacio de nombres de Java JNDI ...
Con esto finaliza el artículo relativo a parametrizar aplicaciones, cabe destacar que YAML no sólo se utiliza para parametrizar aplicaciones (en Ruby mayormente sí) y es multilenguaje. En la próxima entrega espero poder hablar sobre pruebas unitarias y concretamente de JUnit y el módulo Test de Ruby.
Mostrando entradas con la etiqueta Java. Mostrar todas las entradas
Mostrando entradas con la etiqueta Java. Mostrar todas las entradas
martes, 20 de diciembre de 2011
lunes, 12 de diciembre de 2011
Log4J, aprendiendo a hacer trazas
Comenzamos esta andadura 2.0 con Java, para calentar motores aprenderemos a utilizar una herramienta muy útil que dará un valor añadido a nuestras aplicaciones. Log4J (Apache, Log for Java, http://logging.apache.org/log4j/1.2/) es una forma fácil de tener un sistema de logging que nos permitirá "controlar" y monitorizar nuestras aplicaciones de forma transparente al usuario y sobretodo de una forma mucho más elegante que los típicos System.out.println de marras que son muy sencillos de insertar pero siempre podemos caer en el error de que se nos quede alguno sin borrar de nuestro código y eso da bastante mala imagen de cara a por ejemplo entregar una práctica (los mensajes aparecerán por consola) o presentar un trabajo más profesional.
Para todo lo relacionado con Java que aparezca en este post siempre se utilizará Eclipse como IDE debido a que es el más utilizado y gratuito, el proceso para utilizar otros (NetBeans por ejemplo) debería de ser análogo.
Obteniendo el JAR
Antes de nada debemos de ir a este enlace y descargarnos el siguiente zip que contiene el jar:
en este enlace, pulsaremos sobre la versión HTTP y se nos descargará. Una vez lo tengamos en nuestro poder, descomprimiremos únicamente el archivo log4j-1.2.16.jar que es el que tiene la funcionalidad de Log4J.
Configurando el proyecto
Ahora abriremos Eclipse, y crearemos un nuevo proyecto (File->New..->Java Proyect) , para este caso le llamaremos PruebaLog4J (por ejemplo). Una vez tengamos creado nuestro proyecto, añadiremos una carpeta "lib"(New->Folder) que dependerá del proyecto y en la cual pegaremos (o descomprimiremos) el jar antes mencionado. Con el jar ya descomprimido en la carpeta "lib", haremos click derecho sobre el propio jar y en el ítem "Build Path" presionaremos sobre "Add to Build Path". Automáticamente se añadirá a nuestro path y podremos utilizarlo en nuestras clases.
| Estructura final del proyecto |
Creando nuestra clase con Log4J
En este punto vamos a crear una clase donde probaremos los diferentes niveles de log que nos proporciona Log4J. Comenzaremos creando un paquete "test" (nunca utilizar default package) donde introduciremos una clase de prueba, por ejemplo PruebaLog4J y seleccionamos que nos genere el main también para ahorrarnos un poco en código.
Ya tenemos la clase sobre la cual hacer logging, para utilizar Log4J necesitaremos crear una instancia en todas las clases donde vayamos a usarla de la siguiente forma:
Log4J por defecto utilizará una especie de Singleton (algún día escribiré sobre patrones) que se creará solo una vez y te dará la instancia cuando se necesite. Al método getLogger, le pasaremos siempre el nombre de la clase en la que estemos .class para que nos "personalice" los mensajes de log que nos mostrará.
Poseemos una variable logger, ¡usémosla!
Vamos a comenzar con lo básico, dentro del método main introduzcamos esto:
Con la sentencia de encima, conseguimos meter ese mensaje entrecomillado en nuestro log.
Ahora toca hacerlo funcionar...
Si intentamos ejecutar lo que hemos hecho hasta ahora, nos mostrará un error porque falta configurar cómo queremos que Log4J nos grabe los logs.
Configurando Log4J
Hay 2 formas de configurarlo, una más básica y que no quiero ver aquí porque nos interesa más entrar en cómo hacer una configuración más a medida y que cada uno la prepare a su gusto.
Para configurarlo, tenemos que crear un archivo log4j.properties (New->File) dentro de "src" para que la biblioteca lo reconozca por defecto y dentro introduciremos el siguiente texto:
# Niveles de Log
log4j.rootLogger=trace, stdout, R
# Configuracion del Appender de la consola
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
# Appender del fichero
log4j.appender.R=org.apache.log4j.RollingFileAppender
# Path and file name to store the log file.
log4j.appender.R.File=./logs/testlog4j.log
log4j.appender.R.MaxFileSize=500KB
# Manten solo un fichero
log4j.appender.R.MaxBackupIndex=1
# Plantilla del fichero
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d - %c - %p - %m%n
Lo seguido de # son comentarios.
Vamos a intentar entender un poco qué definimos en estas líneas.
A grosso modo, un fichero .properties es un fichero de configuración que se basa en definir líneas de tipo clave=valor.
La primera línea útil que nos encontramos es la siguiente:
log4j.rootLogger=trace, stdout, R
Aquí estamos definiendo el log "maestro", que hará logging sobre todas las clases, le estamos indicando el nivel traza, por salida estándar y que lo llamaremos R.
Cada vez que veamos la R en el fichero, estamos haciendo referencia a este log que hemos definido aquí.
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
Definimos un appender para la consola.
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
Definimos que layout (estilo) llevará nuestro log y debajo definiremos el patrón que queramos que siga.
log4j.appender.R=org.apache.log4j.RollingFileAppender
Definimos otro appender con nuestro ROOT, queremos que sea un RollingFileAppender, eso quiere decir que queremos que nos cree un fichero de texto con el log (opción fundamental de un log).
log4j.appender.R.File=./logs/testlog4j.log
log4j.appender.R.MaxFileSize=500KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d - %c - %p - %m%n
Aquí definimos lo relacionado con el log que hemos definido como ROOT, la ruta que tendrá el archivo (lo ideal es mantener esta estructura), el tamaño máximo que tendrá el archivo, los backups que quieres tener del fichero, qué layout seguirá y qué patrón seguirá.
Podemos añadir tantos appenders como queramos y para que salgan por diferentes archivos (esto sería lo ideal para tener un control total de nuestro programa, pero no es realmente necesario).
Con todo el fichero properties definido (y espero que más o menos entendido), ya podemos ejecutar nuestra aplicación, y así podemos ver los resultados.
Veremos por consola un mensaje del tipo:
y en la carpeta logs aparecerá el fichero pruebalog4j.log :
Ya tenemos nuestro log funcionando. Cada mensaje que queramos poner en nuestra aplicación, tendremos que hacer una sentencia como la anterior del tipo:
logger.info("Otro mensaje para el log");
Recuerden que en cada clase hay que obtener el logger para usarlo.
Niveles de Log
Ahora que ya sabemos como hacer nuestros logs, pasemos a ver qué es esto de los niveles de logging.
Existen 5 niveles en la jerarquía de logging que son de menor a mayor dureza: DEBUG, INFO, WARN, ERROR y FATAL.
DEBUG: Usaremos este nivel cuando queramos ver por dónde va la traza, así tendremos un control exhaustivo de nuestros desarrollos.
INFO: Aquí podemos definir información que puede ser útil del funcionamiento del programa, como por ejemplo decir que se están tomando correctamente unos parámetros.
WARN: Utilizaremos este nivel para mostrar un funcionamiento anómalo de nuestra aplicación pero que no afectará al funcionamiento de la misma.
ERROR: Utilizaremos este para decir que ha ocurrido un error.
FATAL: Este es el nivel superior de la jerarquía y con él definiremos un error fatal de la aplicación que llevará a la finalización inmediata de la misma.
Que estos niveles siguen una jerarquía quiere decir que si definimos un log con nivel DEBUG se mostrarán todos los mensajes que definamos, desde los logger.debug("loquesea"); hasta los logger.fatal("estovamal");
Si por el contrario definimos un nivel FATAL, solo aparecerán los logger.fatal("estorompió");
Así mismo, esto que acabo de escribir sirve para orientarse de cómo escribir diferentes niveles de log en nuestra aplicación.
Finalizando
Ya hemos terminado, sólo queda que cada uno mire los patrones de cómo configurar los layouts y esa no es tarea fácil pero seguro que será muy reconfortante una vez se tiene definido como uno quiere puesto que hay infinidad de opciones. Aquí estan todas.
Al principio comenté que a diferencia de los System.out.println el log podía quitarse para no dejar rastro en la ejecución, aquí entra otra vez el fichero properties y los niveles de la jerarquía. Lo ideal es poner un nivel INFO cuando se pasa a producción y tan sólo en el fichero, quitaríamos el appender de la consola. El código permanecerá en nuestros ficheros que una vez haya que mantener ese código, solo tendremos que reestablecer el nivel DEBUG.
Pues hasta aquí el primer post-tutorial de cómo conseguir definir nuestro propio sistema de Logging, espero que os haya servido de ayuda y ojalá alguien me comente sus experiencias y qué patrones ha seguido en sus configuraciones. Para ello, tenéis a vuestra disposición mi cuenta de Twitter @Minikisto y los comentarios de este mismo post. En la próxima entrega, probablemente nos centremos en JUnit y unas nociones básicas de estructuración de la información de un proyecto.
Fuentes del artículo: http://logging.apache.org/log4j/1.2/manual.html
sábado, 10 de diciembre de 2011
Presentación
¡Hola! primero déjenme presentarme. Soy Daniel Machado Fernández y estoy cursando tercero en la Ingeniería Técnica en Informática en la Universidad de Oviedo a la par que estoy realizando el Proyecto Fin de Carrera (PFC).
Bueno, ya me conocen, déjenme presentarles ahora el blog. Diario de un Proyectante pretende ser un cajón de sastre donde intentaré comentarles qué problemas me voy encontrando a lo largo de la realización de mi PFC, pero no solo eso, también me gustaría escribir sobre buenas prácticas a la hora de desarrollar software (sobretodo a utilizar las herramientas adecuadas). No quiero limitarlo a estos 2 puntos (que ya sería bastante), me gustaría poder escribir sobre lo que me apeteciera, sobretodo cosas que fueran útiles, que no se enseñan en la carrera de informática o al menos que no se enseñan en ninguna asignatura obligatoria/troncal y que si se quieren aprender se tienen que hacer por cuenta propia.
Quiero que quede claro que en este blog se va a hablar sobre Ruby y Java dado que este último es el lenguaje base que se utiliza en mi Universidad y Ruby es el lenguaje que he escogido para realizar mi PFC por lo que son los lenguajes de los que más puedo hablar.
No quiero que piensen que soy un experto Java ni mucho menos, ya he dicho que soy estudiante por lo que probablemente todo lo que les cuente ya lo conozcan pero eso no quiere decir que estas cosas no haya tenido que buscarlas en algún momento de la carrera, que me han sido útiles y que suelo utilizar en mi día a día.
Por último para los que tengan curiosidad, voy a dejarles en este mismo post unos enlaces a tutoriales que he hecho en algún momento de mi vida sobre Java y Ruby que me han sido realmente útiles.
Java: Aprende Java como si estuvieras en Primero, de Tecnum
Ruby: Why's (poignant) Guide to Ruby (Inglés)
Learn Ruby (Inglés)
Guía del usuario de Ruby
Si quieren contactarme, pueden hacerlo en Twitter .
Suscribirse a:
Entradas (Atom)