Refactorización

La refactorización es una técnica para reestructurar un código fuente, alterando su estructura interna sin cambiar su comportamiento externo, es decir, aquellos cambios son reflejados automáticamente donde estos aparezcan.

Para ver un ejemplo de refactorización, pincha en el siguiente enlace:
EJEMPLO REFACTORIZACIÓN. Para conseguir una visión óptima, aumentar la calidad de imagen (botón derecho sobre el flash).

También se llama refactorización a la creación automática de aquellos elementos mencionados y no creados previamente ( esto es de gran utilidad cuando aplicamos TDD, ya que las clases, interfaces, variables, ... son mencionadas en la zona de pruebas (test) y luego son creados automáticamente en el source correspondiente (src) . Para aplicar esto, CTRL+SPACE en el IDE ECLIPSE.

Servidor de Aplicaciones

Un Servidor de aplicaciones (S.A.), es un dispositivo software, que como todo servidor, proporciona unos recursos o servicios a las aplicaciones cliente, diferenciándose del resto en que integra 3 contenedores: Contenedor Web (Servlet, JSP,...), Contenedor EJB y Contenedor o Gestión de la Persistencia, es decir, permite implementar diferentes capas en la aplicación, como: la interfaz de usuario, la lógica de negocio (la gestión de sesiones de usuario,...) o el acceso a bases de datos local o remoto, todo ello de un forma centralizada y disminuyendo así la complejidad en el desarrollo de aplicaciones siempre que se haga un buen diseño (Ingeniería del SoftWare).


Los servidores de aplicaciones son aplicables todas las plataformas software, aunque hoy día se ha convertido un sinónimo de la plataforma J2EE.

Otra característica y obvia antes mencionada implícitamente, es la portabilidad de Java (multi-plataforma) ya que permite que los servidores de aplicaciones J2EE se encuentren disponibles en una gran variedad de Sistemas Operativos (Windows, Linux,...).

Servidores de Aplicaciones más conocidos:

  1. S.A. privativos : WebSphere (IBM), WebLogic (BEA), Oracle Aplication Server (Oracle Corporation).
  2. S.A. Libres : JOnAS y JBOSS (nuestro caso).

He aquí un pequeño esquema de un S.A. :

Pincha aquí para ver las características de la plataforma J2EE en una ventana aparte.

Interceptores / Controladores

Llamamos interceptor o controlador aquel elemento u objeto que conecta la capa vistas con la capa del modelo ( patrón MVC, hay una entrada en este blog ). El usuario, cuando realiza una petición (c. vistas), no habla directamente con la lógica del negocio ( c. modelo) , sino a través de un intermediario, siendo éste el interceptor. Cuando el interceptor recibe la petición por parte del usuario, pone en funcionamiento el servicio correspondiente, siendo éstos ocultos e invisibles para el ususario, por tanto, podríamos llamarlo también como el gestor de eventos (handler). También se encarga de controlar los diversos aspectos (AOP, hay una entrada en este blog) que maneja el sistema. Puede darse el caso de que haya más de un controlador en nuestra aplicación.

Programación Orientada a Objetos (POO)

La Programación Orientada a Objetos ( POO u OOP en adelante ) es uno de los paradigmas de la programación. Parte de la programación estructurada (a la que engloba), con la gran diferencia de que nos permite modelar problemas no estructurados. La OOP no sustituye a ninguna metodología ni lenguaje de programación anterior, es decir, todos los programas que se realizan en POO se pueden realizar igualmente mediante programación estructurada, aunque si cabe destacar que con dicho paradigma el desarrollo de muchas herramientas es bastante más sencillo, como son las interfaces gráficas de usuario ( Windows, X-Window,...).


El uso de la OOP hoy día es muy variado, aplícandose tanto en Sistemas Operativos (S.O.), Inteligencia Artificial (I.A.),"Aplicaciones Empresariales",SBGDOO (no muy utilizado ya que hay muchos problemas)...

Principales características de la OOP:

A) Clase: Es el núcleo de la POO. Se define como un nuevo tipo de dato que se utiliza para crear objetos de ese tipo.
B) Metaclases: Son clases cuyos ejemplos son a su vez clases. "Java" tiene esta carácterística pero no es aplicable a todos los lenguajes OOP, como pasa con C++.
C) Objetos: Un objeto es una instancia o ejemplo de una clase. En "java", estos son creados con el operador new (es creado en tiempo de ejecución como es obvio). Cada objeto tiene un estado definido por sus atributos (salvo los objetos stateless ya que estos no tienen propiedades) y un comportamiento (definido por sus métodos).
D) Identidad: Aquella propiedad que distingue al objeto de los demás (salvo objetos stateless).
E) Abstraccion: Capacidad de conceptualizar el problema en forma de clases (tipos) y variables pertenecientes a estos tipos (instancias). Hacemos clasificaciones jerárquicas.
F) Encapsulación: Capacidad de aunar dentro de una clase las propiedades y métodos para trabajar con sus datos internos. Con esta capacidad, conseguimos reutilización.
G) Herencia: Capacidad de derivar de una clase genérica, clases diferentes que hereden las propiedades y métodos de su clase antecesora.La herencia nos da reusabilidad de código.En "Java", no existe herencia múltiple, siempre herencia simple.
H) Polimorfismo: Capacidad para que varias clases derivadas de una antecesora utilicen el mismo método de forma diferente. Otra aplicación sería jugar con los comportamientos de los objetos. El polimorfismo es coseguido graciasa la herencia y a la ligadura dinámica. Una de las ventajas del polimorfismo es que se puede hacer uso de una solicitud de una operación sin conocer el método que debe ser llamado. Aquí podemos hacer uso de las interfaces, donde decimos el comportamiento que va a tener un objeto en un instante dado.
I) Persistencia: Es la propiedad por la cual la existencia de un objeto transciende tanto en el tiempo como en el espacio.
j) Otros conceptos son: Modularidad, tipificado,...

