domingo, 6 de noviembre de 2011

Los Metodos repaint(), paint() y update()

Muchos programadores se confunden con estos tres metodos, esto se debe a que estan disenados para trabajar en una amplia variedad de circunstancias e interactuan de una manera no tan obvia.
Esto sucede en varios contextos de Java pero en la promgracion de GUI'S es donde es mas evidente. Los disenadores de Java querian que cualquier programa pudiera correr en cualquier maquina que tuviera una Java VM.
Por lo tanto, un programa en particular podria estar ejecutandose en una maquina de escritorio o un portatil, o una ipad o en un telefono. Esto representa un desafio para el disenador que use AWT Tambien hace que el trabajo de un programador novato sea mas complicado de lo que podria ser. Asi son las cosas.
Evolucion del sistema de pintado en swing
Cuando el API original de AWT fue desarrollado para el JDK 1.0, unicamente existian componentes pesados ("heavyweight") Esto obligo al AWT a depender del subsistema de pintado nativo de cada plataforma. Este subsistema se hizo cargo de los detalles tales como la deteccion de danos, el calculo del clip, y el ordenamiento de componentes. Con la introducion de los componentes ligeros en JDK 1.1 el AWT necesito implementar el proceso de pintado para los componentes ligeros. En consecuencia, hay diferencias sutiles en la forma del pintado entre los componentes ligeros y los pesados.
Despues del JDK 1.1 cuando el toolkit de Swing fue liberado, definio su forma de pintar los componentes. En su mayor parte, el mecanismo de pintado se asemeja a la del AWT. Pero tambien presenta algunas diferencias en el mecanismo, asi como nuevas APIs que hacen mas facil el proceso de pintado.
Pintando en AWT
Para comprender como el API AWT realiza el proceso de pintado, vamos a conocer las razones por las que se dispara una accion de pintado en una ventana. En AWT, hay dos tipos de operaciones de pintado: disparados por el sistema
1) public void update(Graphics g)
Rellena el area dibujable de un componente con su color de fondo y entonces llama a paint(Graphics g) del objeto. Por lo tanto, el parpadeo que viene de volver a dibujar el fondo una y otra vez a veces puede ser fixeado sobreescribiendo el metodo update( )



Referencia

https://www.oracle.com/java/technologies/painting.html

domingo, 23 de octubre de 2011

Como decirle a netbeans donde esta Java

Ayer en la tarde decidí desinstalar Java para volver a instalarlo, una instalación mas limpia, bien pues hoy he lanzado netbeans y me arroja el siguiente error Cannot find java. Please use the --jdkhome switch.

Entonces me dije, oooh netbeans no sabe que he cambiado la instalación de java, y es así como me di la tarea de buscar en donde se configura, en donde poder yo decirle a netbeans cual es el path de mi java.

Netbeans tiene un properties en el directorio etc el archivo se llama netbeans.conf y la propiedad se llama netbeans_jdkhome

El directorio etc se encuentra es el directorio de instalación de Netbeans, en mi yo tengo Linux/Ubuntu y este se encuentra en /home/rlopez/netbeans-6.9.1


Pero no es la única forma, el lanzador de NetBeans te permite lanzar netbeans como varias opciones, las más relevantes:

General options:
  --help                show this help
  --jdkhome <path>      path to JDK
  -J<jvm_option>        pass <jvm_option> to JVM

  --cp:p <classpath>    prepend <classpath> to classpath
  --cp:a <classpath>    append <classpath> to classpath

  --fork-java           run java in separate process
  --trace <path>        path for launcher log (for trouble shooting)

  --console suppress    supppress console output
  --console new         open new console for output



Por ejemplo, si queremos especificar el path del jdk home, podemos ejecutar Netbeans de la siguiente forma (en Windows).

Abrimos una shell de Windows y vamos al directorio bin de Netbeans
C:\devel\tools\NetBeans 8.2 RC\bin 

