Gli eventi / le funzioni devono essere ridefinite a ogni livello per un'API?

1

Generalmente scrivo codice che uso solo, ma ho un github pubblico con alcune librerie JS. Un componente chiave della maggior parte delle librerie sono gli eventi. La mia domanda può essere supponente, ma non so dove altro postarla ed è importante per me come perfezionista.

Durante la scrittura di un'API gli eventi devono essere inviati nuovamente attraverso ogni livello, o ci si dovrebbe aspettare che un cliente sappia come accedere a quegli eventi?

Esempio

class Button {
     onClick(){
         this.emit('click');
     }
}

class UI {
     constructor(){
           let self = this;
           this.button = new Button();
           // is this necessary?
           this.button.on('click', function(){
                self.emit('button.click');
           });
      }
}

class Application {
        constructor(){
             this.ui = new UI();
             // this?
             this.ui.on('button.click', function(){

             });
             // or is this acceptable?
             this.ui.button.on('click', function() {

              });
        }
}

Questa è una domanda abbastanza ampia, poiché sto anche chiedendo la necessità di fare o non fare questo:

class Foo {
    explode(){
        console.log('boom');
    }
} 

class Bar {
   constructor(){
     this.foo = new Foo();
   }

   // necessary?
   explodeFoo(){
      return this.foo.explode();
   }
}

class Application(){
    constructor(){
        this.bar = new Bar();
        // this? 
        this.bar.explodeFoo();
        // or is this fine?
        this.bar.foo.explode();
    }
}
    
posta J Doe. 17.07.2017 - 19:58
fonte

1 risposta

2

Chiamata diretta

Se vuoi che il chiamante sia in grado di manipolare gli oggetti contenuti, e l'applicazione principale non ha bisogno di fare nulla per coordinare tale attività, allora va bene, ed è meno lavoro:

this.bar.foo.explode();

Tieni presente che se cambi mai l'implementazione di bar , il codice del chiamante si interromperà. Questa è sempre una preoccupazione quando si interrompe l'incapsulamento.

Chiamata avvolta

Se le attività del chiamante devono essere controllate (ad esempio se a volte non è OK esplodere qualcosa) o se sono necessari ganci per le applicazioni per coordinare le cose (ad esempio per registrare le azioni dell'applicazione), allora il seguente sarebbe meglio:

explodeFoo() {
    if (this.explodeAllowed) {
        this.bar.foo.explode();
        this.logExplosion("Foo");
    }
}

this.bar.explodeFoo();

Se non avevi il metodo wrapper explodeFoo , non ci sarebbe nessun posto dove aggiungere il controllo explodeAllowed o implementare la registrazione. Per questo motivo, potresti anche voler introdurre la chiamata al metodo avvolto prima che tu ne abbia effettivamente bisogno; in questo modo puoi aggiungere ganci senza problemi nelle versioni future.

Suppongo che potresti saltare il wrapper e scrivere semplicemente la documentazione che dice a chiunque usi la tua API che devono prima controllare il flag explodeAllowed , ad esempio. Tuttavia ciò introdurrebbe quello che è noto come accoppiamento sequenziale non forzato, che è un anti-pattern.

    
risposta data 17.07.2017 - 21:55
fonte

Leggi altre domande sui tag