Vous êtes sur la page 1sur 8

La misin principal de Spring es la de simplificar el desarrollo de aplicaciones Java, pero seguro que

habis ledo esta frase muchas veces. Probablemente cada framework basado en Java proclama esta
misma idea. Entonces, Por qu Spring es diferente? Qu hace que sea especial y diferente al resto?
Para empezar (y esta es una de las opciones qu ms valoro) Spring se acopla a tu aplicacin sin
obligarte a modificar tu cdigo para utilizar las funcionalidades y beneficios que ofrece. Para usar
Spring no es imprescindible implementar un interfaz propio de Spring o heredar de una clase propia
(puede que para utilizar cierta funcionalidad avanzada s sea necesario, pero para un uso habitual
no); lo que significa que Spring estar ah pero tus clases sern Java puro y duro. Como mucho, tus
clases tendrn anotaciones propias de Spring, pero no dejan de ser anotaciones por lo que tu clase
ser reutilizable en cualquier momento, sin cambios. Esta caracterstica con otros frameworks es
impensable, ya que para poder utilizar dicho framework habrs tenido que implementar un interfaz
propio del framework y a la vez implementar los mtodos establecidos en dicho interfaz; mtodos
que fuera de ese framework no tienen ningn sentido ni utilidad (no hace falta que mencione
ninguno en concreto verdad?). Por tanto, aqui tenemos la primera ventaja: Gracias a Spring,
nuestro cdigo Java puede ser ms limpio, elegante y reutilizable. Elegante y reutilizable ya que la
filosofa de Spring nos gua a programar orientado a interfaces, de modo que toda nuestra
aplicacin sea altamente modular y posea bajo acoplamiento. Veamos cmo en la Segunda ventaja
(Antes de empezar he de avisaros que esta entrada no pretende ser una charla tcnica, es ms, est
orientada a ser divulgativa y a mostrar lo que podemos hacer con Spring sin entrar en detalles de
cmo hacerlo por no hablar de que es un peln extensa :P )

Segunda ventaja: Inyeccin de Dependencias o IoC (Inversion of


Control)
Inyeccin de dependencias? Eso tiene pinta de ser un paradigma de programacin nuevo y por el
nombre suena a que debe ser complicado, no? Realmente no lo es, de hecho todos los que hemos
programado alguna vez lo hemos utilizado de una forma u otra, simplemente no sabamos que se
llamaba as.
Lo habitual es que nuestra aplicacin est compuesta de dos o ms clases que deben interactuar
entre ellas para llevar a cabo determinada funcionalidad. Lo normal era que cada objeto fuera
responsable de adquirir las referencias al resto de objetos con los que colabora, sus dependencias.
Esto, a parte de ser una mala prctica, provoca que nuestras clases se encuentren fuertemente
acopladas y que llevar a cabo tareas de Test, sea mucho ms complejo. Veamos un ejemplo:

public class Elfo implements Guerrero {

private Arma arma;

public Elfo(){
arma = new Arco();
}

@Override
public void ataca() {
arma.dispara();
}
}
Como vis en el ejemplo, Elfo crea su propia instancia de Arma, un Arco. Esto provoca que las
instancias de Elfo estn fuertemente acopladas a la clase Arco, lo que obviamente fuerza a que un
Elfo slo pueda utilizar un Arco como arma. Qu ocurre si queremos darle una espada?
Este fuerte acoplamiento nos lleva a otro problema. Qu ocurre si queremos aplicar test unitarios
al mtodo ataca()? No tenemos ninguna forma de probar diferentes implementaciones (o stubs o
mocks) de la clase Arma, ya que un Elfo utiliza directamente una instancia de clase Arco
Aqu es donde entra en juego el concepto Inyeccin de Dependencias: Los objetos reciben sus
dependencias en tiempo de creacin, de manera que ellos no son responsables de la instanciacin e
inicializacin de esas dependencias. Por eso se dice que las dependencias se inyectan en el objeto
que las necesite, porque de esta forma, el objeto no debe preocuparse de crear esas instancias.
Veamos el mismo ejemplo, pero ahora con inyeccin de dependencias:

public class Elfo implements Guerrero {


private Arma arma;

public Elfo(Arma a){


arma = a;
}

@Override
public void ataca() {
arma.dispara();
}
}
Como vis, an pareciendo lo mismo, el panorama cambia ampliamente. En esta ocasin, las
instancias de Elfo no crean una instancia de Arma, por tanto podrn utilizar cualquier arma que se
les asigne desde el constructor, ya que todas las armas deben implementar el interfaz Arma. Aqu
se aprecia nuevamente la ventaja de programar orientado a Interfaces (os suena
polimorfismo?? :P). Este tipo de inyeccin de dependencias se conoce con el nombre de: Inyeccin
por constructor.
Lo ms importante es que la clase Elfo, no est acoplada a ninguna implementacin concreta del
interfaz Arma, por tanto no importa que arma utilice siempre y cuando ese arma implemente el
interfaz Arma. Si un objeto slo conoce a sus dependencias mediante su interfaz (no por
su implementacin), podremos cambiar la implementacin de esa dependencia como
consideremos necesario sin que el objeto sea consciente de esos cambios y, por tanto,
sin que le afecten.
Pero, y si en mitad de una batalla queremos cambiar el arma de nuestro guerrero? Aqui entra en
juego el segundo tipo de inyeccin de dependencias: Inyeccin por setter.

public class Elfo implements Guerrero {


private Arma arma;

public Elfo(Arma a){


arma = a;
}
//Nuevo metodo setter
public void setArma(Arma a) {
arma = a;
}
@Override

public void ataca() {


arma.dispara();
}
}
Como vemos, ahora la inyeccin de dependencias no la estamos realizando nicamente en tiempo
de construccin, si no que puede realizarse en cualquier momento durante la ejecucin de la
aplicacin, lo que nos permitir cambiar las instancias concretas de Arma cuando sea oportuno.
Vale, muy bien, es todo muy bonito, pero si la propia clase Elfo no crea e inicializa sus instancias de
Arma, quin lo hace? cundo? cmo? .. Obviamente esta accin debe llevarse a cabo por
unatercera parte. Una parte encargada de que cada objeto reciba las dependencias que requiere
para su correcta compilacin y ejecucin. Y aqu es donde entra en juego Spring. l va a ser el
encargado de completar ese puzzle de dependencias segn nosotros le indiquemos, l va a realizar
toda las inyecciones que sean necesarias para que nuestra aplicacin funcione. Por tanto Spring ser
el encargado de: Inicializar todas nuestras clases (llamando a sus constructores) e inyectar todas las
instancias requeridas. Y lo que es ms importante, todo esto lo har sin que nosotros tengamos que
tocar ni un punto y coma de nuestra implementacin de Elfo o Arma

Tercera ventaja: Aspectos (AOP)


Qu es la programacin orientada a aspectos? Teora en base a este concepto hay
mucha,muchisima, pero si resumimos mucho y vamos a buscar la esencia sobre la que se apoya
AOP, podramos decir que aplicar aspectos a nuestro cdigo se basa en aadir funcionalidad extra a
nuestras clases y/o mtodos sin alterar ni el comportamiento ni el cdigo original del mtodo o
clase. (Esta definicin totalmente informal es ma, por tanto aqu podis discrepar todo lo que
consideris oportuno ;) )
Hay muchas actividades que resultan comunes a la mayora de aplicaciones software, por ejemplo:
tareas de logging, seguridad, control de transacciones Cualquiera que haya programado una
aplicacin ms o menos grande sabe que antes o despus debes enfrentarte a ellas, pero: Debe
nuestra aplicacin participar activamente en estas funciones (o aspectos)? No sera mejor que
nuestra aplicacin se enfocara nicamente en su objetivo principal y dejara que esta funcionalidad
la llevara a cabo una tercera parte? Obviamente la respuesta es s. Si estamos programando un
mtodo que se encargue de obtener un listado de todos los clientes de la base de datos, este mtodo
slo debe preocuparse de obtener ese listadosi el usuario tiene permisos o no para hacerlo no es
tarea suya el comprobarlo, o si debe dejar trazas de log, tampoco debe ser tarea del propio mtodo.
Esta funcionalidad extra que cruza por varios puntos de nuestra aplicacin (logging, seguridad, etc.)
es lo que se conoce como Cross-cutting concerns. La programacin orientada a aspectos nos va a
permitir mantener dos principios bsicos en un buen diseo: SoC y DRY.