ejecutamos el comando
netbeans64 --jdkhome %JAVA_HOME%

donde %JAVA_HOME%  es nuestra variable de entorno, asegúrate que la variable de entorno es correcta,

Como instalar Apache Tomcat 7.0 en Ubuntu 10.04

En esta entrada no explicaré lo que es tomcat, quizas mas adelante escriba acerca de ello.

Lo primero es descargarnos una distribucion, en mi caso la version 7.0


Yo descargue la version .zip

Una vez descargado lo descomprimimos, y luego lo copiamos al directorio donde lo dejaremos, en mi caso lo dejare en /usr/local/apache-tomcat-7

para ello abrimos una terminal y ejecutamos

sudo mv /home/betito/Descargas/apache-tomcat /usr/local/apache-tomcat-7

Bien ahora vamos a configurar las variables de entorno (he escrito una entrada referente a ellas)

Normalmente suelo escribir las variables de entorno en el archivo /etc/bashr.bashrc pero ahora mostrare otra manera de definir variables de entorno, esto es escribiendolas en el archivo /etc/enviroment Cual es el lugar correcto? en realidad no lo se pero prometo investigarlo mas adelante.

Entonces ejecutamos en nuestra terminal

sudo gedit /etc/enviroment

Y escribimos al final
CATALINA_BASE="/usr/local/apache-tomcat-7"
CATALINA_HOME="/usr/local/apache-tomcat-7"

Guardamos y salimos.

Por ultimo le damos permisos de usuario al startup.sh que es el script que corre apache tomcat y a catalina.sh , tecleamos en la terminal.

cd /etc/local/apache-tomcat-7/bin
chmod +x startup.sh
chmod +x catalina.sh


sábado, 22 de octubre de 2011

Como instalar java desde cero en Ubuntu

Personalmente me gusta y prefiero instalar java manualmente y no desde el centro de Software de Ubuntu, esto por que me permite explicitamente instalarlo en el directorio que deseo.

Primero desinstalo completamente el OpenJDK ya que no me es util e incluso me genera conflictos en mi desarrollo.

Para ello abro mi terminal y ejecuto lo siguiente

sudo aptitude purge openjdk-6-jre

O la version que tengas.

Una vez removido vamos a descargar el JDK de Sun



Buscamos de la lista la siguiente version
Linux x86 - Self Extracting Installer81.20 MB jdk-6u27-linux-i586.bin


Por defecto lo descargara en nuestro directorio de Descargas (/home/betito/Descargas) en mi caso.

En mi caso lo quiero instalar en /usr/local/install_dir Para efectos de comodidad voy a copiar el archivo descargado al directorio /usr/local/

Me voy a descargas:
cd /home/betito/Descargas

Me logueo como sudo
sudo su

copiar el archivo descargado
mv jdk-6u27-linux-i586.bin /usr/local/

me voy a /usr/local/
cd /usr/local/

asignar permisos de ejecucion
chmod +x jdk-6u27-linux-i586.bin

ejecutar el binario
./jdk-6u27-linux-i586.bin

Ahora solo nos queda configurar las variables de entorno JAVA_HOME y PATH
sudo gedit /etc/bash.bashrc


Y al final agregar las siguientes lineas
export JAVA_HOME=/usr/local/jdk1.6.0_27
export PATH=$PATH:$JAVA_HOME/bin

Para asegurarnos que las variables de entorno esten seteadas correctamente, ejecutamos lo siguiente en la terminal
set|grep CATALINA_HOME

para actualizar las variables de entorno en la terminal tipear
source /etc/bash.bashrc



Y con ello estara instalado Java





domingo, 16 de octubre de 2011

Interfaces de Usuario Swing con Hilos

En esta entrada quiero compartir algunos problemas de subprocesamiento multiples  (ejecución de tareas en paralelo) relacionados con la programacion de interfaces graficas de usuarios.

