significa que gui expected definicion java oop design aop

java - gui - ¿Qué puede hacer AOP que OOP no puede hacer?



jlabel definicion (7)

AOP es OO; Los aspectos son objetos.

No entiendo por qué la mentalidad de ambos.

AOP es la elección perfecta para problemas interconectados y encadenados (por ejemplo, registro, seguridad, transacciones, proxy remoto, etc.)

ACTUALIZAR:

Creo que las críticas que ofrece el PO son subjetivas y no tan generalizadas como se dijo. Las afirmaciones declaradas sin prueba pueden ser descartadas sin prueba.

No creo en el uso de la magia, pero AOP no es mágico si lo entiendes. Yo lo entiendo. Quizás el OP no. Si ese es el caso, y el OP se siente más cómodo con una solución OO, yo diría que lo haga.

"Me parece que es innecesario" es una mera opinión, que se ofrece sin prueba. No hay respuesta a eso, excepto "No estoy de acuerdo".

Creo que AOP es perfecto para esos casos porque puedo aplicarlo de manera declarativa . Puedo escribir una clase de aspecto una vez y aplicarla en muchos lugares con un control detallado, cambiándola en configuración en lugar de código. Puedo escoger y elegir qué métodos, clases y paquetes tienen un aspecto aplicado a ellos en la configuración.

Pruébalo con un enfoque OO escrito a mano.

Además, AOP está orientado a objetos. Puede verlo como una persona inteligente que le proporciona un lenguaje o marco específico de dominio para lo que quiere hacer a mano. Las características comunes han sido abstraídas en algo más general. ¿Por qué alguien se opondría a eso?

Soy principalmente un desarrollador de Java. Conocí a muchos desarrolladores de Java que adoran AOP. También he estado viendo cada vez más "patrones de diseño" de AOP que parecen haber sido adoptados de forma bastante amplia. Aun así, todavía no estoy convencido de que AOP en código OO sea una buena idea en general, por un par de razones.

  1. Agrega "magia" al código en forma de complejidad opaca que puede ser extremadamente difícil de depurar, y puede hacer extremadamente difícil depurar el código orientado a objetos que afecta.

  2. Me parece que es en su mayoría innecesario, y (lo que es peor) a menudo se usa para evitar tener que diseñar bien, o para compensar el pobre diseño anterior.

Aquí hay un ejemplo que he estado viendo mucho en los últimos años, como fondo de mi pregunta.

Antes de AOP (de los documentos de Hibernate)

public void saveMyEntityToTheDatabase(MyEntity entity) { EntityTransaction tx = null; try { tx = entityManager.getTransaction(); tx.begin(); entityManager.persist(entity); tx.commit(); } catch (RuntimeException e) { if(tx != null && tx.isActive()) { tx.rollback(); } throw e; } }

Después de AOP

@Transactional public void saveMyEntityToTheDatabase(MyEntity entity) { entityManager.persist(entity); }

Parece una victoria obvia para AOP para mucha gente. Para mí, el problema original es sintomático de niveles inconsistentes de abstracción API. Es decir, EntityManager tiene un nivel mucho más bajo que la API de nivel empresarial del mensaje que lo usa. Este problema se puede resolver con un nivel de abstracción más apropiado y un diseño mejor (OO).

Una solución OO

public void saveMyEntityToTheDatabase(MyEntity entity) { database.performInTransaction(new Save(entity)); }

Esta solución supone que el objeto de database contiene el mismo tipo de lógica transaccional que el aspecto responsable que gestiona los métodos @Transactional . Esto responde a mis preocupaciones anteriores al hacer más obvio que hay algo que gestiona la interacción con EntityManager , y no introduce otro paradigma de programación.

Entonces, finalmente, mi pregunta: ¿qué puede hacer AOP que OOP no puede? Estoy un poco convencido de su utilidad en el registro de rastreo, y tal vez de forma predeterminada implementaciones de toString() o algo similar, pero me encantaría saber si alguien lo encontró significativamente mejor que OO para determinados tipos de problemas.


En general, toda pregunta de la forma "¿Qué puede hacer eso no puede?" no tienen sentido Todos los lenguajes de propósito general son igualmente poderosos (Ver: Tesis de la Iglesia ).

La diferencia entre los idiomas no radica, por tanto, en lo que pueden hacer sino en cómo lo hacen. En otras palabras, ¿cuánto trabajo debe hacer para obtener un comportamiento en un idioma, frente a la cantidad de trabajo para obtener ese mismo comportamiento en otro idioma?


