1 July, 2010

Aprendiendo a desarrollar con tests

El proyecto en el que trabajo actualmente es mi primera experiencia mas o menos seria con el desarrollo orientado a tests. Al principio los escribía después de implementar la funcionalidad requerida, pero por recomendación de un compañero pasé a escribirlos antes (TDD). Escribes el test que falla porque todavía no tienes implementada la funcionalidad que lo hace pasar, implementas la funcionalidad para que pase el test, y le das las vueltas que necesites a tu código (para hacerlo mas legible o eficiente) si el test pasa tu código es válido.

Cuesta iniciarse en esta forma de desarrollo, cuesta escribir buenos tests, cuesta mantenerlos, pero como se suele decir es una inversión con retorno y me estoy convenciendo de que estos son imprescindibles para profesionalizar en gran parte nuestro trabajo. Es mas, ahora me acuerdo de algunos proyectos en los que trabajé anteriormente y lo bien que nos habrían venido en el testeo de algunos procesos complejos, la de tiempo que habría ahorrado y sobre todo la tranquilidad que habría aportado al equipo.

De todas formas, aun tenemos algunas lagunas, por lo menos yo no tengo nada claro como se debe mantener un juego de datos coherente con el que hacer pasar los tests, sin que esto lleve mas tiempo que beneficio, por el momento tenemos 2 aproximaciones:
- Almacenar con dbunit un juego de datos (xml, cvs, etc) con unos identificadores reservados (por ej de 1 a 500), e importarlos a BD cada vez que pasemos los tests.
- Usar una BD independiente contra la que ejecutar los tests.
Usaremos la segunda opción aunque insisto, no tengo una postura clara sobre el tema y no termina de convencerme.

Hay quien dice que lo mejor es tener los X registros que necesitamos en xml para cada test de forma independiente, solo esos X registros ni uno mas ni uno menos. Me gusta la idea de tener muy controlados los registros que pruebas y que todo el equipo los conozca, del identificador 1 al 20 entidad en Y estado, del 20 al 40 en Z estado etc etc.

Al final escribir y mantener tests y sus datos de prueba no es gratis, lleva tiempo y creo que no solo cuando empiezas, pero debes convecerte de que es la forma de garantizar un software de calidad, de desarrollar con tranquilidad sabiendo que si haces algo que afecte a otra parte del sistema te vas a enterar antes que tu cliente. No creo que se escriban tests para hacer el desarrollo mas rápido sino para hacerlo mejor.

Recomiendo especialmente un par de podcasts de javahispano sobre el tema:

http://www.javahispano.org/contenidos.item.action?id=1985256&menuId=JH_PODCASTS

http://www.javahispano.org/contenidos.item.action?id=6813316&menuId=JH_PODCASTS

Y habrá que seguir leyendo y buscar mas opiniones de gente con experiencia.

30 January, 2009

Volviendo a j2ee, comenzando con Maven (eclipse, tomcat)

Este pequeño descanso en la uoc esta viniendo muy bien, tanto para descansar como para probar cosillas que tenía en el baúl de los recuerdos, ya sabéis, para eso de "sentirse vivo" tecnológicamente hablando.

Después de 2 días iniciándome en RoR, en realidad de rails apenas he visto nada todavía, simplemente he preparado el entorno, familiarizado con ruby, me peleé un poco con las gemas y mysql, y ejecuté algunos de sus comandos para crear una aplicación rails, modelo, controlador.
Logo maven
Pues eso, que después de estos 2 días y por razones que no vienen a cuento he estado probando maven (desde el curso de j2ee tenía pendiente echarle un vistazo). La experiencia esta siendo muy satisfactoria, lejos de la complejidad de la que muchos compañeros me habían hablado.

Maven al igual que ant es una utilidad para... automatizar muchas de las tareas en el desarrollo de un proyecto (compilar, desplegar, descargar librerías, pasar tests de unidad, empaquetar, etc etc). Si conoceis ant estaréis pensando que no es nada nuevo, en realidad se podría decir que es una evolución de ant, incluso podemos integrar las dos utilidades para ejecutar tareas ant desde maven.

