Quando i ganci sono la scelta giusta per il design?


10

Ho lavorato su una grande app Rails in cui l'uso dei callback di ActiveRecord era dilagante e straziante. Salvare un disco spesso ha avuto effetti collaterali inaspettati ed è stata una sfida da ragionare sul sistema.

Allo stesso tempo, ho visto gli hook utilizzati con buoni risultati come parte dell'ereditarietà (ad esempio una classe genitore che utilizza un metodo modello per consentire alle sottoclassi di aggiungere un comportamento specializzato senza la necessità di conoscere gli interni del genitore) e nei plug-in (ad esempio una modalità emacs che esegue un hook quando è attivata, consentendo agli utenti di aggiungere un comportamento personalizzato in quella modalità).

Mi rendo conto che un'app Rails e un interprete Lisp sono sistemi molto diversi, ma sono curioso di sapere se ci sono criteri ben noti che le persone guardano quando decidono se gli hook sono la scelta giusta per il problema che stanno affrontando.

Il tema che mi emerge è la prevedibilità. L'uso improprio di ganci sembra portare a un'azione spettrale a distanza e comportamenti sorprendenti, mentre un buon uso può portare a un quadro prevedibile senza un accoppiamento stretto.

Dato che sono ancora solo pochi anni nella mia carriera di programmatore, mi considero un noob sotto molti aspetti e sospetto che le persone abbiano riflettuto molto su questo argomento. Quali sono alcune linee guida che possono guidare questa decisione?

Risposte:


5

I ganci sono una buona scelta di progettazione quando si desidera disaccoppiare i dettagli di implementazione di un'astrazione dai suoi consumatori trasferendo il controllo ai ricevitori del gancio.

Puoi farlo tramite una trasmissione anonima (come eventi o callback anonimi) o usando astrazioni tipizzate (come interfacce o classi parent).

È necessario utilizzare la trasmissione anonima quando:

  • La chiamata dell'hook è facoltativa
  • Al chiamante non importa chi riattiva l'hook.
  • L'ordine di esecuzione dei destinatari è irrilevante.
  • Si desidera trasmettere lo stato dell'oggetto a tutti gli abbonati all'hook.

Dovresti usare un'astrazione tipizzata quando:

  • Chiamare l'hook è obbligatorio.
  • L'oggetto chiamante deve identificare il ricevitore dell'hook.
  • L'ordine di esecuzione dei ricevitori è rilevante per l'oggetto.

Un esempio di hook di broadcasting è un KeyPressedEvent. Alla classe che lancia l'evento non importa chi lo riceve e sta trasmettendo lo stato della tastiera a chiunque si sia iscritto all'evento. L'ordine di esecuzione dei ricevitori non ha alcun effetto sullo stato dell'oggetto della classe che genera l'evento.

Un esempio di hook di astrazione tipizzato è il metodo modello che hai citato. In questo caso, la classe genitore richiede un'implementazione per i suoi metodi modello, sa che i destinatari ne saranno figli e ha un ordine di esecuzione specifico per i metodi modello, come definito dalla classe genitore.


7

La maggior parte delle lingue e la maggior parte delle piattaforme usano l'aggancio, anche se è vestito come qualcos'altro. Ogni volta che senti il ​​termine "evento", "messaggio", "innesco", "segnale" o altri termini di quella natura, probabilmente hai a che fare con l'aggancio, anche se ci sono eccezioni alla regola, che probabilmente non lo fanno questione per questa discussione.

Li usi perché la piattaforma te li fornisce o forse ne richiede persino l'uso per motivi di prestazioni. L'uso degli hook riduce spesso la complessità del codice, aiuta a far rispettare i requisiti aziendali e riduce l'utilizzo della CPU, prolungando la durata della batteria e dell'hardware. Dovresti usarli ogni volta che vuoi le migliori prestazioni dal tuo codice.

Anche la tua straziante esperienza con Rails identifica praticamente un caso d'uso comune per gli hook: le regole di business devono essere applicate e gli hook sono usati universalmente per imporre le regole di business. Sfortunatamente, non tutte le regole hanno senso e, come puoi dire, rende le cose più difficili per uno sviluppatore quando sono arbitrarie, ma è per questo che la documentazione di un sistema è importante tanto quanto il codice stesso.

Come regola generale, usa gli hook perché sono funzionalità prestazionali e faranno funzionare il tuo codice in modo più efficiente rispetto all'alternativa (che si chiama "polling", dove attendi in un ciclo occupato per verificare la presenza di eventi). Tuttavia, assicurarsi anche di utilizzare la documentazione appropriata e tenerlo aggiornato. Gli hook sono usati praticamente in tutte le lingue che incontrerai ed è importante sapere perché esistono.


1

In precedenza ho lavorato su un programma che a mio avviso ha reso un buon uso degli hook. Nel mio libro, un vero hook è una chiamata (pubblica) a un elenco di callback (abbonati). È potente, l'abuso è facile. La migliore domanda da porre per il caso d'uso è: voglio abilitare o disabilitare il comportamento in fase di esecuzione? Ad esempio, potresti voler consentire ai tuoi utenti di fornire script che eseguirai su determinati eventi o di creare un programma generico fatto di plugin più piccoli. Quindi le chiamate hook sono appropriate. In generale, hai poche altre opzioni.

In caso contrario, dovresti cavartela con un buon arco di moduli. I metodi modello funzionano bene con funzioni sovraccaricate, per questo non è necessaria una logica di runtime. Considerare che imporrebbe un accoppiamento libero è un'illusione: esiste lo stesso livello di dipendenza tra qualcosa che si chiama direttamente o si aggancia, la chiamata deve comunque riempire il suo contratto.

Nota che forse alcune persone chiamano metodo-template con funzioni sovraccariche di aggancio, ma questo è diverso da quanto sopra: qui hai un collegamento statico, con un rischio minore di entrare in un incubo di manutenzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.