¿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.