martes, 31 de enero de 2012

La función mutante

Cuando se va a empezar con el desarrollo de una aplicación, siempre se realizan distintas acciones como:

  • Pruebas de concepto: Mirar ejemplos, documentación, restricciones, etc.. de las tecnologías que se van a utilizar.
  • Toma de requisitos: Hablar con el cliente para ver a mas bajo nivel la información.
  • Definir metodología de trabajo: Establecer que procedimientos se van a utilizar para asignar tareas, herramientas de integración continua, etc..
  • Etc..

Pero hay tareas de la que todo el mundo habla y a las que no se quiere enfrentar nadie como:

  • Definición de clases, ficheros con funciones, etc.. que se van a utilizar.
  • Metodología de programación.
  • Adecuación de la información a la forma de programar.
  • Etc…

Es decir, la forma de programar es libre y que cada uno haga lo que quiera. Voy a ilustrar el “cuento” de la función mutante. Este cuento nos va a sonar a todos e ilustra perfectamente como una linda función se convierte en un monstruo.

Hace mucho tiempo en un país muy lejano, había un proyecto consistente en la gestión de “algo” una empresa “cualquiera”. Mientras se está desarrollado, de cualquier manera, el programador lee un requisito que le pide que cree una linda función “altaDeUsuario” donde llega un objeto (o estructura) y este se da de alta en base de datos.

El programador, tan contento y risueño ve que el requerimiento no dice nada más y que hay una función en el controlador de Base de Datos para darlo de alta. Se crea la siguiente función:

public int altaDeUsuario (Usuario usuario){

int respuesta;

int salida = controladorBaseDeDatos.altaUsuario(usuario);

switch (salida){

case controladorBaseDeDatos .OK: respuesta = OK; break;

default: respesta = ERRORBD; break;

}

return respuesta;

}

Y todos contentos. Qué función más bonita.

Tras X tiempo, el gran ogro jefe del bosque llama al pobre programador con el comentario “como es que no se valida que el usuario ya este dado de alta!!!”. El pobre programador pone un control en el primer sitio que pilla:

public int altaDeUsuario (Usuario usuario){

int respuesta;

Usuario usuarioBuscado = controladorBaseDeDatos.buscarUsuario(usuario);

If (usuarioBuscado ¡= null){

int salida = controladorBaseDeDatos.altaUsuario(usuario);

switch (salida){

case controladorBaseDeDatos .OK: respuesta = OK; break;

default: respesta = ERRORBD; break;

}

}else

respuesta = 3;

return respuesta;

}

El pobre programador tiene que poner porque la función que llama a la linda función altaDeUsuario entiende la respuesta 3 como que no el usuario ya existe pero no esta tipificado :(.

Un buen dia, aparece una función no tan bonita pero que necesita el ultimo usuario que se de dio de alta. La función altaDeUsuario no tiene culpa de eso pero otro pobrecito programador hace la solución mas fácil:

public int altaDeUsuario (Usuario usuario){

int respuesta;

Usuario usuarioBuscado = controladorBaseDeDatos.buscarUsuario(usuario);

If (usuarioBuscado ¡= null){

int salida = controladorBaseDeDatos.altaUsuario(usuario);

switch (salida){

case controladorBaseDeDatos .OK: respuesta = OK;

if (usuarioGlobal == null )

usuarioGlobal = usuario;

break;

default: respesta = ERRORBD; break;

}

}else

respuesta = 3;

return respuesta;

}

Los días terribles se suceden y aparece nuevos requerimientos que se suceden al grito del ogro jefe “esto ya que tenemos que sacar version” o la ya tristemente famosa “no me puedo creer que no lo hicierais así en su día. Si es de lógica”. Estos requerimientos son:

- Solo tener en cuenta los usuario con fecha superior al 01/01/2011

public int altaDeUsuario (Usuario usuario, Date fechaValidezUsuario){

int respuesta;

if (fechaValidezUsuario > 01/01/2011)

Usuario usuarioBuscado = controladorBaseDeDatos.buscarUsuario(usuario);

If (usuarioBuscado ¡= null){

int salida = controladorBaseDeDatos.altaUsuario(usuario);

switch (salida){

case controladorBaseDeDatos .OK: respuesta = OK;

if (usuarioGlobal == null )

usuarioGlobal = usuario;

break;

default: respesta = ERRORBD; break;

}

}else

respuesta = 3;

}else

respuesta = 4;

return respuesta;

}

