Come si fa un servizio senza stato?

5

Quando si esegue Domain Driven Design si consiglia che i servizi siano senza stato. Esistono diversi tipi di servizi durante il DDD:

  • Servizi applicativi.
  • Servizi di dominio.
  • Servizi di infrastruttura
  • Fabbriche, archivi, specifiche, ecc.

Come faccio a rendere un servizio senza stato?

Significa che non dovrei avere alcuna variabile di istanza in una classe? C'è qualche indicazione su come rendere un servizio / classe apolide?

Potrei davvero utilizzare un esempio di codice che illustri la differenza tra un servizio stateful e stateless.

Esempio: (questa classe è di stato o no?)

Class DataToCsvFileGenerator{

    private String filePath;
    private ResultSet data;

    public String createCsv(ResultSet data){
       this.data=data;

       this.createLocalFile();
       this.loadDataIntoFile();

       return this.filePath;
    }

    private void createLocalFile(){    
        this.filePath=//... logic to create file    
    }

    private void loadDataIntoFile(){    
        //function uses this.filePath to load data    
    }
}

Tieni presente che eventuali chiamate successive a createCsv() non saranno interessate da alcuna chiamata precedente.

    
posta Songo 06.08.2014 - 13:52
fonte

5 risposte

9

I servizi stateless non tracciano le informazioni da una chiamata all'altra. Ciò significa che non possono avere variabili di istanza impostate come risultato della chiamata a un metodo. Possono avere variabili di istanza di cui ha bisogno il servizio, come un logger o le proprietà necessarie per operare.

Un servizio clienti non tiene traccia delle informazioni relative a un cliente da una chiamata all'altra. Qualsiasi informazione necessaria per rintracciare il cliente verrebbe salvata esternamente e recuperata secondo necessità. Solitamente viene utilizzato un database per la persistenza, ma in alcuni casi i servizi Web potrebbero utilizzare cookie o altri meccanismi del lato client.

La tua classe sembra essere stateful, sebbene lo stato non sia utile. Tuttavia, metodi aggiuntivi potrebbero rendere le tue variabili di istanza accessibili pubblicamente. Una modifica semplice come eseguire un generatore in un IDE potrebbe farlo. La seguente riscrittura è senza stato. Si noti che la variabile del logger, conterrebbe un riferimento al logger e non conterrebbe lo stato della classe. L'inizializzazione e l'uso del logger sono stati omessi.

Class DataToCsvFileGenerator{

    Static Logger logger; 

    public String createCsv(ResultSet data){
       String filePath = createLocalFile();
       this.loadDataIntoFile(filePath, data);

       return filePath;
    }

    private String createLocalFile(){    
        string filePath=//... logic to create file 
        return filePath;   
    }

    private void loadDataIntoFile(String filePath, ResultSet data){    
        //function uses filePath to load data    
    }
}
    
risposta data 06.08.2014 - 14:03
fonte
4

Certo, il libro DDD non lo rende molto chiaro, ma quando dice "senza stato" significa "senza persistente o longevo stato". Quindi, gli oggetti di servizio sono permessi di mantenere lo stato nei loro campi / variabili di istanza, a patto che non sia lo stato che viene mantenuto persistente o esternalizzato in qualche modo.

Lo stato di cui si occupa il libro, quando si parla di stato, è lo stato mantenuto nel dominio entità e in oggetti di valore , poiché lo stato normalmente viene memorizzato e ricostituito da alcuni archivi esterni (un database relazionale, file) o tenuti in memoria per periodi arbitrariamente lunghi e possono essere raggiunti da thread diversi (come in un oggetto "carrello del cliente online").

Gli oggetti di servizio che sono di breve durata (cioè gli oggetti veri), in particolare, sono particolarmente adatti allo stato di istanza, dato che (normalmente) vengono creati da un singolo thread e accessibili solo da quello stesso thread.

    
risposta data 15.04.2016 - 19:25
fonte
1

Naturalmente puoi avere variabili di istanza in una classe ma l'istanza di classe non esiste più alla prossima chiamata se hai un servizio stateless.

un servizio statefull classico è un carrello in cui è possibile aggiungere articoli. con questi metodi di servizio statefull:

  • createCart
  • addArticleToCart (quantità, articleid)
  • removeArticleFromCart (quantità, articleid)
  • ....

puoi rendere un servizio senza stato se fornisci tutte le informazioni necessarie come parametri della chiamata:

  • createCart restituisce un cartID
  • addArticleToCart (cartID, quantity, articleid)
  • removeArticleFromCart (cartID, quantity, articleid)

lo statoful cartService è responsabile di ricordare il cartID.

il cartService stateless ottiene il cartID su ever servicecall.

    
risposta data 06.08.2014 - 17:20
fonte
1

(Is this class stateful or not?)

Sì, è stato.

Ora non è ...

    Class DataToCsvFileGenerator{

      public string createCsv(ResultSet data, string filePath){
         string fullFilePath = string.Empty;

         fullFilePath = this.createLocalFile(filePath);
         this.loadDataIntoFile(data, fullFilePath);

         return fullFilePath;
      }

      private string createLocalFile(string filePath){    
          filePath=//... logic to create file    
      }

      private void loadDataIntoFile(ResultSet data, string filePath){    
          //function uses filePath to load data    
      }
    }
    
risposta data 06.08.2014 - 18:50
fonte
0

Nel tuo caso specifico dovrebbe essere fatto come dice @radarbob.

Comunque per rispondere in un modo più generale, nel mio progetto la maggior parte dei miei servizi sono stateful se parliamo solo di raw design, ma ora se si considera che in realtà sto usando un framework DI (Spring nel mio caso) , sto solo iniettando altri servizi, che saranno costruiti da Spring in questo modo. una volta terminato, non cambierò mai uno dei miei campi.

Quindi è stato definito sul design, ma nell'uso si comportano allo stesso modo dell'oggetto stateless.

Esempio:

public class PeopleService{
    private RightsService rightsService;
    //+setter to init with spring
}

Questo è stateful di progettazione perché hai la possibilità di cambiare il rightsService, ma finché non lo fai, avrai lo stesso comportamento di un oggetto stateless (supponendo che RightsService stia seguendo lo stesso comportamento).

Nota: se vogliamo essere puristi, invece di usare setter, puoi usare i campi finali e inizializzarlo nel costruttore. In questo modo avrai davvero un oggetto stateless.

    
risposta data 07.09.2016 - 09:22
fonte