Valutazione di (a) progetto sincrono dell'interfaccia di contabilità generale

0

Attualmente sto progettando un'API di contabilità generale, che dovrebbe funzionare con diverse implementazioni (ad esempio basate su Blockchain, database tradizionali o file).

Il suo scopo è aggiungere / ricevere messaggi a / da un libro mastro di calcestruzzo. I messaggi vengono incapsulati nelle transazioni, che hanno ulteriori metadati come ora e autore, ecc. L'inizializzazione avviene in un LedgerProvider , che non è incluso.

Ci sono anche altre parti che scrivono nel libro mastro (ad esempio nel caso di un'implementazione basata su blockchain).

Domanda L'interfaccia del libro mastro dovrebbe essere progettata sincrona o asincrona? E perché? A quali dati dovresti dare un'occhiata quando prendi questa decisione?

Un registro sincrono dovrebbe essere interrogato dai suoi utenti, i callback sembrano più convenienti. D'altra parte, anche classi come InputStream sono sincrone e alcuni meccanismi di callback possono essere costruiti sopra (i polling di libraray sono internamente e richiama callback registrati).

Sotto la versione sincrona.

/**
 *
 * @param <M> Message type
 */
public interface Ledger<M> {    
    Transaction<M> addTransaction(M message);
    List<Transaction<M>> getTransactions();
    List<Transaction<M>> getTransactions(LocalTime since, LocalTime to);
}

Ecco come sarebbe la versione asincrona.

public interface Ledger<M> {    
    Transaction<M> addTransaction(M message);    
    void registerObserver(Observer o);    
    void unregisterObserver(Observer o);    
}

public interface Observer<M> {
    void update(Transaction<M>  tx);
}
    
posta mike 07.09.2018 - 08:55
fonte

1 risposta

1

Suppongo che tu usi i termini sincrono e asincrono come definito da UML:

A Behavior may be invoked synchronously or asynchronously. Synchronous invocation means that an invoking Behavior retains a reference to the invoked Behavior execution and waits for the execution to complete. Asynchronous invocation, on the other hand, means that the invoked Behavior execution proceeds concurrently with the invoking Behavior.

Ma prima alcune osservazioni:

  • AddTransaction() ha un design sincrono in entrambe le interfacce a causa del suo valore di ritorno. Quindi l'interfaccia non sarebbe puramente asincrona.
  • Qualsiasi metodo con un progetto sincrono può essere invocato in modo asincrono (in java, utilizzando CompletableFuture ).

Quindi la principale differenza tra voi due design non è la sincronicità, ma il modo in cui vi consentono di accedere ai dati. Pertanto ti suggerisco caldamente di utilizzare il push più preciso pull terminologia invece.

L'interfaccia pull ("sincrono"):

Il consumatore deve interrogare il libro mastro quando i dati sono dati necessari.

Vantaggio:

  • Il consumatore può ottenere un'immagine completa del libro mastro o un sottoinsieme limitato a un intervallo di tempo.

Inconvenienti:

  • È difficile e inefficiente ottenere solo nuove transazioni.
  • Non è possibile garantire che le nuove transazioni contabili siano elaborate esattamente una volta se non si è anche l'originatore.

Quindi, se devi reagire alle nuove transazioni, dovresti interrogare frequentemente l'intervallo di tempo più recente e filtrare le transazioni che hai già visto. Questa è una risorsa inefficiente (CPU, rete, ...)

E se hai bisogno di fare qualcosa esattamente - una volta che il filtraggio sarebbe inaffidabile. Perché, come puoi filtrare in modo affidabile i dati già ricevuti:

  • in base al timestamp? ma il timestamp è abbastanza affidabile?
  • basato su una bandiera? ma è possibile con un libro mastro blockchain-write-once?
  • in base a un elenco di transazioni già elaborate? Ma come renderlo persistente quando il processo viene arrestato?

Conclusione:

  • se hai bisogno di elaborare esattamente una volta le nuove transazioni, non puoi fare affidamento su questa interfaccia.
  • se devi monitorare nuove transazioni, questa interfaccia potrebbe causare inefficienze.

L'interfaccia push ("asincrona")

I consumatori sono informati dal registro quando qualcosa di nuovo sta accadendo. Quindi è un evento drivent.

Vantaggio:

  • Il monitoraggio delle nuove transazioni è molto efficiente. Non ci sono risorse spese per attendere i dati o filtrare i dati non necessari.

Inconvenienti:

  • Non è possibile ottenere un set o un sottoinsieme delle transazioni nel libro mastro, a meno che non si crei una copia di ogni transazione.
  • È difficile e inaffidabile effettuare analisi su cifre passate, perché dovresti aggiornare gli indicatori (min, max, sum, average, ..) in tempo reale e i dati registrati nel libro mastro mentre il processo è inattivo non sarebbe stato ricevuto

Conclusione:

  • Se vuoi monitorare in modo reattivo il tuo libro mastro, questa è l'interfaccia ideale
  • Se vuoi elaborare i dati storici delle transazioni, questo è quasi impossibile con questa interfaccia.

Conclusione

Hai qui due interfacce che sono adattate per soddisfare esigenze molto diverse. Quindi non esiste una scelta migliore universale: dipenderà dai tuoi casi d'uso.

Poiché le due interfacce non si escludono a vicenda, perché non combinarle per beneficiare della loro rispettiva forza?

    
risposta data 08.09.2018 - 18:41
fonte