- El nuevo campo de Usuario tipoDeUsuario hay que rellenarlo comparando el campo A en una lista.

public int altaDeUsuario (Usuario usuario, Date fechaValidezUsuario){

int respuesta;

if (fechaValidezUsuario > 01/01/2011)

Usuario usuarioBuscado = controladorBaseDeDatos.buscarUsuario(usuario);

If (usuarioBuscado ¡= null){

int salida = controladorBaseDeDatos.altaUsuario(usuario);

switch (salida){

case controladorBaseDeDatos .OK: respuesta = OK;

if (usuarioGlobal == null )

usuarioGlobal = usuario;

for (int i = 0, i < tipos.longitud; i++){

if (usuario.getA() == tipos[i].getA())

controladorBaseDeDatos.modificaTipoUsuario(usuario,tipos[i]);

}

break;

default: respesta = ERRORBD; break;

}

}else

respuesta = 3;

}else

respuesta = 4;

return respuesta;

}

Y asi siguió el cuento. Al final la función acabo con mas de 500 lienas de código y sin que nadie se atreva a tocarla por miedo de fastidiar algo que funciona.

Te suena ¿Verdad?

Creo que la conclusión es HAY GASTAR TIEMPO EN PENSAR LAS COSAS ANTES.


lunes, 23 de enero de 2012

El lenguaje XML de JavaFX 2.0 . FXML (II) - Objetos simples

A continuación voy a comentar una serie de objetos simples, como usarlos en el un fichero FXML y sus propiedades mas utilies.

Button


- Incluir import:
javafx.scene.control.Button

- Ejemplo de etiqueta:
<Button id="ticket" fx:id="ticket" layoutX="620" layoutY="150" text="Pulsame" scaleX="2" scaleY="2"/>


- Propiedades:
  • id: Texto que referencia al objeto dentro del conjunto.
  • layoutX: Posicion X dentro del panel.
  • layoutY: Posicion Y dentro del panel.
  • text: Texto inicial.
  • scaleX: % de escala con el tamaño por defexto en el sentido X.
  • onAction: Nombre de la funcion que va a realizar la accion del boton. Esta funcion debe de estar en la clase marcada por el atributo "fx:controller" y tener la anotacion @FXML.
  • scaleY: % de escala con el tamaño por defexto en el sentido Y.



Label

- Incluir import:
javafx.scene.control.Label

- Ejemplo de etiqueta:
<Label id="cantidad" fx:id="cantidad" layoutX="670" layoutY="50" scaleX="1" scaleY="2" text="1"/>


- Propiedades:
  • id: Texto que referencia al objeto dentro del conjunto.
  • layoutX: Posicion X dentro del panel.
  • layoutY: Posicion Y dentro del panel.
  • text: Texto inicial.
  • scaleX: % de escala con el tamaño por defexto en el sentido X.
  • scaleY: % de escala con el tamaño por defexto en el sentido Y.


TextField

- Incluir import:
javafx.scene.control.TextField

- Ejemplo de etiqueta:
<TextField id="cantidad" fx:id="cantidad" layoutX="670" layoutY="50" scaleX="1" scaleY="2" text="1" prefWidth="100"/>


- Propiedades:
  • id: Texto que referencia al objeto dentro del conjunto.
  • layoutX: Posicion X dentro del panel.
  • layoutY: Posicion Y dentro del panel.
  • text: Texto inicial.
  • prefWidth: Tamaño del cuadro de texto.
  • scaleX: % de escala con el tamaño por defexto en el sentido X.
  • scaleY: % de escala con el tamaño por defexto en el sentido Y.

ImageView

- Incluir imports:
javafx.scene.image.ImageView
javafx.scene.image.Image

- Ejemplo de etiqueta:
<ImageView id="st21" fx:id="st21" x="380" y="0">
<image>
<Image url="@ic_tren.gif"/>
</image>

</ImageView>

- Propiedades:
  • id: Texto que referencia al objeto dentro del conjunto.
  • x: Posicion X dentro del panel.
  • y: Posicion Y dentro del panel.
  • url: Url de la imagen.

