¿Cuándo son los ganchos la elección de diseño correcta?

10

He trabajado en una gran aplicación de Rails donde el uso de las devoluciones de llamadas de ActiveRecord era rampante y desgarrador. Guardar un registro a menudo tuvo efectos secundarios inesperados y fue un desafío razonar sobre el sistema.

Al mismo tiempo, he visto que los ganchos se usan con buenos resultados como parte de la herencia (por ejemplo, una clase principal que usa un método de plantilla para permitir que las subclases agreguen un comportamiento especializado sin necesidad de conocer las partes internas de los padres) y en complementos (por ejemplo, un modo emacs que ejecuta un gancho cuando está activado, lo que permite a los usuarios agregar un comportamiento personalizado alrededor de ese modo).

Me doy cuenta de que una aplicación de Rails y un intérprete de Lisp son sistemas muy diferentes, pero tengo curiosidad por saber si hay algún criterio conocido que la gente tenga en cuenta al decidir si los ganchos son la opción de diseño correcta para el problema que enfrentan.

El tema que me llama la atención es la previsibilidad. El mal uso de los ganchos parece conducir a una acción espeluznante a distancia y un comportamiento sorprendente, mientras que el buen uso puede conducir a un marco predecible sin un acoplamiento estrecho.

Como todavía estoy solo unos años en mi carrera de programación, me considero un novato en muchos aspectos, y sospecho que la gente ha pensado mucho en este tema. ¿Cuáles son algunas pautas que pueden dirigir esta decisión?

ivan
fuente

Respuestas:

5

Los ganchos son una buena opción de diseño cuando desea desacoplar los detalles de implementación de una abstracción de sus consumidores transfiriendo el control a los receptores del gancho.

Puede hacerlo mediante una transmisión anónima (como eventos o devoluciones de llamadas anónimas) o mediante abstracciones escritas (como Interfaces o clases para padres).

Debe usar la transmisión anónima cuando:

  • La llamada del gancho es opcional.
  • A la persona que llama no le importa quién recibe el gancho.
  • El orden de ejecución de los receptores es irrelevante.
  • Desea transmitir el estado del objeto a todos los suscriptores del enlace.

Debe usar una abstracción escrita cuando:

  • Llamar al gancho es obligatorio.
  • El objeto llamante necesita identificar el receptor del gancho.
  • El orden de ejecución de los receptores es relevante para su objeto.

Un ejemplo de un enlace de transmisión es un evento KeyPressedEvent. A la clase que dispara el evento no le importa quién lo reciba y está transmitiendo el estado del teclado a cualquier persona suscrita al evento. El orden de ejecución de los receptores no tiene efecto sobre el estado del objeto de la clase que dispara el evento.

Un ejemplo de un gancho de abstracción escrito es el método de plantilla que mencionó. En este caso, la clase padre requiere una implementación para sus métodos de plantilla, sabe que los receptores serán hijos de ella y tiene un orden de ejecución específico para los métodos de plantilla, según lo definido por la clase padre.

Cesar Hernandez
fuente
7

La mayoría de los idiomas y la mayoría de las plataformas utilizan el enganche, incluso si está disfrazado de otra cosa. Cada vez que escuche del término "evento", "mensaje", "disparador", "señal" u otros términos de esa naturaleza, probablemente esté tratando de enganchar, aunque hay excepciones a la regla, que probablemente no importa para esta discusión.

Los usa porque la plataforma se los proporciona, o posiblemente incluso requiera su uso por razones de rendimiento. El uso de ganchos a menudo reduce la complejidad del código, ayuda a cumplir los requisitos comerciales y reduce el uso de la CPU, lo que prolonga la vida útil de la batería y el hardware. Debe usarlos siempre que desee el mejor rendimiento de su código.

Incluso su experiencia desgarradora con Rails identifica prácticamente un caso de uso común para los ganchos: las reglas de negocios deben aplicarse, y los ganchos se usan de manera universal para hacer cumplir las reglas de negocios. Desafortunadamente, no todas las reglas tienen sentido y, como puede ver, dificulta las cosas para un desarrollador cuando son arbitrarias, pero es por eso que la documentación de un sistema es tan importante como el código en sí.

Como regla general, use ganchos porque son características de rendimiento y harán que su código se ejecute de manera más eficiente que la alternativa (que se llama "sondeo", donde espera en un bucle ocupado para verificar eventos). Sin embargo, también asegúrese de utilizar la documentación adecuada y mantenerla actualizada. Los ganchos se utilizan en prácticamente todos los idiomas que encontrará, y es importante saber por qué existen.

phyrfox
fuente
1

Anteriormente trabajé en un programa que, en mi opinión, hizo un buen uso de los ganchos. En mi libro, un verdadero enlace es una llamada (publicación) a una lista de devoluciones de llamada (suscriptores). Es poderoso, el abuso es fácil. La mejor pregunta para el caso de uso es: ¿deseo habilitar o deshabilitar el comportamiento en tiempo de ejecución? Por ejemplo, es posible que desee permitir que sus usuarios proporcionen secuencias de comandos que ejecutará en ciertos eventos, o crear un programa genérico hecho de complementos más pequeños. Entonces las llamadas de gancho son apropiadas. En general, tiene pocas otras opciones.

Si no, debe salirse con un buen arco de sus módulos. Los métodos de plantilla funcionan bien con funciones sobrecargadas, no necesita lógica de tiempo de ejecución para esto. Considere que impondría un acoplamiento flojo es una ilusión: existe el mismo nivel de dependencia entre algo que llama directamente o que engancha, la persona que llama tiene que cumplir su contrato de todos modos.

Tenga en cuenta que, tal vez, algunas personas llaman al método de plantilla con enganche de funciones sobrecargadas, pero eso es diferente de lo anterior: aquí tiene un enlace estático, con un menor riesgo de entrar en una pesadilla de mantenimiento.

Arthur Havlicek
fuente