Programación Orientada a Aspectos vs. Programación Orientada a Objetos

199

Como la mayoría de los desarrolladores aquí y en todo el mundo, he estado desarrollando sistemas de software utilizando técnicas de programación orientada a objetos (OOP) durante muchos años. Entonces, cuando leo que la programación orientada a aspectos (AOP) aborda muchos de los problemas que la OOP tradicional no resuelve completa o directamente, hago una pausa y pienso, ¿es real?

He leído mucha información tratando de aprender las claves de este paradigma AOP y estoy en el mismo lugar, así que quería comprender mejor sus beneficios en el desarrollo de aplicaciones del mundo real.

¿Alguien tiene la respuesta?

yeradis
fuente
77
Todas las respuestas han sido muy buenas, este es un caso perfecto para una sola respuesta editada por la comunidad que las combinaría a todas. Todos dicen lo mismo pero de diferentes maneras y usan diferentes ejemplos que se suman al valor general
Vinko Vrsalovic

Respuestas:

323

¿Por qué "vs"? No es "vs". Puede utilizar la programación orientada a aspectos en combinación con la programación funcional, pero también en combinación con la orientada a objetos. No es "vs", es "Programación Orientada a Aspectos con Programación Orientada a Objetos".

Para mí, AOP es una especie de "metaprogramación". Todo lo que hace AOP también podría hacerse sin él simplemente agregando más código. AOP simplemente te ahorra escribiendo este código.

Wikipedia tiene uno de los mejores ejemplos para esta metaprogramación. Suponga que tiene una clase gráfica con muchos métodos "set ... ()". Después de cada método establecido, los datos de los gráficos cambiaron, por lo que los gráficos cambiaron y, por lo tanto, los gráficos deben actualizarse en la pantalla. Suponga que para volver a pintar los gráficos debe llamar "Display.update ()". El enfoque clásico es resolver esto agregando más código . Al final de cada método establecido, escribe

void set...(...) {
    :
    :
    Display.update();
}

Si tiene 3 métodos de configuración, eso no es un problema. Si tiene 200 (hipotético), se está volviendo realmente doloroso agregar esto en todas partes. Además, cada vez que agregue un nuevo método set, debe asegurarse de no olvidar agregar esto al final, de lo contrario, simplemente creó un error.

AOP resuelve esto sin agregar toneladas de código, sino que agrega un aspecto:

after() : set() {
   Display.update();
}

¡Y eso es! En lugar de escribir el código de actualización usted mismo, simplemente le dice al sistema que después de alcanzar un punto de corte set (), debe ejecutar este código y lo ejecutará. No es necesario actualizar 200 métodos, no es necesario asegurarse de no olvidar agregar este código en un nuevo método set. Además solo necesita un punto de corte:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

Qué significa eso? Eso significa que si un método se llama "set *" (* significa que cualquier nombre puede seguir después del set), independientemente de lo que devuelva el método (primer asterisco) o qué parámetros toma (tercer asterisco) y es un método de MyGraphicsClass y esto La clase es parte del paquete "com.company. *", entonces este es un punto de corte set (). Y nuestro primer código dice " después de ejecutar cualquier método que sea un corte de punto establecido, ejecute el siguiente código".

¿Ves cómo AOP resuelve elegantemente el problema aquí? En realidad, todo lo descrito aquí se puede hacer en tiempo de compilación. Un preprocesador de AOP puede modificar su fuente (por ejemplo, agregar Display.update () al final de cada método de set-pointcut) incluso antes de compilar la clase en sí.

Sin embargo, este ejemplo también muestra uno de los grandes inconvenientes de AOP. AOP en realidad está haciendo algo que muchos programadores consideran un " antipatrón ". El patrón exacto se llama " Acción a distancia ".

La acción a distancia es un antipatrón (un error común reconocido) en el que el comportamiento en una parte de un programa varía enormemente en función de operaciones difíciles o imposibles de identificar en otra parte del programa.