Hilos en Swing
Una de las razones de usar hilos en tus aplicaciones es la de hacer que tu aplicacion sea mas interactivo. Cuando tu aplicacion realiza una tarea que requiere mucho tiempo, más de dos segundos a mi juicio, entonces debes ejecutar la tarea en otro hilo para evitar que la interfaz de usuario se quede "congelada".

Hay un hilo diseñado exclusivamente para pintar la interfaz grafica y para procesar los eventos del usuario, este hilo es conocido como el EDT (Event Dispatch Thread), todo código que requiera manipular componentes swing debe ser ejecutado en este hilo, de no hacerlo así te puedes llevar varias sorpresas. Swing es not thread safe. Es decir, la mayoria de los metodos de las clases Swing no son sincronizados. Si tu intentas manipular los elementos de la interfaz grafica del usuario desde varios hilos entonces la interfaz de usuario se dañara.

Evolución del Multiprocesamiento en Java
Me inicié en el mundo Java por los años 2008, han pasado ya casí 10 años y he visto como Java ha ido creciendo y evolucionando para facilitarle las tareas al programador. Antes de la versión 1.6, para ejecutar tareas en paralelo tenías que extender explicitamente a la clase Thread y programar toda la lógica del subprocesamiento multiple, sincronización, interacción con la GUI y demás. Con la llegada de la versión 1.6 aparece una clase llamada SwingWorker el cual se encarga de manejar toda la logica del subprocesamiento en paralelo, facilitandote en mucho la programación.

Resumiendo, hay dos formas de programar el subprocesamiento multiple con Swing.
  1. La forma tradicional en la que extiendes a Thread y programas toda la lógica de hilos.
  2. Extendiendo la clase SwingWorker

Yo recomiendo la segunda, usando la clase SwingWorker.
Para profundizar en el hilo EDT y SwingWorker puedes leer mi entrada SwingWorker y el Hilo que despacha los Eventos ahí explico detalladamente estás dos clases.

Problemas más comunes con sub procesamiento multiple

Por ejemplo corre el siguiente programa.

package com.maro.gui;

import java.util.Random;

import javax.swing.JComboBox;

public class BadWorkerThread extends Thread {

public BadWorkerThread(JComboBox aCombo){
combo = aCombo;
generator = new Random();
}
public void run(){
try {
while (!interrupted()){
int i = Math.abs(generator.nextInt());
if(i % 2 == 0){
combo.insertItemAt(new Integer(i), 0);
} else if(combo.getItemCount() > 0){
combo.removeItemAt(i % combo.getItemCount());
}
sleep(1);
}
} catch(InterruptedException iee){
}
}
private JComboBox combo;
private Random generator;
}


Un frame para visualizarlo, una vez que corras el programa presiona el boton "Bad" y juega con el combo box, notaras que el compilador lanza varias excepciones.

package com.maro.gui;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestBadWorkerThread extends JFrame{

private JComboBox combo;
private Thread longTask;
public TestBadWorkerThread (){
super("Prueba");
combo = new JComboBox();
JPanel contentPanel = new JPanel();
contentPanel.setLayout(new FlowLayout());
JButton badButton = new JButton("Bad");
badButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
longTask = new BadWorkerThread(combo);
longTask.start();
}
});
contentPanel.add(badButton);
contentPanel.add(combo);
this.getContentPane().add(contentPanel);
this.pack();
//this.setVisible(true);
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// TODO Auto-generated method stub
TestBadWorkerThread pr = new TestBadWorkerThread();
pr.setVisible(true);
}
});
}
}

Graficos y Java 2D : El contexto grafico

Un contexto de graficos en java es un objeto que nos permite dibujar en pantalla, dibujar pixeles en la pantalla que representan texto y otros objetos graficos (como lineas, elipses, rectangulos y otros poligonos). El contexto grafico tambien nos proporciona y nos permite manipular otro conjunto de informacion, como el color de fondo, el font a usar, etc,. La clase Graphics de java es un contexto de graficos, encapsula toda la informacion requerida para dibujar, ademas nos permite dibujar graficos (como lineas, elipses, rectangulos y poligonos).

