pattern listener di eventi in api: cosa dovrebbe fare due volte lo stesso ascoltatore?

8

Nella progettazione di un'API che fornisce un'interfaccia per l'ascolto di eventi, sembra che ci siano due modi contrastanti di trattare le chiamate per aggiungere / rimuovere listener:

  1. Più chiamate a addListener aggiungeranno un solo listener (come aggiungendolo a un set); può essere rimosso con una sola chiamata a removeListener.

  2. Più chiamate a addListener aggiungeranno un listener ogni volta (come aggiungerlo a un elenco); deve essere bilanciato da più chiamate a removeListener.

Ho trovato un esempio di ciascuno: (1) - La chiamata addEventListener del DOM nei browser aggiunge solo gli ascoltatori una volta, silenziosamente ignorando le richieste di aggiungere lo stesso listener una seconda volta e (2) - jQuery .on behavior aggiunge listener più volte .

La maggior parte delle altre API listener sembrano utilizzare (2), come i listener di eventi SWT e Swing. Se viene scelto (1), c'è anche la domanda se debba fallire in modo silenzioso o con un errore quando c'è una richiesta di aggiungere lo stesso listener due volte.

Nelle mie implementazioni, tendo ad attenermi a (2) poiché fornisce un'interfaccia di tipo clean setup / teardown e rivela bug in cui "setup" viene eseguito involontariamente due volte ed è coerente con la maggior parte delle implementazioni che ho visto.

Questo mi porta alla mia domanda - Esiste una particolare architettura o altra struttura di base che si presti meglio all'altra implementazione? (es: perché esiste l'altro modello?)

    
posta Krease 02.01.2013 - 18:42
fonte

2 risposte

2

Se hai alcuni eventi a cui stai incontrando problemi con la gestione dell'aggiunta / rimozione, inizierei ad aggiungere gli ID.

Aggiungi un listener restituisce un ID, la classe che lo ha aggiunto tiene traccia degli ID per gli ascoltatori aggiunti e quando è necessario rimuoverli, chiama remove listener con quegli / quegli ID univoci.

Ciò mette i consumatori sotto controllo in modo che possano ottenere la conformità con Principio di Almostonation nel comportamento.

Questo significa che aggiungere lo stesso due volte lo aggiunge due volte, fornisce un ID diverso per ciascuno e la rimozione per ID rimuove solo quella associata a quell'ID. Chiunque utilizzi l'API si aspetta questo comportamento quando ha visto i sig.

Un'ulteriore aggiunta in violazione di YAGNI sarebbe un GetIds in cui lo consegni a un listener e restituisce un elenco di ID associati a quell'ascoltatore se è in grado di ottenere controlli di uguaglianza appropriati, sebbene ciò dipenda dalla tua lingua: fa riferimento all'eguaglianza, tipo uguaglianza, valore uguaglianza, ecc.? bisogna stare attenti qui perché è possibile restituire gli ID che il consumatore non deve rimuovere o intromettersi, quindi questa esposizione diventa pericolosa e sconsigliabile e non dovrebbe essere necessaria, ma i GetID sono una possibile aggiunta se vi sentite fortunati.

    
risposta data 02.01.2013 - 19:55
fonte
3

In primo luogo, sceglierei un approccio in cui l'ordine in cui vengono aggiunti gli ascoltatori è esattamente l'ordine in cui verranno chiamati quando vengono attivati gli eventi correlati. Se decidi di andare con (1), ciò significa che usi un set ordinato, non solo un set.

In secondo luogo, dovresti chiarire un obiettivo generale di progettazione: la tua API seguirà più una strategia "crash early" o una strategia "error perdiving"? Questo dipende dall'ambiente di utilizzo e dagli scenari di utilizzo della tua API. Generalmente, (sviluppando principalmente app desktop) preferisco "crash early", ma a volte è meglio tollerare alcuni tipi di errori per rendere più fluido l'uso di un'API. I requisiti, ad esempio, in app empressive o app server potrebbero essere diversi. Forse ne parli con uno dei tuoi potenziali utenti API?

Per una strategia "crash early", usa (2), ma non aggiungere due volte lo stesso listener, lanciare un'eccezione se un listener viene aggiunto di nuovo. Inoltre, lancia un'eccezione se si tenta di rimuovere un listener non presente nell'elenco.

Se ritieni che una strategia "error perdiving" sia più appropriata nel tuo caso, puoi

  • ignora la doppia aggiunta dello stesso listener all'elenco - che è l'opzione (1) -, o

  • aggiungilo alla lista come in (2), quindi verrà chiamato due volte quando gli eventi vengono lanciati

  • o lo aggiungi, ma non chiama lo stesso ascoltatore due volte in caso di attivazione dell'evento

Si noti che la rimozione del listener dovrebbe corrispondere a quella - se si ignora la doppia aggiunta, si dovrebbe anche ignorare la doppia rimozione. Se consenti allo stesso ascoltatore di essere aggiunto due volte, dovrebbe essere chiaro quale delle due voci listener verrà rimossa quando si chiama removeListener(foo) . L'ultimo dei tre proiettili è probabilmente l'approccio meno incline agli errori tra questi suggerimenti, quindi in caso di una strategia di "errore perdonare", andrei con quello.

    
risposta data 02.01.2013 - 19:31
fonte

Leggi altre domande sui tag