Ventajas que proporciona la OOP frente a otros lenguajes de programación:

A) Uniformidad: La representación de los objetos lleva implícita tanto el análisis como el diseño y codificación de los mismos.
B) Comprensión: Los datos que componen los objetos y los procedimientos que los manipulan, están agrupados en clases, que se corresponden con las estructuras de información que el programa trata.
C) Flexibilidad: Al relacionar los métodos y propiedades, cualquier cambio que se realice sobre ellos quedará reflejado automáticamente en cualquier lugar donde estos datos aparezcan.
D) Reutilización: La noción de objeto permite que programas que traten las mismas estructuras de datos reutilicen las definiciones de objetos empleadas en otros programas e incluso los métodos que los manipulan. De esta forma, el desarrollo de un programa puede llegar a ser una simple combinación de objetos ya definidos donde éstos están relacionados de una manera particular.
En la programación OOP, los componentes (objetos) se conocen, cosa que no pasa con la AOP.

Desarrollo guiado por pruebas (TDD)

El Test-Driven Development ( TDD en adelante ) es una técnica que involucra dos partes en el siguiente orden:

  1. Escribir primero las pruebas (Test First Development), es decir, usando para ello los framework JUNIT o TESTNG (de este último hay una entrada en el blog).

  2. Refactorización. Ya comentado en otra entrada del blog.

Aplicando TDD sobre la aplicación, conseguimos un software seguro y fiable.

Programación Orientada a aspectos (POA)

Con la Programación Orientada a aspectos ( POA o AOP en adelante ) conseguimos que los distintos componentes ( modulos ) que componen la aplicación sean independientes unos de otros, aplicando para ello las API´s de reflexión (java.lang.reflect). Un ejemplo típico y bastante claro ( dado en clase ) es el aspecto de la seguridad, en donde vimos que según el tipo de usuario (despues de hacer login) podía hacer unas operaciones u otras (otro ejemplo podría ser salida por la consola,...) . Con la AOP conseguimos una separación de las funcionalidades del sistema, por un lado las comunes de la aplicación y por otro lado las propias de cada módulo.

En la programación AOP, los distintos componentes no se conocen, cosa que no pasa con la OOP.

La versión EJB2 usa ficheros XML para basarse en POA, mientras que EJB3 se basa en anotaciones· Con las anotaciones queda más claro para el programador, ya que la información relativa a aspectos/interceptores queda en el mismo fichero java, en vez de utilizar otro fichero (XML) situado en otro directorio de la aplicación.

Enterprise JavaBeans v.3 (EJB3)