La clase Graphics es una clase abstracta (es decir, no pueden instanciarse objetos Graphics). Esto contribuye a la portabilidad de java. Como el dibujo se lleva a cabo de diferente manera en cada plataforma que soporta a java, no puede haber una accion de implemento de las herramientas de dibujo en todos los sistemas, es decir, las herramientas usadas para dibujar graficos en windows son distintas a las usadas en linux, o en mac. Cada plataforma tiene su implementacion de la clase Graphics y esta implementacion esta oculta para nosotros por medio de la clase Graphics.

La funcion paint y update nos suministran el contexto grafico del applet o del componente, en otros casos, hemos de obtener el contexto grafico del componente mediante la función getGraphics.Una vez obtenido el contexto grafico podemos llamar desde este objeto a las funciones graficas definidas en la clase Graphics.

public void paint(Graphics g){
   //usar el contexto gráfico g 
}
public void update(Graphics g){ 
   //usar el contexto gráfico g 
}
void funcion(){     
   Graphics g=getGraphics();     
   //usar el contexto gráfico g     
   g.dispose(); 
}

Como vemos en esta porcion de codigo existe una sutil diferencia entre suministrar y obtener el contexto grafico g. Solamente es necesario liberar los recursos asociados al contexto g, mediante la llamada a la función dispose, cuando se obtiene el contexto grafico mediante getGraphics.




Graficos y Java 2D : Introduccion

Java nos proporciona un conjunto de herramientas para dibujar figuras bidimensionales, controlar colores y fuentes. Herramientas para el control del estilo de lineas utilizadas para dibujar figuras y el control del relleno de las figuras con colores y patrones.

Con estas herramientas es posible darle un toque mas estetico a componentes como botones, paneles, etiquetas, tablas, listas, etc,.

Es posible tambien realizar graficas (pastel, barras, etc,.) y muchas cosas mas.

Para poder dibujar en java, primero debemos comprender su sistema de coordenas, el contexto grafico, las llamadas a los metodos update, paint y repaint.

sábado, 15 de octubre de 2011

El Principio Abierto-Cerrado (PAC)

Las entidades de software (clases, modulos, funciones, etc.) Deberian ser abiertas para permitir su extension, pero cerradas frente a la modificacio.

En palabras mas sencillas, deberias poder cambiar el entorno que rodea a un modulo sin cambiar el modulo en si. Considera por ejemplo la figura 1. Muestra una sencilla aplicacion que trata con objetos Empleado mediante una fachada de datos llamada EmpleadoDB. La fachada trata directamente con el API de la base de datos. Cualquier sistema que contenga la clase Empleado debera contener tambien el API de la base de datos LaBasededatos.

Las unidades de prueba son siempre situaciones controladas donde realizamos cambios en el entorno. Considera, por ejemplo que desearamos probar Empleado. Los objetos Empleado hacen cambios en la base de datos. En un entorno de prueba no queremos que cambie la base de datos real. Tampoco queremos crear base de datos de mentira(claro, si no se tiene el script para hacerlo) solo para crear unidades de prueba. En vez de ello, nos gustaria cambiar el entorno de forma que la prueba cazara todas las invocaciones que Empleado hiciera a la base de datos. Y verificara que todas esas llamadas se hacen correctamente.

Podemos hacerlo conviertiendo EmpleadoDB en una interfaz, como en la figura 1.2. Entonces podemos crear derivados que bien invocan el API real de la base de datos, o que soportan nuestras pruebas. La interfaz separa Empleado del API de la base de datos y nos permite cambiar el entorno de la base de datos que rodea a Empleado sin afectar a Empleado en lo absoluto.

