¿Se resuelven ciertos problemas de manera más elegante con AOP?

19

Me he encontrado con la idea de la Programación Orientada a Aspectos, y tengo algunas preocupaciones al respecto.

La idea básica parece ser que queremos tomar inquietudes transversales que no están bien modularizadas usando objetos y modularizarlas. Todo eso está muy bien y bien.

Pero la implementación de AOP parece ser la de modificar el código desde fuera del módulo. Entonces, por ejemplo, se podría escribir un aspecto que cambie lo que sucede cuando un objeto en particular se pasa como parámetro en una función. Esto parece ir directamente en contra de la idea de los módulos. No debería poder modificar el comportamiento de un módulo desde fuera de ese módulo, de lo contrario, se anulará todo el punto de los módulos. ¡Pero los aspectos parecen estar haciendo exactamente eso!

Básicamente, los aspectos parecen ser una forma de parcheo de código. Puede ser útil para algunos hacks rápidos; pero, como principio general, tal vez no sea algo que quieras hacer. La programación orientada a aspectos me parece que toma una mala práctica y me eleva a un principio de diseño general.

¿Es AOP una buena práctica? ¿Se resuelven ciertos problemas de programación de manera más elegante con AOP?

Winston Ewert
fuente
ahhh, el famoso parche de mono!
Muad'Dib
1
Edité la pregunta para mejorar su tono y voté para reabrirla.
Robert Harvey
Questio también se ha vuelto a preguntar en una forma diferente aquí: programmers.stackexchange.com/questions/19344/…
Peter Boughton el

Respuestas:

19

La Programación Orientada a Aspectos hace posible realizar ciertos tipos de programación que son difíciles de hacer sin dispersar innecesariamente el código en su aplicación o biblioteca que no está relacionado con las funciones principales de su software (es decir, preocupaciones transversales). Ejemplos incluyen:

  1. Registro y Monitoreo
  2. Análisis de rendimiento
  3. Depuración y seguimiento
  4. Deshacer funcionalidad
  5. Validación de entradas y salidas.
  6. Morphing el comportamiento de los objetos existentes
  7. Filtros de objetos
  8. Implementación de seguridad
  9. Gestionar transacciones

Al limitar estas preocupaciones transversales a una sola parte de la aplicación, y luego hacer referencia a estas características en el código a través de atributos, interceptación de llamadas a métodos o proxys dinámicos, permite la encapsulación del comportamiento transversal; esto tiene todos los beneficios (es decir, un único punto de modificación) que la encapsulación proporcionaría en cualquier otro lugar de su aplicación.

El punto clave aquí es que AOP encapsula el comportamiento que es 1) común en toda la aplicación y 2) periférico a la funcionalidad principal de la aplicación.

Robert Harvey
fuente
7

Llegué tarde al juego, pero proporciono esto para desarrolladores posteriores que podrían tropezar con esta pregunta.

Recomiendo encarecidamente contra AOP si su aplicación depende de que funcione correctamente. Los aspectos funcionan así:

  • Se aplica asesoramiento (comportamiento adicional) a
  • Unir puntos (lugares donde se puede adjuntar el código adicional, como comenzar o finalizar un método, o cuando se desencadena un evento determinado)
  • ... donde pointcut (un patrón que detecta si un punto de unión dado coincide) patrones coinciden

Para cualquiera que haya estado usando computadoras durante mucho tiempo, el hecho de que se usen patrones podría ser algo que se debe observar de cerca. Así que aquí hay un ejemplo de un punto de corte que coincide con cualquier método nombrado setindependientemente de los argumentos:

call(* set(..))

Entonces, ese es un punto de corte bastante amplio y debe quedar claro que se recomienda manejar esto con cuidado (sin juego de palabras) porque está aplicando consejos a muchas cosas.

O diablos, ¡apliquemos consejos a todo , independientemente de su nombre o firma!

execution(* *(..))