Los EJB forman parte del API del J2EE desarrollado por Sun Microsystems y se centran en lógica de negocio (recordamos que en las aplicaciones cliente servidor basadas en sistemas distribuidos existen 3 capas : presentación (se encarga de la visualización), lógica de negocio(su nombre lo indica todo) y de datos(se encarga del almacenamiento de datos:SGBD)). Una vez comprendido lo anterior (arquitecturas multicapas), ahora, podemos definir lo que es un EJB: Modelo de componenetes distribuido estándar del lado del servidor. Los EJB´s se encuentran ubicados dentro del contenedor EJB del servidor de aplicaciones,en nuestro caso JBOSS AS.

Historia de los EJB:

EJB 1.0: La especificación original .
EJB 1.1: La primera incluida dentro de J2EE
EJB 2.0: Incluida en J2EE 1.3, añadía las interfaces Locales y los Message-Driven beans.
EJB 2.1: Incluida en la última revisión de J2EE, la 1.4.


Hasta ahora, el manejo y configuración de los EJB´s se basaba en ficheros XML, sin embargo, la última versión,(EJB 3.0) se caracteriza porque permite el manejo con anotaciones. EJB3 está incluida en JEE5.0. En realidad, un EJB3 es un POJO ( para comprender su significado, buscar dicha entrada en este blog) más anotaciones (tales como @Entity,@StateFull,...)(También hay una entrada en este blog sobre las anotaciones). Al ser POJO, cada objeto ha de llevar el constructor por defecto, siendo éste implícitamente ( es insertado automáticamente) o explícitamente ( en caso de que necesitemos constructores con parámetros).

A continuación, veamos el proceso de creación de un EJB:
Hay 3 tipos de EJB:

A) EJB de entidad (Entity EJBs): No explicado todavía.


B) EJB de sesión (Session EJBs): Gestionan el flujo de la información en el servidor. Generalmente sirven a los clientes como una fachada de los servicios proporcionados por otros componentes disponibles en el servidor. Hay dos tipos de EJB de entidad:
  1. Con estado (StateFul). Los beans de sesión con estado son objetos distribuidos que poseen un estado. El estado no es persistente, pero el acceso al bean se limita a un solo cliente. Para la creación de un EJB statefull se usan llamadas RMI.


  2. Sin estado (StateLess). Los beans de sesión sin estado son objetos distribuidos que carecen de estado asociado ( carecen de atributos o propiedades ) permitiendo por tanto que se los acceda concurrentemente. No se garantiza que los contenidos de las variables de instancia se conserven entre llamadas al método, es decir, el componente (objeto) no está asociado al usuario (sólo es creada una única instancia como máximo). Un objetos Stateless también puede usarse para modificar alguna propiedad de un objeto StateFull. Para la creación de un EJB stateless se usa pooling web services.

En el caso de JBOSS SEAM, este distingue 3 tipos de EJB de sesión con estado:

  • Objeto Página: Guarda información mientras la página este activa. Se destruye cuando pasa un cierto tiempo o cuando el usuario a cambiado de página web.

  • Objeto evento: Ocurre cuando el cliente modifica o actualiza algo en la ventana del navegador.

  • Objeto conversación(Task): El cliente pone a próposito que inicie un servicio para conseguir su objetivo.

C) EJB dirigidos por mensaje (Message-driven EJBs(MDB)): : No explicado todavía.

Servicios que nos proporcionan los EJB
A) Messaging (Se trata de una comunicacion asíncrona).
B) Inyección de dependencias.
C) Pooling.
D) Thread-safely.
E) Mantenimiento del estado.
F) AOP-Interceptores. De esto se habla en otra entrada.
G) RMI (Remote Invocation Method).
H) Web Services.
I) Transacciones.
J) Seguridad (gracias a las anotaciones).

He aquí un esquema y su relación con las aplicaciones J2EE:


Java 2 Enterprise Edition (J2EE)

Se trata de una plataforma de desarrollo para aplicaciones empresariales multicapa desarrollado por Sun Microsystems. Se basa en componentes modulares y estandarizados ejecutándose sobre un servidor de aplicaciones (por ejemplo JBOSS AS), proveyendo un completo cojunto de servicios a estos componentes, y manejando muchos de las funciones de la aplicación de forma automática, sin necesidad de una programación compleja. Java EE incluye varias especificaciones de API, tales como JDBC,RMI,e-mail,JMS,Servicios web,JSP,Servlet,EJB,XML...

Las características del J2EE, son las siguientes: Alto rendimiento, aplicaciones distribuidas y multiusuario, escalable, testeable, gestión del estado, persistencia (ya definido), transacciones, seguridad (gracias a las anotaciones) e interceptores .