Otro ejemplo, una caja de dialogo muy sencilla que muestre una lista de empleados. El usuario seleccionara el empleado de la lista y pulsara sobre el boton "Termina". Suponemos que si no se selecciona ningun empleado el boton "Termina" no estara habilitado. Por otra parte, si se seleccionamos un empleado de la lista el boton "Termina" estara habilitado. Cuando el usuario pulsa sobre del boton "Termina" el empleado terminado desaparece de la lista, no se muestra seleccionado ni uno de los empleados restantes y se desabilita el boton "Termina".



domingo, 11 de septiembre de 2011

Las Variables de Entorno en Ubuntu

¿Que son?
Una variable de entorno es una variable el cual contiene un nombre, un valor, pueden ser declararas o eliminadas. En Ubuntu, pueden estar disponibles para cierto usuario, para todos los usuarios o para un grupo en especifico, pueden ser temporales o permanentes.

Las variables de entorno influyen en el comportamiento del software en el sistema. Por ejemplo la variable de entorno "LANG" determina el idioma en el que los programas de software se presentaran al usuario(etiquetas, titulos de botones, mensajes de error, etc,.).

Normalmente el significado y el formato del valor de una variable de entorno es interpretado por la aplicacion que ha de usarlo. Incluso entre varias aplicaciones se puede llegar a un acuerdo sobre el formato y significado del valor de ciertas variables de entorno.


Las variables PATH y CLASSPATH son ejemplos de variables de entornos muy usadas. La variable PATH tiene como contenido una cadena que contiene rutas de directorios, por ejemplo la ruta donde se encuentra el compilador de java. Para agregar mas directorios a esta variable es necesario separarlas con :
La variable CLASSPATH tiene una funcion parecida al PATH, en ella se definen directorios, librerias (.jar u otros) que nuestra programa en java vaya a usar, al igual que el PATH si son varios directorios estos se separan con un .

Definición de una variable de entorno.
Para definir una variable abrimos nuestra consola y la definimos de la siguiente manera.

usuario@Linux:~$ nombreUno=”Esta es una variable de entorno”

Podemos concatenarla con otra variable.

usuario@Linux:~$ nombreUno= $otraVariable:”Esta es una variable de entorno”

Una vez definida la variable es necesario exportarla al entorno.

El comando export.
Para que una variable de entorno este disponible se dice que hay que exportarla a nuestro entorno. El comando export es el indicado, su sintaxis es la siguiente y la ejecutamos en la misma terminal despues de definir.

usuario@Linux:~$ export nombreVariable

Tanto la exportación cómo la definición pueden hacerse en un mismo paso.


usuario@Linux:~$ export variableDos=”2”

Incluso se pueden exportar más de una variable a la vez.

usuario@Linux:~$ export variableTres=”Tres” variableCuatro=”Four"
Variables de Entorno persistentes.
Como dije anteriormente hay variables de entorno temporales y permanentes. En ocasiones se requiere que el valor de cierta variable de entorno quede guardado aun despues de cerrar sesion, es decir guardarlo en el disco duro.

Variables de Entorno ligados a un usuario en particular.
Si queremos que ciertas variables de entorno solo esten disponibles para cierto usuario cada que este inicie session, entonces debemos colocar las sentencias de exportación  para que estas variables sean exportadas a nuestro entorno como variables temporales cada que se inicia session, las sentencias se colocan en el archivo oculto bashrc que se localiza en el directorio home de nuestro usuario, este archivo ademas de definir variables de entorno nos permite guardar distintas configuraciones .

Algunos ejemplos:

export PATH=$PATH:"/home/automaton/netbeans-7.0.1/bin"
export PATH=$PATH:~/bin
export SUDO_PASSWORD=roberto10
export JAVA_HOME=/usr/lib/jvm/java-6-sun
export CATALINA_HOME=/usr/share/tomcat6
export CATALINA_OPTS="-server -Djava.awt.headless=true -Xms384M -Xmx1536M -XX:MaxPermSize=256M"