Text

Incluir import:
javafx.scene.text.Text.

- Ejemplo de etiqueta:

<Text id="stt21" fx:id="stt21" x="50" y="30" text="HOLA"/ >


- Propiedades:
  • id: Texto que referencia al objeto dentro del conjunto.
  • x: Posicion X dentro del panel.
  • y: Posicion Y dentro del panel.
  • text: Texto que pintar.
Line

- Incluir import:
javafx.scene.shape.Line.

- Ejemplo de etiqueta:
<Line id="line11" fx:id="line11" startX="0" startY="0" endX="300" endY="290" strokeWidth="1"/>

- Propiedades:
  • id: Texto que referencia al objeto dentro del conjunto.
  • startX: Posicion X dentro del panel donde empieza la linea.
  • startY: Posicion Y dentro del panel donde empieza la linea.
  • endX: Posicion X dentro del panel donde termina la linea.
  • endY: Posicion Y dentro del panel donde termina la linea.
  • strokeWidth: Tamaño de la linea de dibujo.
  • stroke: Color de la linea.

Rectangle

- Incluir import:
javafx.scene.shape.Rectangle.

- Ejemplo de etiqueta:

<Rectangle id="cuadro" fx:id="cuadro" x="550" y="0" height="600" width="250" strokeWidth="1" fill="#999999"/ >

- Propiedades:
  • id: Texto que referencia al objeto dentro del conjunto.
  • x: Posicion X dentro del panel.
  • y: Posicion Y dentro del panel.
  • height: Altura.
  • width:Anchura.
  • strokeWidth: Tamaño de la linea de dibujo.
  • fill: Color de relleno.

El lenguaje XML de JavaFX 2.0 . FXML (I) - Paneles

Una escena de JavaFx 2.0 se puede componer como una pantalla de Swing y se puede evitar el uso de código “spaguetti” para ir definiendo los distintos componentes de los paneles que forman una pantalla gracias a FXML.

¿Cómo se usa un fichero FXML? La mejor forma de entender un fichero FXML es verlo como esa clase Java de código “spaguetti” puesta en notación XML. Tomemos como ejemplo la clase MiPantalla.java

public class MiPantalla extends JPanel{

public MiPantalla(){

inicializar();

}

private void inicializar(){

}

}

En una clase de código “spaguetti” MiPantalla si quieres definir un layout para un panel incluyes el import del tipo de layout y lo incluyes en una función

import java.awt.BorderLayout;

public class MiPantalla extends JPanel{

Public MiPantalla(){

inicializar();

}

Private void inicializar(){

setLayout(new BorderLayout());

}

}

Pues esto es prácticamente igual en un fichero FXML:


<?import javafx.scene.layout.AnchorPane?>

Ojo con este paso porque es la dinámica para usar FXML. Cuando se quiere usar una etiqueta nueva lo primero es incluir su “import” correspondiente en la parte superior del fichero XML. Una vez incluida se puede usar la etiqueta en el XML. Y esto es para todos los componentes igual.

Una vez que se incluye un componente en forma de etiqueta de XML también se puede acceder a todas sus propiedades de dicho componente en forma de atributo. Supone que tienes el siguiente código:

AnchorPane anchorPane = new AnchorPane();

anchorPane.setId("AnchorPaneId");

El equivalente en FXML seria:

<AnchorPane id="AnchorPaneId" prefHeight="500" prefWidth="800" xmlns:fx="http://javafx.com/fxml" fx:controller="es.ejemplo.Control">

</AnchorPane>

Es decir, el nombre del atributo es la función “setXXXX” quitándole el prefijo “set” y cambiando la primera letra a minúscula (ojo que Java es “Case sensitive”).

Respecto a los paneles que se pueden usar en JavaFx 2.0 son AnchorPane, BorderPane, FlowPane, GridPane, HBox, StackPane, TilePane y VBox.

Tambien cabe destacar el atributo fx:controller. Este atributo indica el nombre de la clase donde estarán “mapeados” todos los componentes y todas las acciones de esos componentes para que puedan interactuar con el resto de la aplicación. Esto se verá mejor en los siguientes post cuando se empiece con los componentes.