2008-10-16 25 views
5

Heredé esta gigantesca aplicación web heredada de Java utilizando Struts 1.2.4. Tengo una pregunta específica con respecto a Acciones. La mayoría de las páginas tienen exactamente una Acción, y los métodos processExecute() son monstruos horribles (muy largos y toneladas de declaraciones anidadas basadas en parámetros de solicitud).¿Cómo lidiar con acciones monstruosas de Struts?

Dado que las acciones son una implementación del patrón de comando, estoy pensando en dividir estas acciones en una acción por gesto de usuario. Sin embargo, esta será una gran refactorización, y me pregunto:

  1. ¿Es esta la dirección correcta?
  2. ¿Hay algún paso intermedio que pueda tomar, un patrón que se ocupe del desorden dentro de las acciones monolíticas? Tal vez otro patrón de comando dentro de la acción?

Respuesta

9

Mi manera de hacer frente a esto sería:

  • No hago los 'todo a la vez'
  • cada vez que cambie nada, lo deja mejor que lo encontró
    • condicionales reemplazando con implementaciones de Acción separadas es un paso.
    • Mejor aún: Haga que sus implementaciones separadas de las clases de acción para que pueda utilizarlo cuando se cambia marcos
    • Mantenga su nueva aplicación Comando absolutamente y sin referencias a Struts, utilizar sus nuevas acciones como la envoltura alrededor de estas implementaciones.
    • Puede que necesite proporcionar interfaces a sus Struts ActionForms para pasarlas sin copiar todos los datos. Por otro lado - es posible que desee pasar alrededor de otros objetos que ActionForms que son por lo general un montón de cadenas (ver su otra pregunta sobre Struts 1.2 ActionForms)
  • de iniciar la migración a nuevas partes & mejor tecnología. Struts 1.2 fue genial cuando salió, pero definitivamente no es lo que quieres apoyar en la eternidad. Hay algunas generaciones de mejores marcos ahora.

Definitivamente hay más - Lo siento, estoy acabando el tiempo aquí ...

1

Tough problema, pero típico de desarrollo de aplicaciones Web temprana.

Lo primero es lo primero que necesita para empezar a pensar qué lógica constituye el comportamiento empresarial, qué lógica constituye "flujo" (es decir, qué ve el usuario) y qué lógica obtiene el contenido de lo que ve.

No tiene que ir por la ruta de fábricas e interfaces y todo eso; la implementación retroactiva es mucho menos útil ... pero consolida la lógica empresarial y la lógica de recuperación de datos en delegados de algún tipo ... y deja las acciones struts para determinar el flujo de páginas en función del éxito/fracaso de esa lógica.

A partir de ahí sólo hay que tomar unas pocas semanas y moler a cabo

1

Un método mucho no es bueno, a menos que pasa a ser una sola instrucción switch, donde los casos son muy cortos (análisis ficha o algo parecido ese).

Podría al menos refactorizar el método largo en métodos más pequeños con nombres descriptivos.

Si es posible, puede comenzar su método con el reconocimiento de lo que debe hacer examinando el formulario y luego, si no, vaya a las distintas opciones. Sin embargo, aunque no anidados, tienden a hacer que el código sea ilegible. Solo

enum Operation { 
    ADD, DELETE; 
} 

... 

Operation operation = determineOperation(form); 
if (operation == Operation.DELETE) { 
    doDelete(form); 
} else if (operation == Operation.ADD) { 
    doAdd(form); 
} 

Si puede llegar tan lejos, tiene su lógica limpia y agradable y puede hacer la refacturación que desee.

Lo difícil es dejar clara su lógica, y puede hacerlo en pasos. No elija un patrón hasta que no entienda exactamente cuál es su problema.

1

Si está planificando la refactorización del código, primero debe asegurarse de escribir las pruebas para el código existente para asegurarse de no haber alterado la funcionalidad una vez que comience a refactorizar.

+0

Voy a decir pshah. El autor afirma que los métodos son monstruosamente largos y tienen una alta complejidad ciclomática. Ese tipo de código es a menudo una prueba de pesadilla a unidad. – JonMR

2

He tratado con este tipo de cosas antes. Un buen primer paso es insertar otra clase base en la cadena de herencia entre Acción y una de las clases de acción monstruosas originales (vamos a llamarlo ClassA). Especialmente si no tienes tiempo para hacer todo de una vez. Luego puede comenzar a extraer partes de la funcionalidad en clases de acción en paralelo más pequeñas (ClassB, ClassC). Todo lo que es común entre la ClassA original y las nuevas clases refactorizadas puede ser retirado a la nueva clase base. Así que la jerarquía ahora se ve así:

Original Hierarchy:  New Hierarchy: 

    Action     Action 
     |      | 
     |      BaseA 
    (old)ClassA     | 
         +--------+----------+ 
         |  |   | 
        ClassB (new)ClassA ClassC 
+0

Lea mi respuesta anterior para obtener ideas sobre cómo tener una jerarquía de Acción. Creo que en muchos lugares que hacen esto probablemente tengan demasiada lógica comercial en su capa web. – bpapa

5

puntales acciones, en mi mente, no deben tener mucho código en ellos en absoluto. Simplemente deberían interactuar directamente con la solicitud y la respuesta: tomar algunos datos de un formulario o un parámetro de solicitud, entregar esa información a la capa de servicio, y luego poner algunas cosas en un objeto de respuesta o tal vez guardar algunos datos en la sesión del usuario.

Recomiendo que se mantenga alejado de hacer herencia con las clases de acción. Suena como una buena idea al principio, pero creo que tarde o temprano te darás cuenta de que estás jugando a las cartas más de lo que en realidad estás fortaleciendo la base del código. Struts tiene suficientes acciones básicas como están, si estás creando nuevas probablemente tengas código en la capa web que no debería estar allí.

Esa es solo mi experiencia personal.

2
  1. Ir un método a la vez
  2. Registro algunos casos de prueba se puede jugar de nuevo más tarde. Example here (asegúrate de recorrer tantas rutas a través del código como sea posible, es decir, todos los gestos de usuario en la página que llaman a esta acción)
  3. refactoriza el método para reducir su complejidad creando métodos más pequeños que hacen cosas más pequeñas.
  4. pruebas realizadas Re-Al hacer esto

En este punto, se ha rediseñado la versión de la gran método molesto enorme. Ahora puede comenzar a crear acciones específicas.

Puede utilizar su clase recién refactorizada como clase base e implementar cada acción específica como una subclase utilizando esos métodos pequeños refactorizados.

Una vez que haya hecho esto, debe tener una buena idea de la lógica compartida entre las clases y puede desplegar o empujar esos métodos según sea necesario.

No es divertido, pero si va a trabajar en la base de código por un tiempo, le ahorrará tiempo y dolores de cabeza.