Ley de Demeter LoD

Tambien llamado Principio del Minimo Conocimiento (Northeastern University, 1987).

(Sacado del articulo de Jorge Rodriguez, “pruebas-unitarias“)

Esta ley dice que un objeto solo debe depender de objetos que esten muy cercanos a el, o sea no debería usar objetos globales.

Ejemplo:

  • helper.metodo(); // BIEN
  • helper.getSegundoHelper().metodo(); // MAL
Ley de Demeter LoD

Versiones de Java

Articulo original

Java 1

Java 1.0 (Enero 1996) – 8 paquetes, 212 clases –
Primera versión pública. La presión hizo que se hiciera pública demasiado pronto, lo cual significa que el diseño del lenguaje no es demasiado bueno y hay montones de errores. Respecto a seguridad, es restrictivo por defecto, no dejando hacer demasiado al código no fiable.

Java 1.1 (Marzo 1997) – 23 paquetes, 504 clases –
Mejoras de rendimiento en la JVM, nuevo modelo de eventos en AWT, clases anidadas, serialización de objetos, API de JavaBeans, archivos jar, internacionalización, API Reflection (Reflexión), JDBC (Java Data base Connectivity), RMI (Remote Method Invocation). Se añade la firma del código y la autentificación. Es la primera versión lo suficientemente estable y robusta.

Java 2

Java 1.2 (Diciembre 1998 ) – 59 paquetes, 1520 clases –
JFC (Swing), Drag and Drop, Java2D, Corba, API Collections. Se producen notables mejoras a todos los niveles. Para enfatizar esto Sun lo renombra como “Java 2”. El JDK (Java Development Kit) se renombra como SDK (Software Development Kit). Se divide en J2SE, J2EE y J2ME.

Java 1.3 (Abril 2000) – 77 paquetes, 1595 clases –
Orientada sobre todo a la resolución de errores y a la mejora del rendimiento; se producen algunos cambios menores como la inclusión de JNDI (Java Naming and Directory Interface) y la API Java Sound. También incluye un nuevo compilador de alto rendimiento JIT (Just In Time).

Java 1.4 (2002) – 103 paquetes, 2175 clases –
También conocido como Merlin, es la versión actual. Mejora notablemente el rendimiento y añade entre otros soporte de expresiones regulares, una nueva API de entrada/salida de bajo nivel (NIO, New I/O), clases para el trabajo con Collections, procesado de XML; y mejoras de seguridad como el soporte para la criptografía mediante las Java Cryptography Extension (JCE), la inclusión de la Java Secure Socket Extension (JSSE) y el Java Authentication and Authorization Service (JAAS).

Java 1.5 (Octubre 2004) – 131 paquetes, 2656 clases –
También conocido como Tiger, renombrado por motivos de marketing como Java 5.0.
Incluye como principales novedades: tipos genéricos (generics), autoboxing/unboxing conversiones impliticas entre tipos primitivos y los wrappers correspondientes, Enumerados, Bucles simplificados, printf, Funciones con número de parámetros variable, Metadatos en clases y métodos.

Java 1.6 (diciembre de 2006) —
También conocido como Mustang. Estuvo en desarrollo bajo la JSR 270. En esta versión, Sun cambió el nombre “J2SE” por Java SE y eliminó el “.0” del número de versión.
Los cambios más importantes introducidos en esta versión son: Incluye un nuevo marco de trabajo y APIs que hacen posible la combinación de Java con lenguajes dinámicos como PHP, Python, Ruby y JavaScript. Incluye el motor Rhino, de Mozilla, una implementación de Javascript en Java. Incluye un cliente completo de Servicios Web y soporta las últimas especificaciones para Servicios Web, como JAX-WS 2.0, JAXB 2.0, STAX y JAXP. Mejoras en la interfaz gráfica y en el rendimiento.

Versiones de Java

Patrones de Diseño

Los patrones de diseño (design patterns) son la base para la búsqueda de soluciones a problemas comunes en el desarrollo de software y otros ámbitos referentes al diseño de interacción o interfaces.

Un patrón de diseño es una solución a un problema de diseño. Para que una solución sea considerada un patrón debe poseer ciertas características. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reusable, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias.

