Buenas Practicas De Configuracion De Spring
Una recopilacion de buenas practicas a la hora de configurar Spring Framework.
Contenido
- 1 Evitar el uso de autowiring
- 2 Usar convenciones de nomenclatura
- 3 Usar formas abreviadas de configuración
- 4 Utilizar type en vez de index para los argumentos del constructor
- 5 En lo posible, reutilizar definiciones de Beans
- 6 Integrar archivos de configuración mediante ApplicationContext y no utilizando import
- 7 Usar ids como identificadores de beans
- 8 Usar dependency-check durante la fase de desarrollo
- 9 Agregar una descripcion en el encabezado de cada archivo de configuración
- 10 Comunicar los cambios al equipo
- 11 Utilizar inyección de dependencias por Setter en vez de por Constructor
- 12 No abusar de la inyección de dependencias
- 13 Leer más
Evitar el uso de autowiring
Spring puede hacer autowiring de dependencias haciendo instropeccion de las clases, logrando de esta manera evitar que uno tenga que especificar las propiedades del bean o los argumentos de los constructores. Se puede hacer autowiring de las propiedades de los beans ya sea por nombre de propiedad o por tipo. En el caso de los constructores, solo se permite por tipo. Tambien se puede especificar el modo "autodetect autoriwiring", que deja que Spring elija el mecanismo mas apropiado. Miremos el siguiente código:
<bean id="invasorService"
class="com.dosideas.spring.InvasorService" autowire="byName"/>
Los nombres de las propiedades de la clase InvasorService son usadas para buscar instancias de beans en el contenedor. El uso de Autowiring nos salva de tipear mucho código. De todas formas, nunca deberiamos utilizar Autowiring en una aplicación real porque perjudicamos la legibilidad de nuestro archivo de configuración y la mantenibilidad del mismo. Parece una buena idea hacer que nuestros archivos XML de configuración sean pequeños, pero esto aumenta en gran medida la complejidad de comprensión de la solución.
Spring tambien nos permite mezclar las dos técnicas (Autowiring y no-autowiring), pero con esto solamente lograriamos hacer mucho mas confusa la configuración.
Usar convenciones de nomenclatura
Esta es la misma filosofia que utilizamos con el código Java. Usar una nomenclatura clara, descriptiva y consistente en todo el proyecto es de gran ayuda para que los desarrolladores entiendan la configuración XML. Para el id de los Beans, por ejemplo, se puede seguir la convención de atributos de una clase Java. El Bean ID de una instancia de InvasorDAO podria ser InvasorDAO. En proyectos grandes, se puede agregar el nombre del paquete como prefijo del Bean ID.
Usar formas abreviadas de configuración
Las formas abreviadas son mas faciles de leer, dado que transforma el valor de los elementos hijos en atributos del elemento padre. Por ejemplo:
<bean id="invasorService"
class="com.dosideas.spring.InvasorService"> <property name="nombreInvasor"> <value>Zim</value> </property> <constructor-arg> <ref bean="invasorDAO"> </constructor-arg>
</bean>
puede ser reescrito de forma abreviada:
<bean id="InvasorServic"
class="com.dosideas.spring.InvasorService"> <property name="nombreInvasor" value="Zim"/> <constructor-arg ref="invasorDAO"/>
</bean>
Este feature esta disponible desde la versión 1.2 de Spring. Vale aclarar que no existe abreviacion para el elemento <ref local="...">.
Esta forma de abreviar nuestra configuración no solo nos evita tipear, tambien deja al archivo XML mucho mas claro.
Utilizar type en vez de index para los argumentos del constructor
Spring permite utilizar indices (que comienzan en cero) para resolver el problema de ambigüedad cuando un constructor tiene mas de un argumento del mismo tipo, o cuando se utiliza el atributo value para asignar el valor. Por ejemplo, en vez de:
<bean id="InvasorService"
class="com.dosideas.spring.InvazorService"> <constructor-arg index="0" value="Zim"/> <constructor-arg index="1" value="100"/>
</bean>
es mejor utilizar el atributo type de la siguiente manera:
<bean id="invasorService"
class="com.dosideas.spring.InvasorService"> <constructor-arg type="java.lang.String" value="Zim"/> <constructor-arg type="int" value="100"/>
</bean>
Utilizar index es mas sencillo, ya que tipeamos menos, pero es mas propenso a errores y mucho mas dificil de leer que si utilizamos type. Se deberia utilizar index solamente cuando se presenta una ambigüedad en los argumentos del constructor.
En lo posible, reutilizar definiciones de Beans
Spring ofrece un mecanismo de pseudo-herencia que reduce la duplicacion de informacion en los archivos de configuracion. Una definición de un Bean hijo puede heredar la información de configuracion de sus padres, los cuales sirven como un "template" para los beans hijos. En grandes proyectos el uso de este feature deberia ser obligatorio. Todo lo que se necesita hacer es especificar abstract=true en el Bean padre y referenciar a dicho Bean desde los Beans hijos. Por ejemplo:
<bean id="abstractInvasorService" abstract="true"
class="com.dosideas.spring.AbstractInvasorService"> <property name="nombreInvasor" value="Zim"/>
</bean>
<bean id="InvasorService"
parent="abstractInvasorService" class="com.dosideas.spring.InvasorService"> <property name="robotAsignado" value="Gir"/>
</bean>
El bean InvasorService hereda el valor Zim para la propiedad nombreInvasor del bean abstractInvasorService. Una aclaración: Si no se especifica el nombre de una clase un un factory method en la definición de un bean, este bean es implicitamente abstracto.
Integrar archivos de configuración mediante ApplicationContext y no utilizando import
Al igual que el import en los scripts de Ant, el import en Spring es conveniente para unir archivos modularizados de configuración. Por ejemplo:
<beans>
<import resource="InvasorServices.xml"/> <import resource="RobotsServices.xml"/>
<bean id="PlanetaObjetivoService" class="com.dosideas.spring.PlanetaObjetivoService"/>
<beans>
En vez de unirlos dentro del XML utilizando imports, es mucho mas flexible configurarlo a traves del ApplicationContext. Utilizando ApplicationContext tambien hace que nuestra configuración XML sea mas facil de manejar. Se le puede pasar como argumento al constructor de ApplicationContext una lista de archivos de configuración. Nuestro ejemplo anterior quedaria:
String[] serviceResources =
{"PlanetaServices.xml", "InvasorServices.xml", "RobotServices.xml"};
ApplicationContext orderServiceContext = new
ClassPathXmlApplicationContext(serviceResources);
Usar ids como identificadores de beans
Se pueden especificar un name o un id como identificador de beans. Utilizar ids no incrementa la legibilidad, pero puede permitir que el parser XML valide las referencias de los beans. Si los ids no pueden ser utilizados debido a alguna restriccion XML IDREF, se pueden utilizar nombres como identificadores de beans. La restriccion XML IDREF dice que los ids deben comenzar con una letra (o alguno de los pocos caracteres de signo de puntuación permitidos en la especificación XML) seguido de letras, digitos, guiones, guiones bajos, dos puntos, o punto. Es muy raro que en algun proyecto tengamos un problema con algun nombre por no cumplir con estas restricciones.
Usar dependency-check durante la fase de desarrollo
Se puede asignar al atributo dependency-check en la definicion de un bean un valor distinto del default none, como puede ser: simple, objects, o all. Con esto el contenedor puede realizar validaciones de dependencias. Esto es útil cuando todas las propiedades (o cierto grupo de propiedades) de un bean deben ser asignadas explícitamente (o por autowiring...pero ya dijimos lo malo de usar autowiring).
<bean id="invasorService"
class="com.dosideas.spring.InvasorService" dependency-check="objects"> <property name="nombreInvasor" value="Zim"/> <constructor-arg ref="invasorDAO"/>
</bean>
En este ejemplo, el contendedor se asegurara que las propiedades de InvasorService que no sean primitivos o colecciones esten asignadas. Se puede configurar el chequeo de dependencias para que controle que todas las propiedades del bean esten asignadas, pero esto es necesario en raras ocasiones ya que puede que haya propiedades que no necesiten ser asignadas.
Agregar una descripcion en el encabezado de cada archivo de configuración
Es preferible usar ids y nombres descriptivos en vez de utilizar comentarios en los archivos de configuración. Adicionalmente, es útil agregar un encabezado en los archivos de configuración, el cual englobe los beans definidos en el archivo. Por ejemplo:
<beans>
<description> Este archivo define los Invasores que atacaran los disintos planetas. Depende de RobotsServices.xml, el cual provee los servicios de los robots que cada invasor tiene asignado.... </description> ...
</beans>
Comunicar los cambios al equipo
Cuando se esta refactorizando código Java, es necesario asegurarse de actualizar el archivo de configuración para que refleje los cambios realizados e informar estos cambios a los miembros del equipo. El archivo de configuración XML es parte del código y es una parte crítica de la aplicación. La mayoria de las veces es necesario leer tanto el archivo XML como el código java para comprender como funciona algun componente.
Utilizar inyección de dependencias por Setter en vez de por Constructor
Spring provee tres tipos de inyección de dependencias: inyección por constructor, por setter y por método. Usualmente solamente utilizamos las dos primeras.
<bean id="invasorService" class="com.dosideas.spring.InvasorService">
<constructor-arg ref="invasorDAO"/>
</bean>
<bean id="robotService" class="com.dosideas.spring.RobotService">
<property name="robotDAO" ref="robotDAO">
</bean>
En este ejemplo, el bean invasorService usa inyección por constructor, mientras que el bean robotService usa inyección por setter. La inyección de dependencias por constructor garantiza que el bean no será construido con un estado inválido, pero la inyección de dependencias por setters es mucho más flexible, especialmente cuando la clase tiene muchas propiedades y la mayoria de ellas son opcionales.
No abusar de la inyección de dependencias
El ApplicationContext de Spring puede crear los objetos java que sean necesarios, pero no todos los objetos deberian ser creados a través del motor de inyección de dependencias. Como ejemplo, los objetos de dominio no deberian ser creados utilizando inyección de dependencia. Los archivos de configuración pueden sobrecargarse mucho si no se controla bien el crecimiento de los beans definidos. Sobreutilizar la inyección de dependencia puede hacer el archivo de configuración muy complicado y sobrecargado.