Como novato en un proyecto, podría leer el código de cualquier método set y considerarlo roto, ya que parece no actualizar la pantalla. No veo simplemente mirando el código de un método set, que después de que se ejecute, algún otro código se ejecutará "mágicamente" para actualizar la pantalla. ¡Considero que esto es un inconveniente serio! Al realizar cambios en un método, podrían introducirse errores extraños. Comprender mejor el flujo de código del código donde ciertas cosas parecen funcionar correctamente, pero no son obvias (como dije, simplemente funcionan mágicamente ... de alguna manera), es realmente difícil.

Actualizar

Solo para aclarar que: algunas personas pueden tener la impresión de que estoy diciendo que AOP es algo malo y que no debe usarse. Eso no es lo que estoy diciendo! AOP es en realidad una gran característica. Solo digo "Úselo con cuidado". AOP solo causará problemas si mezcla el código normal y AOP para el mismo Aspecto . En el ejemplo anterior, tenemos el Aspecto de actualizar los valores de un objeto gráfico y pintar el objeto actualizado. De hecho, ese es un aspecto único. La codificación de la mitad como código normal y la otra mitad como aspecto es lo que agrega el problema.

Si usa AOP para un aspecto completamente diferente, por ejemplo, para iniciar sesión, no se encontrará con el problema antipatrón. En ese caso, un novato en el proyecto podría preguntarse "¿De dónde vienen todos estos mensajes de registro? No veo ninguna salida de registro en el código", pero eso no es un gran problema. Los cambios que realiza en la lógica del programa difícilmente romperán la instalación del registro y los cambios realizados en la instalación del registro difícilmente romperán la lógica del programa: estos aspectos están totalmente separados. El uso de AOP para el registro tiene la ventaja de que el código de su programa puede concentrarse completamente en hacer lo que sea que deba hacer y aún así puede tener un registro sofisticado, sin que su código esté abarrotado por cientos de mensajes de registro en todas partes. Además, cuando se introduce un nuevo código, los mensajes de registro mágico aparecerán en el momento correcto con el contenido correcto.

Por lo tanto, un buen uso de AOP en mi ejemplo sería siempre registrar si algún valor se ha actualizado a través de un método establecido. Esto no creará un antipatrón y casi nunca será la causa de ningún problema.

Se podría decir que si puede abusar fácilmente de AOP para crear tantos problemas, es una mala idea usarlo todo. Sin embargo, ¿qué tecnología no se puede abusar? Puede abusar de la encapsulación de datos, puede abusar de la herencia. Se puede abusar de casi todas las tecnologías de programación útiles. Considere un lenguaje de programación tan limitado que solo contiene características que no se pueden abusar; un lenguaje en el que las funciones solo se pueden usar como estaban destinadas inicialmente. Tal lenguaje sería tan limitado que es discutible si incluso se puede usar para la programación del mundo real.

Mecki
fuente
44
El registro parece ser un ejemplo específico en el que AOP no resulta en acción a distancia. En este momento, wikipedia es el ejemplo del uso de aspectos para cosas como las comprobaciones de seguridad, que realmente hacen que el programa fluya mucho más para comprender.
kizzx2
77
@ kizzx2: De hecho, es un gran punto de inicio de sesión: es el mejor ejemplo que he visto hasta ahora de la fortaleza de AOP, sin saber demasiado sobre AOP. ¡Gracias por compartir!
errores el
@Mecki, su ejemplo está demasiado simplificado y no refleja el caso de uso general. En su ejemplo, Display.updateno toma ningún argumento. ¿Qué sucede si necesitamos pasar argumentos (por ejemplo, una logfunción requeriría un messageparámetro)? ¿Entonces no necesitaríamos agregar mucho código repetitivo para hacerlo de la manera AOP?
Pacerier
3
@Pacerier Mi ejemplo se simplifica porque SO no es un foro de enseñanza. Estaba respondiendo la pregunta del interrogador, probablemente mucho más detallada de lo que hubiera sido necesario. Si desea saber más sobre AOP, intente leer la documentación del programador y si tiene una pregunta detallada, ¿por qué no la hace aquí? No, no en un comentario, ve y crea una nueva pregunta porque de eso se trata SO. Estoy seguro de que alguien podrá disipar sus dudas en una respuesta.
Mecki
2
@Pacerier Lo siento, pero no entiendo tu punto. Consulte aquí: stackoverflow.com/a/8843713/15809 Este código registra cada llamada a cada método público, incluidos todos los tipos y valores de argumentos de método. Escribe esto exactamente una vez y no se agrega código repetitivo a ningún método, es solo el código que se muestra en la respuesta.
Mecki 01 de
29