Maneras de implementar, mediante interfaces, casos específicos en programación.

Patrones de Diseño

Patrones de Diseño

Los patrones de diseño (design patterns) son la base para la búsqueda de soluciones a problemas comunes en el desarrollo de software y otros ámbitos referentes al diseño de interacción o interfaces.

Un patrón de diseño es una solución a un problema de diseño. Para que una solución sea considerada un patrón debe poseer ciertas características. Una de ellas es que debe haber comprobado su efectividad resolviendo problemas similares en ocasiones anteriores. Otra es que debe ser reusable, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias.

Maneras de implementar, mediante interfaces, casos específicos en programación.

Patrones de Diseño

Inversión de Control (IoC) & Inyección de Dependencia (DI)

<!– @page { margin: 2cm } P { margin-bottom: 0.21cm } –>

En los comienzos de la programación, los programas eran lineales y monolíticos. El flujo de ejecución era simplemente ejecutar línea tras linea.

Aparecieron dos conceptos que revolucionaron la programación: la modularidad y la reutilización de los componetes: se crean librerías de componentes reutilizables. El flujo se complica, saltando de componente a componente, y aparece un nuevo problema: la dependencia (acoplamiento) entre nuestros componentes.

El problema se empieza a considerar lo suficientmente importante como para definir nuevos conceptos en el diseño :

  • Inversion of Control (IoC)

  • Dependency Injection (DI)

La utilización de interfaces y la aparición de los frameworks es un primer paso para minimizar estas dependencias entre componentes, aunque pagamos un precio: la configuración en ficheros xml se empieza a volver monolítica, difícil de mantener, crítica y es fácil cometer errores.

Inversión de Control (IoC) & Inyección de Dependencia (DI)

Inyeccion de Dependencia (Dependency Injection, DI)

Es un término comúnmente confundido con Inversion de Control.

En un escenario en el que utilizamos IoC, delegamos en una entidad “Contenedor” no solo la gestión de las instancias, sino la inyección de las sub-partes (dependencias). Si una venta se compone de un cliente y un producto, al instanciar un objeto venta la DI le inyecta directamente su cliente y su producto específicos.

La arquitectura de Spring esta basada en patrón de diseño llamado “Dependency Injection”, Rob Harrop define a este patrón como: “Es la manera de externalizar la creación y el manejo de las dependencias de los componentes”.

Clases e InterfacesPara comprender el patrón Dependency Injection considere la figura 1 la cual es un diagrama de clases, la clase Foo depende de una instancia de la clase Bar, para realizar algún tipo de procesamiento, tradicionalmente en la clase Foo se tendría la sentencia Bar bar=new Bar(); para crear el objeto bar, usando Dependency Injection una instancia de Bar (o bien una subclase) es proporcionada a la clase Foo en tiempo de ejecución por algún proceso externo, es decir la clase Foo no llama a crear el objeto bar si no que el proceso externo le proporciona el objeto bar a la clase Foo, es por eso que Rod Johnson define a Dependency Injection con la frase: “No me llames, yo te llamo”.

James Shore explica concisamente, “consiste en dar valores a las variables de un objeto”. Una clase, para estar completa necesita información, datos de otra. Con la DI, lo que hacemos es proporcionárselos, ya no tiene que pedir esos datos, se le dan.

1La idea se basa en que dado un objeto, “algo” resuelva sus dependencias, inyectandoselas ya sea a través de métodos setXXX o de uno de los constructores del objeto; para que esto sea posible, ese “algo” debe manejar el ciclo de vida del objeto.

Tipos de DI según Martin Fowler:

  1. TIpo 1 – Inyeccion de Interface.
  2. Tipo 2 – Inyeccion de Setter.
  3. Tipo 3 – Inyeccion de Contructor.

1Jorge Rodriguez, Interplanet S.A (Chile)

Inyeccion de Dependencia (Dependency Injection, DI)

Inversión de Control (Inversion of Control, IoC)

<!– @page { margin: 2cm } P { margin-bottom: 0.21cm } –>