Para desarrollar nuestras aplicaciones empresariales con J2EE usaremos el IDE ECLIPSE versión EUROPA (3.3) , el cual ya tiene integrado el JDT (Java Development Tools).

La última versión del J2EE sacado por Sun es conocida como JEE 5.0.

TestNG

TestNG es un framework que permite realizar pruebas unitarias, funcionales, de integracion,... en aplicaciones java, es decir, comprueba que el comportamiento de los objetos sea el deseado. Esta basado en Junit, pero a diferencia de éste, TestNG añade nuevas funcionalidades (por ejemplo @DataProvider, @BeforeMethod,@BeforeClass,...). Como se habrás observado, nuestro framework se basado en anotaciones, al igual que Junit 4.0 (antes de dicha versión, se hacía heredando de la clase TestCase). Para evaluar aquellos métodos usamos la anotación @Test.

Veamos un ejemplo muy sencillo :


package es.cea.utilidades;

import org.testng.annotations.Test;


public class TestNG {

@Test
public void pruebaDevuelveValor(){

AlmacenaValor miValor=new AlmacenaValor(2);
assert (miValor.dameValor()==1):
"Lo que devuelve el objeto (miValor), es distinto de 2";
}
}

class AlmacenaValor{

int valor;
AlmacenaValor(int valor){
this.valor=valor;
}
int dameValor(){

return valor;
}
}

Como habreis comprobado en vuestro IDE ECLIPSE, el resultado ha fallado dado que hemos almacenado el valor 2 como parámetro en el constructor y lo estamos comparando con el valor 1.

La anotación @DataProvider consiste en evaluar un mismo método de forma iterativa, veamos un ejemplo para que se comprenda mejor:


package es.cea.utilidades;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class TestNG {

@DataProvider(name="pruebaConEstosValores")
public Object[][]teDoyValores(){
return new Object[][]{{1},{2},{3}};
}

@Test(dataProvider="pruebaConEstosValores")
public void pruebaDevuelveValor(int pruebaEntero){

AlmacenaValor miValor=new AlmacenaValor(2);
assert (miValor.dameValor()==pruebaEntero):
"Lo que devuelve el objeto (miValor), es distinto de 2";
}
}

class AlmacenaValor{
int valor;
AlmacenaValor(int valor)
{
this.valor=valor;
}
int dameValor(){
return valor;
}
}

En este ejemplo, cuando el valor del parámetro (pruebaEntero) valga 1 y 3, el test no tendrá éxito, mientras que para el otro caso (valga 2) si lo tendrá.

Como ya se mencionó antes, existen otras anotaciones de utilidad, como @BeforeClass, @BeforeMethod,...

Otra característica es el uso de una suite (fichero basado en xml). Esto es de gran utilidad ya que ejecuta a la vez todos aquellos métodos que tengan la anotación @Test del paquete indicado, en vez de ir uno por uno. He aquí un ejemplo:

Fichero testng.xml (puede llamarse como uno quiera):

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="Suite1" verbose="1" >
<test name="Regression1" >
<packages>
<package name="nombre.paquete.*" />
</packages>
</test>
</suite>

En una misma suite, puede indicarse más de un paquete.

EasyMock

Se trata de un framework para el Eclipse, el cual aisla los detalles de implementación gracias a una interfaz. El uso de dicho framework, lo aplicamos en la zona de pruebas (test).


package es.nuwi;


import org.easymock.EasyMock;
import org.testng.annotations.Test;


public class EjemploEasyMock {


@Test
public void pruebaLlamadaServicio(){


//Creamos el objeto,el cual realizará la llamada.
Controlador controlador = new Controlador();


//Aquí creamos la interfaz del servicio.
InterfazServicio servicioInterfaz=
EasyMock.createMockInterfazServicio.class);


//Reseteamos.
EasyMock.reset(servicioInterfaz);


//Indicamos que llamada esperamos y que es lo que devolvemos.
EasyMock.expect(servicioInterfaz.dameServicio()).andReturn(true);


//Esperamos la llamada.
EasyMock.replay(servicioInterfaz );


/*El objeto controlador ha de tener obligatoriamente
una referencia para realizar la llamada.*/
controlador.servicioInterfaz=servicioInterfaz;


/*dameServicio es un método del objeto controlador.
En dicho método se realizará la llamada.*/
controlador.dameServicio();


//Comprobamos que se ha realizado la llamada.
EasyMock.verify(servicioInterfaz);
}
}