Claramente, deberíamos tener cuidado porque hay mucho poder aquí, pero este no es un argumento en contra de los aspectos: es un argumento de precaución porque hay mucho poder aquí y la coincidencia de patrones puede salir mal fácilmente (simplemente presione su motor de búsqueda favorito para Aop bugs y diviértete).

Así que aquí está lo que parece un punto de corte relativamente seguro:

pointcut setter(): target(Point) &&
                   ( call(void setX(int)) ||
                     call(void setY(int)) );

Eso proporciona consejos explícitamente si se encuentran métodos nombrados setXo setYen un Pointobjeto. Los métodos solo pueden recibir intsy deben ser void. Parece bastante seguro, ¿verdad? Bueno, eso es seguro si existen esos métodos y has aplicado los consejos correctos. Si no, muy mal; silenciosamente falla.

Para dar un ejemplo, un amigo estaba tratando de depurar una aplicación Java en la que todos, de vez en cuando, devolvían datos incorrectos. Fue una falla infrecuente y no parecía estar correlacionada con ningún evento en particular o datos en particular. Fue un error de subprocesamiento, algo que es notoriamente difícil de probar o detectar. Como resultado, estaban usando aspectos para bloquear métodos y hacerlos "seguros para subprocesos", pero un programador renombró un método y un corte de punto no coincidió, lo que provocó una interrupción silenciosa de la aplicación.

Por lo tanto, les digo a las personas que si deben usar AOP, para tratar aspectos como excepciones: en un sistema bien diseñado y si nada sale mal, pueden eliminarse y el software aún funciona correctamente. Sin embargo, si la funcionalidad del programa depende de AOP, introduce una fragilidad en su programa que no está justificada.

Por lo tanto, el registro, la depuración y el seguimiento son excelentes ejemplos de comportamientos que son perfectos para aspectos, pero ¿seguridad? No Hilo de seguridad? No

Para una alternativa robusta al AOP, vea los rasgos . En lugar de estar atornillados al lenguaje, se integran directamente en él, no necesitan un IDE "con reconocimiento de rasgos" (aunque puede ayudar) y tienen fallas en tiempo de compilación si los métodos que necesita no están presentes. Los rasgos hacen un trabajo mucho más limpio al manejar la separación de preocupaciones porque el problema se definió mejor desde el principio. Los uso ampliamente y son fantásticos.

Curtis Poe
fuente
En lugar de argumentar que AOP no debe usarse para la funcionalidad principal, puede ser más apropiado decir que los cortes de puntos que dependen de nombres de métodos son una mala idea. Probablemente argumentaría que el bloqueo y la sincronización tampoco son buenos casos de uso para AOP.
Código Bling
2

Una situación en la que AOP podría ser la única solución decente y práctica es cuando no tiene acceso al código fuente . Para usar el viejo y cansado ejemplo de la preocupación transversal de la tala:

Supongamos que desea registrar el flujo de control en una biblioteca de terceros que consume. Tiene su propio código totalmente equipado con declaraciones de registro. Sin embargo, para esta biblioteca no tiene la fuente, por lo que es imposible agregar sus declaraciones de registro. Ya que hacer que el código de bytes, AOP le permite instrumento que terceros biblioteca de todos modos.

Y si de todos modos está creando un aspecto de registro, también podría considerar implementar el registro con AOP a través de su propio código.

Joseph Tanenbaum
fuente
El registro es para cosas "interesantes". ¿Cómo puede hacer otras cosas que "entrar con estos parámetros" y "salir" con el registro de AOP?
@Thorbjorn: el registro / depuración / rastreo es solo una de las muchas áreas de funcionalidad con las que AOP puede ayudar. Lo usé como un ejemplo para ilustrar mi punto. El punto que estoy tratando de hacer es que AOP le da más control sobre el código de bytes de terceros.
Joseph Tanenbaum el
claro, pero realmente quería saber si el registro de AOP puede hacer más que solo el registro de entrada-salida.
Depende de la herramienta AOP que utilice, pero ciertamente hay límites para lo que puede hacer. Es muy posible que sea imposible ir más allá del registro de entrada y salida.
Joseph Tanenbaum el