Es una técnica que inverte el flujo tradicional. Lo tradicional es que el código que implementes llame a las librerías; la inversión de control ocurre cuando son las librerías las que llaman a tu código.

En cierto modo es una implementación del Principio de Hollywood (no nos llames a nosotros; nosotros te llamaremos a tí.), una metodología de diseño de software.

En Spring, la inversión de control consiste en ceder el control a una entidad externa a la aplicación, llamada “Contenedor”, que se encargará de gestionar las instancias (así como sus creaciones y destrucciones).

¿Quién determina cómo deben inyectarse las dependencias?: El framework de Inversión de Control según los ficheros xml de configuración.

Beneficios

  • Elimina la responsabilidad de buscar o crear los objetos dependientes y la traslada a la configuración

  • Reduce el acoplamiento entre objetos

  • Fomenta el diseño basado en interfaces

  • Permite reconfigurar una aplicación sin modificar el código.

Se puede interpretar como que el Contenedor es un robot. Contiene piezas, engranajes, un Sistema Operativo, memoria, microprocesador… El contenedor esta esperando que le indiquemos que debe realizar para hacerlo, necesita que le programemos unas rutinas para trabajar. Esas rutinas configuradas mediante documentos xml, *.properties, permiten al robot saber que es lo que tiene que hacer. Pero es Inteligente, no le tienes que programar todo de arriba abajo, solo unas partes.

Inversión de Control (Inversion of Control, IoC)

Aspect Orient Programming (AOP)

<!– @page { margin: 2cm } P { margin-bottom: 0.21cm } –>

Entre los objetivos que se ha propuesto la programación orientada a aspectos están principalmente el de separar conceptos y el de minimizar las dependencias entre ellos. Con el primer objetivo se consigue que cada cosa esté en su sitio, es decir, que cada decisión se tome en un lugar concreto, con el segundo se tiene una pérdida del acoplamiento entre los distintos elementos.

De la consecución de estos objetivos se pueden obtener las siguientes ventajas:

  • Un código menos enmarañado, más natural y más reducido.

  • Una mayor facilidad para razonar sobre las materias, ya que están separadas y tienen una dependencia mínima.

  • Más facilidad para depurar y hacer modificaciones en el código.

  • Se consigue que un conjunto grande de modificaciones en la definición de una materia tenga un impacto mínimo en las otras.

  • Se tiene un código más reusable y que se puede acoplar y desacoplar cuando sea necesario.

Básicamente consiste en implementar por un lado un aspecto, que es un trozo de código común a ejecutar en varios métodos/clases. Por otro lado configuraremos los puntos de cruce, que son los lugares en los que el aspecto cruza con el código, es decir, cuando serán ejecutados. Para que funcione debemos interponer un Proxy entre la clase y el aspecto. De esta forma podemos acoplar/desacoplar aspectos comunes sin tocar código.

Los aspectos no suelen ser unidades de descomposición funcional del sistema, sino propiedades que afectan al rendimiento o a la semántica de los componentes. Algunos ejemplos de aspectos son, los patrones de acceso a memoria, la sincronizan de procesos concurrentes, el manejo de errores, etc.