Comentar que un proyecto maven tiene una estructura global mas o menos fija (que se puede variar, pero ni lo he probado ni lo necesito). Cuando creamos un proyecto mediante la linea de comandos mvn archetype:create -DgroupId=net.jsanroman -DartifactId=aprendiendoMaven, o añadiendo el parámetro -DarchetypeArtifactId=maven-archetype-webapp para un proyecto web, se crea una estructura como la que podeis encontrar en la documentación.

Maven, además de la maravillosa funcionalidad de descarga automática de jars, bien de un repositorio externo, o de nuestra propia red local (típica situación de un equipo de desarrollo de muchas personas sobre un mismo proyecto), tiene preparadas para nosotros multitud de tareas y plugins, por ejemplo el despliegue de nuestro proyecto en un tomcat mediante el tomcat-maven-plugin, simplemente ejecutando mvn tomcat:deploy, aunque antes tendremos que configurar ciertos parametros en el fichero de configuración de maven pom.xml:
dentro de proyect>build:

  1. <plugin>
  2.    <groupId>org.codehaus.mojo</groupId>
  3.    <artifactId>tomcat-maven-plugin</artifactId>
  4.    <configuration>
  5.       <warFile>${project.build.directory}/${project.build.finalName}.war</warFile>
  6.       <update>true</update>
  7.       <path>/facturablock_plain</path>
  8.       <username>admin</username>
  9.       <password>admin</password>
  10.    </configuration>
  11. </plugin>

Configuramos por ejemplo en path de la aplicación a desplegar, el usuario y clave de nuestro manager de tomcat, y la localización de nuestro fichero war a desplegar, aquí mas documentación.

Para que maven sepa que jars debe descargar para nuestro proyecto también lo indicaremos en este mismo fichero pom.xml:

  1. <dependency>
  2.    <groupId>javax.servlet</groupId>
  3.    <artifactId>servlet-api</artifactId>
  4.    <version>2.4</version>
  5.    <scope>compile</scope>
  6. </dependency>

Le indicamos que se descargue la api de servlets. Tenemos un listado completo de librerias en http://mirrors.ibiblio.org/pub/mirrors/maven2/.

Maven se integra con diferentes ide's: netbeans, idea, eclipse. Yo solo he probado con eclipse, para el que hay varios plugins, aunque sin duda para mi el mejor es m2eclipse. No cometáis la misma torpeza que yo, que con las ansias de avanzar ni me fijé en el tipo de errores que daba su instalación, y simplemente que depende de otros plugins para poder ser instalado, aquí tenéis la lista http://docs.codehaus.org/display/M2ECLIPSE/Installation+Requirements.

Aunque todavía me quedan muchas cosas que ver de maven, métricas o integración continua, ya tengo lo básico en funcionamiento, y aquí dejo los 4 comandos básicos, en realidad son "mi recordatorio" que soy muy despistado :$:

  • Creamos nuevo proyecto: mvn archetype:create -DgroupId=net.jsanroman -DartifactId=aprendiendoMaven -DarchetypeArtifactId=maven-archetype-webapp
  • Compilamos proyecto: mvn compile
  • Empaquetamos proyecto: mvn package
  • Copiar jar de proyecto a repositorio local de maven: mvn install
  • Desplegar proyecto web en tomcat: mvn tomcat:deploy
  • Generar sitio web (si si como el de maven): mvn site:site

9 July, 2008

Curso J2EE (12ª semana) integración spring+struts, quartz y appfuse

Semana 12ª y continuamos integrando librerías con spring, como veis tenemos un montón y cada vez mas spring es nuestro punto de unión entre todas ellas.

Tenemos 3 formas de integrar struts y spring:

Extendiendo la clase ActionSupport:
Creamos nuestro action que extenderá de ActionSupport, dentro cargaremos el contexto de spring manualmente y obtendremos los bean necesarios y definidos en el fichero de configuración de spring:

  1. public class ObtenerFacturaAction extends ActionSupport {
  2.       public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)
  3.             throws IOException, ServletException {
  4.             ApplicationContext ctx = getWebApplicationContext();
  5.             FacturaManager facturaManager = (FacturaManager) ctx.getBean("facturaManager");
  6. ...

Definimos nuestras acciones en struts-config.xml

  1. <action path="/obtenerFactura"
  2.         type="net.jsanroman.spring.struts.actions.ObtenerFacturaAction">
  3.           <forward name="success" path="/WEB-INF/facturas/fichaFactura.jsp"/>
  4. </action>
  5. ...

y a spring en este caso le toca proporcionar los beans que dispondremos en las clases actions:

  1. ...
  2. <bean id="facturaManager"
  3.    class="net.jsanroman.spring.struts.manager.FacturaManagerImpl"/>
  4. ...

Un gran acoplamiento entre spring y struts.

Empleando DelegatingRequestProcessor:
Debemos añadir a struts-config.xml

  1. <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>

además de definir las acciones en struts deberemos definirlas también como beans en spring:

  1. <bean name="/obtenerFactura" class="net.jsanroman.spring.struts.actions.ObtenerFacturaAction">
  2.    <property name="facturaManager">
  3.       <ref bean="facturaManager"/>
  4.    </property>
  5. </bean>

Empleando DelegatingActionProxy:
En cada acción definida en struts-config.xml debemos añadir type = “org.springframework.web.struts.DelegatingActionProxy”. En este caso la ventaja es que podemos aprovechar las capacidades de spring, por ejemplo aop.

Pero en definitiva, un autentico coñazo cualquiera de las formas y una opción que solo deberemos utilizar en casos excepcionales.

Terminamos esta semana con un par de ejemplos primero con la libreria quartz para configurar "tareas programadas". Y el segundo con appfuse librería que nos crea todo el codigo para una completa aplicación web de gestión de una BD dada, basandose en struts (y en la última versión en struts2) tengo pendiente jugar mas con ella pues me dejó muy buen sabor.

Curso J2EE (11ª semana) spring+(aop, velocity), aspectj

Continuamos con spring y hemos aprovechado su módulo aop para introducirnos en la programación orientada a aspectos además también hemos hecho algún ejemplo con aspectj (otra implementación de este paradigma) mas potente que el módulo aop de spring. Por supuesto también tenemos implementaciones de programación orientada a aspectos para otros lenguajes (aspect#, aspect .net, aspectc, phpAspect, etc).

Esta semana también nos ha dado para conocer otra de las librerías que podemos integrar con spring, el motor de plantillas velocity, integrarlo es tan sencillo como declarar los beans de configuración:

  1. <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
  2.       <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
  3. </bean>
  4. <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
  5.       <property name="cache" value="true"/>
  6.       <property name="prefix" value=""/>
  7.       <property name="suffix" value=".vm"/>
  8. </bean>

6 July, 2008

Curso J2EE (9ª,10ª semana) spring

Llegamos a la 9ª semana y le toca el turno a spring, nos extenderemos 2 semanas y un poquito de la siguiente debido a la gran cantidad de herramientas y frameworks con los que podemos integrarlo además aprovecharemos su módulo aop para introducir los conceptos de la programación orientada a aspectos.

Spring no es un framework al uso como los que yo había utilizado, struts, cakephp, jsf. Spring abarca todas las capas de una aplicación, y no solo de una aplicación web, podemos utilizar perfectamente spring para el desarrollo de aplicaciones de escritorio. Spring se compone de diversos módulos siendo indispensable el "core" a partir de este podemos utilizar cualquiera de los existentes dependiendo de nuestras necesidades:

- MVC: Implementación del patrón MVC.

- ORM: Integración con api's de mapeo objeto-relacional (JDO, Hibernate, iBatis).

- AOP: Implementación de programación orientada a aspectos.

- WEB: Contexto de aplicaciones orientado a web. Deberemos utilizarlo para integrar otros frameworks (struts, webwork, etc).

- DAO: JDBC.

Modulos spring

Por esto al principio me chocó un poco la idea que tenía a priori de spring, esperaba un framework típico y me encontré con algo muy diferente. Podríamos decir que spring es el encargado de unir todas las piezas de nuestra aplicación, piezas que pueden ser propias del framework (módulo mvc), o piezas de terceros que se integran a perfección (hibernate, struts, etc). Frameworks como spring se conocen como "contenedores ligeros" y no es el único: http://www.picocontainer.org.

¿Como integra spring todas estas piezas?. Dos conceptos a tener muy en cuenta: inversión de control e inyección de dependencias. Tenemos un montón de información por la red de "que es" y "hace" cada uno aunque a menudo se confunden. Pero digamos que estas dos técnicas hacen posible que spring elimine todas las dependencias y desacople los diferentes módulos que componen un programa, siguiendo el Principio de Hollywood: "no nos llames a nosotros; nosotros te llamaremos a tí".

Para spring un bean será un objecto que el podrá gestionar, lo crea lo destruye lo inyecta donde sea necesario. Así tenemos una interfaz básica BeanFactory que será la encargada de proporcionar los mecanismos necesarios para gestionar estos beans. Para aprovechar las capacidades de spring todo lo que desarrollemos serán beans, solo de esta forma spring podrá inyectar las dependencias que especifiquemos en el fichero de configuración.

Un ejemplo para verlo un poco mas claro:

Tenemos una clase Factura.java:

  1. public class Factura implements Serializable{
  2.    private Integer num;
  3.    private Double importe;
  4.    public Integer getNum() {
  5.       return num;
  6.    }
  7.    public void setNum(Integer num) {
  8.       this.num = num;
  9.    }
  10.    public Double getImporte() {
  11.       return importe;
  12.    }
  13.    public void setImporte(Double importe) {
  14.       this.importe = importe;
  15.    }
  16. }

Tenemos un FacturasManager.java que contiene una lista de facturas y un método que las pinta por pantalla:

  1. public class FacturasManager implements Serializable {
  2.    private List facturas;
  3.    public List getFacturas() {
  4.       return facturas;
  5.    }
  6.    public void setFacturas(List facturas) {
  7.       this.facturas = facturas;
  8.    }
  9.    public void pintaFacturas() {
  10.       ListIterator iterator = facturas.listIterator();
  11.       while(iterator.hasNext())
  12.       {
  13.             Factura f = (Factura)iterator.next();
  14.             System.out.println("Factura Nº:"+f.getNum()+",importe"+f.getImporte());
  15.       }
  16.    }
  17. }

Deberíamos complicarlo un poco mas pero para ilustrar los conceptos anteriores nos sirve.
Ahora tenemos el fichero xml de configuración de spring donde detallaremos los beans y las inyecciones que necesitamos hacer:

  1. <beans>
  2.     <bean id="factMan" class="net.jsanroman.facturas.FacturasManager">
  3.         <property name="facturas">
  4.             <list>
  5.                 <ref bean="factura1"/>
  6.                 <ref bean="factura2"/>
  7.                 <ref bean="factura3"/>
  8.             </list>
  9.         </property>
  10.     </bean>
  11.     <bean id="factura1" class="net.jsanroman.facturas.Factura">
  12.         <property name="num"><value>1</value></property>
  13.         <property name="importe"><value>124.3</value></property>
  14.     </bean>
  15.     <bean id="factura2" class="net.jsanroman.facturas.Factura">
  16.         <property name="num"><value>2</value></property>
  17.         <property name="importe"><value>14.3</value></property>
  18.     </bean>
  19.     <bean id="factura3" class="net.jsanroman.facturas.Factura">
  20.         <property name="num"><value>3</value></property>
  21.         <property name="importe"><value>224.3</value></property>
  22.     </bean>

Estamos instanciando 3 beans tipo Factura desde el propio xml y los estamos inyectando en la propiedad facturas de FacturasManager:

Ahora simplemente necesitamos un método que ejecute lo anterior, como veis una simple case standalone:

  1. private static FacturasManager facturasManager;
  2.    public static void main(String[] args){
  3.       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  4.         facturasManager = (FacturasManager)ctx.getBean("factMan");
  5.         facturasManager.pintaFacturas();
  6.     }

Hemos desacoplado las clases Factura y FacturasManager, si en lugar de esas 3 instancias de facturas necesitáramos enviar un listado de las facturas de nuestra BD simplemente necesitaríamos modificar la inyección en el fichero .xml.

De esta forma también podremos integrar un montón de librerías externas.

2 July, 2008

Curso J2EE (8ª semana) struts2

Aunque este fin de semana pasado ya hemos terminado el curso, a mi todavía me queda contaros por encima el contenido de algunas semanas, que espero poder liquidar pronto, aquí va la 8ª, dedicada a struts2.

Otro framework, webwork, nació como un fork de struts añadiendo nuevas ideas y funcionalidades. Allá por el 2005 se anunció la fusión de struts con webwork. En ese momento nació struts2.

El primer cambio cuando pasamos de struts a struts 2 lo encontramos en la configuración de nuestro web.xml, ahora ya no utilizamos el conocido ActionServlet, ni especificamos la ruta de nuestro fichero de configuración struts-config.xml. En struts2 lo cambiamos por un DispatcherFilter que debemos definir en web.xml y será el encargado de gestionar nuestras acciones y de selccionar los interceptores a invocar:

  1. <filter>
  2.     <filter-name>struts2</filter-name>
  3.         <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  4.     </filter>
  5.     <filter-mapping>
  6.         <filter-name>struts2</filter-name>
  7.         <url-pattern>/*</url-pattern>
  8.     </filter-mapping>
  9. </filter>

El fichero de configuración principal será struts.xml el cual podremos segmentar en tantos ficheros como deseemos para estructurar lo mejor posible nuestras acciones:

  1. <include file="administracion.xml"/>

Ahora nuestras acciones extienden de ActionSupport y aunque siempre acabamos necesitándolo no tenemos que acceder a la request para obtener nuestros parámetros sino que se encarga de hacerlo struts2 mediante inyección de dependencias, ya no necesitamos ActionForm.

Results predefinidos para devolver el estado de una accion, ERRORS, SUCESS,...

Tenemos una serie de interceptores predefinidos (validaciones, login, logger, etc) y podemos definir nuestros propios interceptores, deben extender de AbstractInterceptor y ser declarados en el fichero principal struts.xml.

  1. <interceptors>
  2.      <interceptor name="login" class="net.jsanroman.interceptors.LoginInterceptor"/>
  3.      <interceptor name="logger" class="net.jsanroman.interceptors.LogInterceptor"/>
  4.           <interceptor-stack name="comun">
  5.                <interceptor-ref name="login"></interceptor-ref>
  6.                <interceptor-ref name="logger"></interceptor-ref>
  7.                <interceptor-ref name="validation"></interceptor-ref>
  8.           </interceptor-stack>
  9. </interceptors>

y los asignamos a una acción, podemos asignar un stack o conjunto de interceptores directamente:

  1. <action name="doLogin" class="net.jsanroman.security.controller.LoginAction">
  2.        <interceptor-ref name="comun"></interceptor-ref>
  3.        <result name="input">/login/login.jsp</result>
  4.        <result name="error">/login/login.jsp</result>
  5.        <result>/login/login_ok.jsp</result>
  6. </action>

Añadido concepto de packages y namespace en la definición de acciones en nuestro xml para agrupar acciones:

  1. <package name="facturas" namespace="/facturas" extends="struts-default">
  2.       <action name="Pagar" class="net.jsanroman.security.controller.factura.PagarFacturaAction">
  3.             <result>/facturas/factura.jsp</result>
  4.       </action>
  5.       <action name="Cargar" class="net.jsanroman.common.controller.CargarFacturaAction">
  6.             <result name="error">/facturas/error.jsp</result>
  7.             <result>/facturas/factura.jsp</result>
  8.       </action>
  9. </package>

Nuevos tags para renderizar diferentes elementos html:

  1. <%@ taglib prefix="s" uri="/WEB-INF/struts-tags.tld" %>
  2.    <head><title>Nueva factura</title></head>
  3.    <body>
  4.     <s:form action="guardar" method="post">
  5.        <s:textfield label="Fecha" name="fecha" />
  6.        <s:textarea label="Concepto" name="concepto" rows="6" cols="35" />
  7.        <s:textfield label="Importe" name="importe" />
  8.        <s:submit value="Guardar"/>
  9.    </s:form>
  10.     </body>
  11.  </html>

Validaciones declarativas en xml, uno por acción, PagarFacturaAction-validation.xml

  1. <validators>
  2.      <field name="importe">
  3.           <field-validator type="requiredstring">
  4.               <param name="trim">true</param>
  5.                <message>Importe factura obligatorio</message>
  6.           </field-validator>
  7.      </field>
  8. </validators>

o mediante anotaciones:

  1. @Validation
  2. public class Factura {
  3.     private float importe;
  4.     @RequiredStringValidator(message="Importe factura obligatorio", key="validation.fieldRequeried")
  5.     public String getImporte() {
  6.         return importe;
  7.     }
  8. ...

Como veis muchos cambios, y muchos mas que nos quedan por descubrir.

http://www.infoq.com/minibooks/starting-struts2
http://struts.apache.org/2.x/

5 June, 2008

Curso J2EE (6ª, 7ª semana) struts

Como ya te habrás dado cuenta estoy bastante retrasado con esta colección de artículos, este lo tengo pendiente desde hace varias semanas, y el próximo no creo que llegue hasta finales de junio que finalizo el semestre en la uoc con 2 puñeteros exámenes. Ese fin de semana lo aprovecharé para disfrutar de un par de días sabáticos por A Coruña, que ya va haciendo falta, y volver cargado de energía.

Estoy planteándome desde hace un tiempo instalar un wiki en este espacio para dejar estos ejemplos y otra información inclasificable bien documentada, cualquier decisión será después de los famosos exámenes, también te tendré al tanto.

Struts ya era un conocido para mi, lo había utilizado en interacción, la última vez hace unos meses antes de irme, por eso que pocas cosas me sorprendieron en esas semanas.

Comenzamos con las explicaciones básicas, un framework que cumple el modelo MVC, que cuenta con una madurez y estabilidad muy valorada por todos, que ha sido de los primeros en aparecer y que ha sido el framework con mayor acogida en el mundo j2ee hasta la fecha. Ahora ya le han salido contrincantes.

Continuamos con los ejemplos básicos, struts-config.xml donde configuramos la navegación, definimos los formularios, definimos nuestro servlet que actúa como controller. Como segregar la configuración de nuestras acciones en diferentes xml. Ejemplos de internacionalización, en ficheros .properties o en .xml. Definición y uso de los filtros de preprocesado, el patrón frontcontroller. El patrón Facade. ActionForm para la definición de nuestros formularios. Uso de las propias librerías de struts para las validaciones. Las plantillas tiles en struts.

En estas semanas ya posteriores a struts estamos viendo spring (el cual hemos aprovechado para introducirnos en la programación orientada a aspectos AOP), y hemos hecho un par de ejemplos con appfuse y struts2.

Como ves da para mucho, y mi tiempo es escaso, asi que mientras sigo pensando en la idea del wiki y en como dejar documentada toda esta información voy a centrarme en mi asignatura de "análisis matemático" que se me está haciendo muy cuesta arriba. Paciencia, en un par de semanas tendrás noticias mías.

Powered by WordPress
Bajo licencia Creative Commons
Contacto sanroman.javier at gmail.com