la programación orientada a aspectos proporciona una buena manera de implementar preocupaciones transversales como la tala, la seguridad Estos concejos transversales son piezas de lógica que deben aplicarse en muchos lugares, pero en realidad no tienen nada que ver con la lógica empresarial.

No debería ver AOP como un reemplazo de OOP, más como un buen complemento, que hace que su código sea más limpio, poco acoplado y centrado en la lógica empresarial. Entonces, al aplicar AOP obtendrá 2 beneficios principales:

  1. La lógica de cada preocupación ahora está en un lugar, en lugar de estar dispersa por toda la base del código.

  2. Las clases son más limpias, ya que solo contienen código para su preocupación principal (o funcionalidad principal) y las preocupaciones secundarias se han trasladado a aspectos.

nkr1pt
fuente
27

OOP y AOP no son mutuamente excluyentes. AOP puede ser una buena adición a OOP. AOP es especialmente útil para agregar código estándar como el registro, el seguimiento del rendimiento, etc. a los métodos sin obstruir el código del método con este código estándar.

Norbert B.
fuente
10

Creo que no hay una respuesta general a esta pregunta, pero una cosa a tener en cuenta es que AOP no reemplaza a OOP sino que agrega ciertas características de descomposición que abordan la llamada tiranía de la composición dominante ( 1 ) (o preocupaciones transversales).

Seguramente ayuda en ciertos casos siempre y cuando tenga el control de las herramientas y los idiomas que se utilizarán para un proyecto específico, pero también agrega un nuevo nivel de complejidad con respecto a la interacción de aspectos y la necesidad de herramientas adicionales como el AJDT para entender su programa

Gregor Kiczales dio una vez una interesante charla introductoria sobre AOP en Google Tech Talks que recomiendo ver: Programación Orientada a Aspectos: Investigación Radical en Modularidad .

fhe
fuente
8

En primer lugar, AOP no reemplazará a OOP. AOP extiende OOP. Las ideas y prácticas de OOP siguen siendo relevantes. Tener un buen diseño de objeto probablemente hará que sea más fácil extenderlo con aspectos.

Creo que las ideas que aporta AOP son importantes. Necesitamos encontrar formas de implementar preocupaciones transversales sobre diferentes clases en su programa sin tener que cambiar las clases por sí mismas. Pero creo que el AOP eventualmente se convertirá en parte de otras herramientas que usamos y no en una herramienta o técnica separada. Ya vemos que esto sucede.

Un par de lenguajes dinámicos como Ruby y Python tienen construcciones de lenguaje como mixins que resuelven los mismos problemas. Esto se parece mucho a AOP pero está mejor integrado en el lenguaje.

Spring y Castle y un par de otros marcos de inyección de dependencia tienen opciones para agregar comportamiento a las clases que inyectan. Esta es una forma de tejer en tiempo de ejecución y creo que tiene mucho potencial.

No creo que tenga que aprender un paradigma completamente nuevo para usar AOP. Las ideas son interesantes pero están siendo absorbidas lentamente por las herramientas e idiomas existentes. Simplemente manténgase informado y pruebe estas herramientas.

Mendelt
fuente
1

Llego tarde a responder esta pregunta, pero es uno de mis temas favoritos, así que permítanme compartir mi opinión.

OOP se utiliza principalmente para organizar la lógica de su negocio, mientras que AOP le ayuda a organizar sus cosas no funcionales como Auditoría, Registro, Gestión de transacciones, Seguridad, etc.

De esta manera, puede desacoplar la lógica de su negocio con la lógica no ficticia que hace que el código sea más limpio.

Otra ventaja es que puede aplicar el consejo (ejemplo de auditoría) de manera muy consistente sin implementar ninguna interfaz que brinde una gran flexibilidad para la modificación sin tocar la lógica empresarial

GPopat
fuente