Debido a la escasa literatura en español sobre el tema, se presenta la terminología original en inglés.

  • Aspect (Aspecto) es la funcionalidad que se cruza a lo largo de la aplicación (cross-cutting) que se va a implementar de forma modular y separada del resto del sistema. El ejemplo más común y simple de un aspecto es el logging (registro de sucesos) dentro del sistema, ya que necesariamente afecta a todas las partes del sistema que generan un suceso.

  • Join point (Punto de Cruce o de Unión) es un punto de ejecución dentro del sistema donde un aspecto puede ser conectado, como una llamada a un método, el lanzamiento de una excepción o la modificación de un campo. El código del aspecto será insertado en el flujo de ejecución de la aplicación para añadir su funcionalidad.

  • Advice (Consejo) es la implementación del aspecto, es decir, contiene el código que implementa la nueva funcionalidad. Se insertan en la aplicación en los Puntos de Cruce.

  • Pointcut (Puntos de Corte) define los Consejos que se aplicarán a cada Punto de Cruce. Se especifica mediante Expresiones Regulares o mediante patrones de nombres (de clases, métodos o campos), e incluso dinámicamente en tiempo de ejecución según el valor de ciertos parámetros.

  • Introduction (Introducción) permite añadir métodos o atributos a clases ya existentes. Un ejemplo en el que resultaría útil es la creación de un Consejo de Auditoria que mantenga la fecha de la última modificación de un objeto, mediante una variable y un método setUltimaModificacion(fecha), que podrían ser introducidos en todas las clases (o sólo en algunas) para proporcionarlas esta nueva funcionalidad.

  • Target (Destinatario) es la clase aconsejada, la clase que es objeto de un consejo. Sin AOP, esta clase debería contener su lógica, además de la lógica del aspecto.

  • Proxy (Resultante) es el objeto creado después de aplicar el Consejo al Objeto Destinatario. El resto de la aplicación únicamente tendrá que soportar al Objeto Destinatario (pre-AOP) y no al Objeto Resultante (post-AOP).

  • Weaving (Tejido) es el proceso de aplicar Aspectos a los Objetos Destinatarios para crear los nuevos Objetos Resultantes en los especificados Puntos de Cruce. Este proceso puede ocurrir a lo largo del ciclo de vida del Objeto Destinatario:

    • Aspectos en Tiempo de Compilación, que necesita un compilador especial.

    • Aspectos en Tiempo de Carga, los Aspectos se implementan cuando el Objeto Destinatario es cargado. Requiere un ClassLoader especial.

    • Aspectos en Tiempo de Ejecución.

Aspect Orient Programming (AOP)

Contenedor

<!– @page { margin: 2cm } P { margin-bottom: 0.21cm } –>

Se puede definir como una estructura de datos, array… que contiene una colección de objetos. Utilizados para almacenar información de manera organizada siguiendo unas normas de acceso.

En POO, un contenedor es una clase capaz de almacenar información de otras clases.

En gráficos, un contenedor es una aplicación que permite editar, crear borrar…

Spring es un contenedor porque contiene código, que permite interaccionar a través de su código con otras aplicaciones, de una manera mas ordenada y fácil.

Contenedor

Contenedor J2EE

<!– @page { margin: 2cm } P { margin-bottom: 0.21cm } –>

Los contenedores J2EE proporcionan acceso a los servicios subyancentes del entorno del Servidor J2EE mediante contenedores para diferentes tipos de componentes. Tradicionalmente, los desarrolladores de aplicaciones tenían que escribir código para el manejo de transaciones, manejo del estado, multi-threads, almacenamiento de recursos, etc. Ahora el contenedor J2EE proporciona estos servicios permitiendo que te puedas concentrar en resolver los problemas de negocio.

Los contenedores son el interface entre un componente y la funcionalidad de bajo nivel específica-de-la-plataforma que soporta el componente. Por ejemplo, antes de poder ejecutar un componente Web, un bean enterprise o un componente de una aplicación cliente, debe ensamblarse dentro de una aplicación J2EE y desplegarse dentro de su contenedor.

El proceso de ensamble implica especificar las configuraciones del servidor para cada componente de la aplicación J2EE y para la propia aplicación J2EE. Estas configuraciones personalizan el soporte subyacente proporcionado por el servidor J2EE, que incluye servicios como JNI, seguridad, control de transaciones, etc.

El servidor J2EE proporciona contenedores para Enterprise JavaBeans (EJB) y para componentes Web. El contenedor EJB maneja la ejecución de los beans enterprise de las aplicaciones J2EE, mientras que el contenedor Web maneja la ejecución de las páginas JSP y los componentes servlets de la aplicación J2EE. Otros contenedores distintos a estos son el contenedor de aplicaciones clientes y el contenedor de applets, que no son parte del servidor J2EE porque residen en la máquina del cliente:

Una contenedor de aplicaciones cliente maneja la ejecución de los componentes de la aplicación cliente mientras que un contenedor de Applets maneja la ejecución de los applets. Normalmente están en el JRE (Java Runtime Environment) y el navegador Web compatible con Java, respectivamente.

Contenedor J2EE