Design per una funzione per saltare un passaggio se chiamato più volte

0

Titolo terribile, ma questa è la situazione in cui mi trovo spesso e non ho trovato un buon design per renderlo bello. Diciamo che sto lavorando con Javascript e ho un oggetto su cui sto lavorando che deve persistere in un DB quando vengono apportate modifiche.

obj = {
  users : [
    {425: {name:'test'}},
    {427: {name:'test1'}},
    {450: {name:'test2'}},
  ],
  deleteUser : function(id){
     delete this.users[id];
     //maybe some other code (ui manipulation)
     this.persist();
  },
  deleteAllUsers : function(){
  var me = this;
    var uids = Object.keys(this.users);
    uids.forEach(function(u, i){
      me.deleteUser(i);
    });
    this.persist();
  },
  persist: function(){
    //some ajax call that persists the users array
    console.log('persist');
    return;
  },
};

obj.deleteAllUsers();

Quindi, al momento, quando chiami deleteAllUsers , verrà mantenuto su ogni chiamata a deleteUser . Voglio deleteUser per saltare il passaggio persistente poiché verrà chiamato più tardi nella funzione di chiamata.

Le due soluzioni che ho pensato:

  1. Duplica il codice da deleteUser a deleteAllUsers e solo alla fine persi. (No, è terribile).

  2. Definisci deleteUser come deleteUser(id, persist) , quindi possiamo specificare nell'argomento persistente se dovremmo chiamare persist oppure no. Questa è una soluzione ok, ma ritengo che non sia l'ideale.

C'è qualche schema di progettazione che si occupa di questo? O qualcuno ha trovato un modo molto pulito per affrontare questa situazione?

    
posta dan08 26.04.2016 - 18:04
fonte

3 risposte

1

Per molti casi, uso semplicemente il flag come il tuo secondo esempio:

  deleteUser : function(id, isPersist){
     delete this.users[id];
     //maybe some other code (ui manipulation)

     if (isPersist)
         this.persist();
  }

  deleteAllUsers : function(){
  var me = this;
    var uids = Object.keys(this.users);
    uids.forEach(function(u, i){
      me.deleteUser(i, false);
    });

    this.persist();
  }

  persist: function(){
    //some ajax call that persists the users array
    console.log('persist');
    return;
  },

A volte però, potrei avere questa struttura:

  deleteSingleUser : function(id){
     me.deleteUser(id);
     this.persist();
  }

  deleteAllUsers : function(){
  var me = this;
    var uids = Object.keys(this.users);
    uids.forEach(function(u, i){
      me.deleteUser(i);
    });
    this.persist();
  }

  deleteUser : function(id){
     delete this.users[id];
     //maybe some other code (ui manipulation)
  }

  persist: function(){
    //some ajax call that persists the users array
    console.log('persist');
    return;
  }

(La convenzione di denominazione potrebbe probabilmente essere migliore, per chiarire quali documenti persistono in db e che si preparano solo per la cancellazione senza persistere. Sono troppo pigro per pensarli adesso.)

Quello che uso in genere dipende da

  • Se ho un codice personalizzato per l'eliminazione di un singolo utente che non dovrebbe essere eseguito quando si eliminano più utenti. In tal caso, il secondo set di codice è migliore.

  • Se mai desidero eliminare un singolo utente senza persistente, come consentire agli utenti di effettuare cancellazioni multiple senza salvare fino a quando non premono un pulsante "Salva". In questo caso, utilizzerei il primo segmento di codice con il flag isPersist .

  • Quanti posti chiamano deleteUser . Se lo chiamo solo da uno o due posti, ho molte più probabilità di usare una bandiera. Ma se lo sto facendo in molte aree dell'applicazione, sono più propenso a usare il secondo caso per evitare di dover digitare molto il parametro extra per isPersist .

risposta data 26.04.2016 - 18:48
fonte
2

Inserendo il tutto in un IIFE , puoi creare variabili e funzioni private. In questo modo, l'API esposta può racchiudere le funzioni private in qualsiasi modo, e persist verrebbe chiamato solo quando si utilizza l'eliminazione pubblica:

var obj;
(function() {
    function realDelete(id) {
        delete obj.users[id];
        //maybe some other code (ui manipulation)
    }
    obj = {
      users : [
        {425: {name:'test'}},
        {427: {name:'test1'}},
        {450: {name:'test2'}},
      ],
      deleteUser : function(id){
         realDelete(id);
         this.persist();
      },
      deleteAllUsers : function(){
        var uids = Object.keys(this.users);
        uids.forEach(function(u, i){
            realDelete(i);
        });
        this.persist();
      },
      persist: function(){
        //some ajax call that persists the users array
        console.log('persist');
        return;
      },
    };
})();

obj.deleteAllUsers();
    
risposta data 26.04.2016 - 18:51
fonte
1

Penso che l'interfaccia per deleteUser() e deleteUsers() dovrebbe essere simile, quindi sono contrario alla tua seconda soluzione.

In questo scenario, manterrò il metodo deleteUser() e internamente delegato a un metodo di persistenza privato. Per motivi di coerenza, farei lo stesso per deleteUsers() . In questo modo si mantengono coerenti le interfacce pubbliche e anche gli interni sono coerenti (a spese di un metodo privato condiviso)

    
risposta data 26.04.2016 - 18:19
fonte

Leggi altre domande sui tag