La respuesta corta es ... nada. AOP, sin embargo, agrega una pizca de lo que nos referiríamos en mis días en los Marines de EE. UU. Como FM, que cuando se limpia para una audiencia civil significa "Magia Freaking". Tienes razón en que no se logra absolutamente nada en el primer caso que citas que no se logra en el segundo. Creo que el razonamiento principal detrás del movimiento es una cuestión de claridad, y el creciente mantra de "Menos ceremonia" en el código. Por lo tanto, puede escribir código para manejar las transacciones, o prescindir de la ceremonia con AOP, que provista por el vendedor o contenedor probablemente se prueba mejor que el código que está escribiendo a mano. Otro punto a favor de AOP es que PUEDE cambiarse en los descriptores de implementación, los archivos de configuración de Spring, etc., y luego puede modificarse si sus requisitos cambian sin ningún cambio en su código real. Así que su código escrito a mano sigue expresando la lógica de negocios que usted quería que paguen, y la capa "FM" maneja cosas como transacciones, registro, etc. con un rociado liberal de polvo de duendes AOP.

YMMV por supuesto.


Para mí, AOP es una forma abreviada de Patrón Interceptor . Y el Patrón Interceptor en sí mismo se deriva (o influyó u obtuvo la idea) del Método de Plantilla , AFAICS.

Un ejemplo popular de Interceptor es el Servlet Filter . Y sabemos que son bastante útiles en muchos casos.

Dado que, todos estos patrones son útiles, por lo tanto, AOP, que se deriva de estos también es útil. Y como usted mismo declaró algunos de sus usos.


Para mí, hasta ahora, el único caso de uso, para el cual AOP es definitivamente mejor que OOP es el método de seguimiento de llamadas.


Tuve la mala suerte de tener que trabajar en una aplicación en la que las llamadas de servicio se realizaban con un OOP normal. Lo odiaba, y voy a decirte por qué:

En primer lugar, su ejemplo es algo simplista, ya que normalmente el límite de la transacción no se trata de una interacción de base de datos única, sino de toda la invocación del servicio comercial. Así que, por el bien del ejemplo, considere el siguiente método:

@Transactional public Employee hire(Person p, Employee manager, BigDecimal salary) { // implementation omitted }

que se invoca utilizando

Employee hired = service.hire(candidate, manager, agreedOnSalary);

En tu caso, esto se convertiría en:

class HireAction implements Callable<Employee> { private final Person person; private final Employee manager; private final BigDecimal salary; public HireAction(Person person, Employee manager, BigDecimal salary) { this.person = person; this.manager = manager; this.salary = salary; } @Override public Employee call() throws Exception { // implementation omitted } }

e invocado por

Employee hired = session.doInTransaction(new HireAction(candidate, manager, agreedOnSalary));

El constructor es necesario para garantizar que todos los parámetros estén asignados (por lo que el compilador puede quejarse si se agrega un parámetro a un método sin actualizar a la persona que llama).

El segundo enfoque es inferior por las siguientes razones:

  1. Viola DRY, ya que cada parámetro se menciona 3 veces y el tipo de devolución dos veces. En particular, ¿dónde colocas JavaDoc para los parámetros? ¿Copias eso también?
  2. Hace difícil agrupar operaciones de servicio relacionadas en un servicio y compartir código entre ellas. Sí, puede poner todas las operaciones relacionadas en el mismo paquete y tener una superclase común para compartir el código, pero de nuevo, esto es bastante más detallado que el enfoque AOP de simplemente ponerlos en la misma clase. O podrías hacer cosas locas como:

    class HRService { class HireAction { // impl omitted } class FireAction { // impl omitted } }

    e invocarlo usando

    Employee emp = session.doInTransaction(new HRService().new HireAction(candidate, manager, salary));

  3. Un programador de aplicaciones puede olvidarse de iniciar la transacción:

    Employee e = new HireAction(candidate, manager, salary).call();

    o inicie la transacción en la sesión / base de datos incorrecta. Las transacciones y la lógica comercial son preocupaciones diferentes, generalmente resueltas por diferentes desarrolladores, y por lo tanto deben separarse.

En resumen, el enfoque OOP simple es más prolijo y propenso a errores, lo que lleva a un aumento de los costos durante el desarrollo y el mantenimiento.

Finalmente, sobre su crítica de AOP:

Agrega "magia" al código en forma de complejidad opaca que puede ser extremadamente difícil de depurar,

La complejidad siempre es difícil de depurar, independientemente de su origen. Recuerdo algunas sesiones de depuración con el código fuente de hibernación, cuyo uso juicioso del patrón de comando no hizo menos difícil encontrar el código que importaba.

La presencia de un interceptor de AOP puede no ser obvia (aunque si un método tiene la anotación @Transactional , lo consideraría obvio), por lo que el AOP se debe usar con moderación (lo cual no es un problema ya que el número de cortes transversales las preocupaciones en un proyecto suelen ser bastante pequeñas).

y puede hacer que sea extremadamente difícil depurar el código orientado a objetos que afecta.

¿Cómo es eso? No veo el problema, pero si lo describieras, probablemente podría decirte cómo lo resuelvo / evito.

Me parece que es en su mayoría innecesario, y (lo que es peor) a menudo se usa para evitar tener que diseñar bien, o para compensar el pobre diseño anterior.

Todas las tecnologías pueden usarse mal. Lo que importa es qué tan difícil es usar bien, y qué podemos lograr si lo hacemos.