miércoles, 24 de agosto de 2011

El principio de la unica responsabilidad

Las clases solo deberian tener una responsabilidad, una tarea, conocer una cosa. Mas concretamente no deberia haber mas de una razon para cambiar una clase.
Considera la siguiente figura, esta clase conoce demasiado. Sabe como calcular un total y los impuestos, como leer y escribir a si misma en el disco, como convertirse a si misma desde y hacia XML y como imprimirse en varios formatos de informes. Puedes oler la fragibilidad? Cambia de SAX a DOM y deberas cambiar Venta, cambia de guardar a un archivo a guardar en una base de datos y tendras que cambiar Venta. Cambia el formato de los informes y tendras que cambiar Venta, te das cuenta a lo que quiero llegar, cuantas razones hay para cambiar la clase Venta? Si, existen 3 razones para cambiar nuestra clase, esto viola completamente el principio de la unica responsabilidad. Este diseno esta malamente acoplado.

El objetivo es separar todos estos conceptos en sus propias clases de forma que cada clase tenga una y solo una razon para cambiar. Nos gustaria que la clase Venta tratara de calculaTotal y calculaImpuestos que una clase XML relacionada tratara con la conversion de instancias de Venta desde y hacia XML, que una clase GuardarVenta tratara con la lectura y escritura de Venta al disco duro y que hubiera una clase para visualizar los informes. En resumen queremos separar cada tarea .

A continuacion muestro un diagrama de como pudiera quedar el conjunto de las nuevas clases.











sábado, 20 de agosto de 2011

Calidad en el Diseño

Que significa que un sistema este bien diseñado? Un sistema esta bien diseñado si es fácil de comprender, fácil de cambiar y fácil de reutilizar. No presenta dificultades concretas de desarrollo es simple terso y económico. Es un placer trabajar con el. A la inversa, un mal diseño no dan ganas de trabajar con el.

Personalmente cuido las siguientes caracteristicas:

Rigidez: El sistema es dificil de cambiar porque cada vez que cambias algo este cambio afecta a otra parte del sistema y entonces nuevamente tienes que cambiar y luego este cambio afecta otra parte del sistema... asi se vuelve un cambio interminable.

Fragilidad: Un cambio en una parte del sistema provoca una ruptura en muchas otras partes que no tienen nada que ver.

Inmovilidad: Se hace muy dificil descomponer el sistema en partes que puedan ser reusables en otros sistemas.

Viscosidad: El entorno de desarrollo se sostiene con cinta adhesiva y engrudo. Lleva una eternidad pasar por el bucle editar-compilar-probar.

Repetición innecesaria El código tiene todo el aspecto de haber sido escrito por dos programadores llamados Copia y Pega, personalmente me llevo cerca de un año dejar este mal habito.

Opacidad: Resulta dificil aclarar cuales fueron las intenciones del creador debido a las formas rebuscadas de expresion.

En las siguientes entradas escribiré tips para evitar caer en estos malos hábitos.

Hello World

Tengo que admitirlo, mantener al día este blog supondrá un esfuerzo adicional para mi. Es complicado escribir, aunque no lo creas, ademas tengo un chingo de cosas por hacer. Aun así, poder expresar lo que siento es algo muy importante para mi.
Espero poder usar este espacio para compartir con ustedes mis pensamientos y conocimiento, más importante aun, espero recibir retro alimentación. Así que siéntete libre de comentar todos mis post.

I have to recognize keeping a blog updated will be a very important effort to me. It's complicated to write for me and I have a ton of things on my to do list. However, I thing spreading the word is an important  task for me.
I hope I can use this space to share my thoughts with you and, most importantly, be able to get your beedback firsthand. Please, feel free to comment my posts.
Anyway, here we go. Let's see what happens.