SoC (Separation of Concerns) y DRY (Dont repeat yourself) nos ayudarn a crear e implementar
clases y mtodos que sigan el patrn 1:1, es decir, Una determinada funcionalidad debe estar
implementada en un slo sitio de nuestra aplicacin y slo debe llevar a cabo esa funcionalidad.
Por ejemplo, qu ocurrira en nuestra clase Elfo si quisiramos que cada vez que un elfo ataque, se
escriba una traza indicando qu elfo ha atacado?
Podramos hacer lo siguiente:

public class Elfo implements Guerrero {


private Arma arma;
private String nombre;

public Elfo(Arma a, String n){


arma = a;
nombre = n;
}
//Nuevo metodo setter
public void setArma(Arma a) {
arma = a;
}
@Override
public void ataca() {
arma.dispara();
System.out.println("Yo "+nombre+", He disparado !!!!");
}
}
Y si ahora queremos que no slo la clase Elfo escriba trazas cada vez que ataque, sino que tambin la
clase Enano debe escribir trazas tras atacar a un enemigo Modificamos tambin la clase Enano
para aadir las trazas?

Obviamente si seguimos por ese camino, vamos a llegar inevitablemente a un muy mal diseo de
nuestro cdigo, que desembocar en dos sntomas inequvocos de que necesitamos aplicar SoC y
DRY (y por ende AOP):
1.

Tangling (o enmaraamiento de nuestro cdigo): Los mtodos cada vez realizan ms


tareas a parte de la tarea principal; lo que conlleva que el cdigo sea ms dificil de leer, revisar,
comprender, depurar, mejorar

2.

Scattering (dispersin del cdigo): Una determinada funcionalidad est dispersa por
mltiples clases y/o mtodos lo que implica que cualquier tarea de refactorizacin de cdigo se
va a hacer muy tediosa y originar fallos y errores que no tenemos contemplados (si la
aplicacin es muuuy grande y el cdigo est muy enmaraado y disperso, quizs no
conozcamos los efectos secundarios que puede tener un determinado cambio en el cdigo)

Aqu es donde Spring aplica su magia de AOP de una manera muy elegante; nosotros simplemente
tenemos que decirle a Spring lo siguiente: Tras la ejecucin del mtodo ataca() del interfaz
Guerrero, ejecutame el mtodo loggingAtaque() de la clase Logging.
La clase Logging ser una clase que nosotros habremos creado y que se encargar nicamente de
realizar trazas de log de diversos mtodos de nuestra aplicacin. No es mucho ms legible y
elegante nuestro cdigo ahora? Y fijos ni siquiera hemos tenido que modificar la clase Elfo, o la
clase Enano porque obviamente ese horrible System.out.println() que habamos escrito
anteriormente ya no sera necesario.
Un ejemplo ms claro en el que se demuestra que utilizar AOP con Spring es una gozada, es el
ejemplo de la seguridad. Retomemos nuestro mtodo encargado de listar los clientes almacenados
en la base de datos, tiene sentido hacer esto?:

public ArrayList<Cliente> listClientes(){


if (usuarioEnSession.tienePermisos()){
//Codigo para conectarse a BD y devolver los
clientes...
//....
}else{
throw new NotAuthorizedException();
}
}

Es decir, cada vez que queramos que un mtodo acceda a la base de datos, el mtodo debe
encargarse de controlar si el usuario tiene permisos?? Nuevamente, queda mucho ms elegante
hacer algo del estilo a lo siguiente:
Oye Spring, mira: Antes de ejecutar el mtodo listClientes() de la clase ClienteDAO,
ejecuta el mtodo tienePermisos(usuarioEnSession) de la clase Seguridad.
De esta forma nuestro cdigo de listClientes() quedara:

public ArrayList<Cliente> listClientes(){


//Codigo para conectarse a BD y devolver los clientes...
//....
}
Mucho ms limpio, no?
Realmente una vez que te acostumbras a programar orientado a aspectosse hace muy dificil
entender y tratar de encontrar una respuesta a la pregunta: Para qu voy a utilizar AOP en mi
cdigo?
En este punto he de reconocerle un gran mrito a Spring. Nunca haba llegado a comprender
completamente qu significa (a efectos prcticos) la AOP hasta que comenc a utilizarla con Spring
y mira que durante mis aos en la carrera y en diversas asignaturas de doctorado trataron de
venderme la AOP como el no va ms.
Como vis aunque el trmino suene un poco intimidatorio, su aplicacin es realmente sencilla y muy
lgica, de esas cosas que una vez que las ves piensas: Cmo nadie haba pensado en esto antes?
Pero, dejemos por hoy la AOP y pasemos a ver otra ventaja muuuy interesante que nos aporta
Spring:

Cuarta ventaja: Eliminar el cdigo boilerplate


Seguro que habis ledo u odo muchas veces esta palabra referida al cdigo fuente: boilerplate. Este
trmino ingls se refiere al cdigo que es necesario para nuestra aplicacin, pero que resulta muy
pesado escribirlo una y otra vez. No hay que confundirlo con cdigo inutil, ya que este cdigo
boilerplate es necesario, nuestra aplicacin lo requiere y sin l no funcionara, sin embargo, es
verdaderamente molesto tener que estar escribiendolo en cada mtodo que lo necesitamos (o hacer
copy/paste cada vez).
Un claro ejemplo de este tipo de cdigo lo encontramos a la hora de utilizar JDBC en Java para
consultar datos de una base de datos: Obtn la conexin, abre la conexin, prepara tu query,
configura sus parmetros, ejecuta tu query, procesa los resultados, cierra las conexiones, procesa
las excepciones..os suena verdad? Al final resulta que para ejecutar una simple Select, debemos

escribir unas 20 lneas de cdigo 15 de las cuales sern siempre iguales. Pero no slo pasa esto con
JDBC, tenemos este mismo comportamiento si utilizamos REST o JMS en Java.
En este caso Spring elimina este cdigo boilerplate mediante el uso de Templates o Plantillas de
Cdigo. De esta forma, en Spring existen plantillas para JDBC, JNDI, JMS, REST, . todas las API
que tengan cdigo susceptible de ser repetitivo, tendrn su correspondiente plantilla en Spring.
En el caso de JDBC, tenemos la plantilla JdbcTemplate, que se encargar de encapsular todo el
cdigo repetitivo de las conexiones a base de datos, para que nosotros nos centremos en lo que
realmente nos interesa: La query y los resultados que obtenemos. De esta forma le diremos a
Spring: Mira, ejectame esta query y los resultados (en caso de que haya alguno) me los mapeas a
este objeto mediante este mtodo. Pero esto es para el caso en el que los resultados que devuelve
nuestra query estn compuestos por cierto nmero de filas y columnas, si el resultado es mucho ms
simple, todo se simplifica, por ejemplo:

int
num_clientes
=
JdbcTemplate(datasource).queryForInt("select
clientes");

count(*)

new
from

Como vis las plantillas en Spring nos permitirn que nuestro cdigo sea mucho ms limpio y
elegante, a la vez que evitamos tener que procesar todas esas Excepciones de tipo SQLException,
que por otra parte nunca he sabido muy bien qu hacer con ellas Si en algn momento de la
ejecucin de tu cdigo se lanza una SQLException Cmo se supone que debe actuar nuestro
cdigo?? Es decir, son excepciones no recuperablesuna vez que salta una, no podemos hacer
mucho: DUPLICATE PRIMARY KEY . no tenemos muchas opciones, como mucho avisar al
usuario con un mensaje de error pero poco ms. entonces mi pregunta es: Por qu estamos
obligados a capturarlas? Por qu no son unchecked exceptions? . Pero bueno, ese ya es otro
tema (Por cierto, Spring tambin ha pensado en esto y nos permite mapear todas las excepciones a
un conjunto de excepciones propias de tipo uncheked)
..
Y llegados a este punto he de decir que no trabajo para SpringSource ni VMware (aunque no estara
nada mal), ni me pagan por escribir todo esto; simplemente quera compartir con todos vosotros
mis pensamientos y sentimientos sobre Spring y animar encarecidamente a todos los que queris
probarlo a hacerlo, porque cuanto ms te adentras en el funcionamiento de Springms te
engancha; y si antes os preguntbais: Y para qu sirve Spring? o Para qu voy a utilizarlo? .
veris como la cosa cambia a: Cmo NO voy a utilizar Spring?
Y ya sabis cualquier mejora, sugerencia, propuesta, duda ser siempre bien recibida ;)

Vous aimerez peut-être aussi