API Design - Observable vs Callback

7

Come team stiamo scrivendo un C # SDK che comunica con un endpoint del server. Tutte le nostre API fino ad ora sono state basate su attività. Come

Operazione DoOperationAsync ()

Recentemente abbiamo superato la necessità dell'API che ottiene un aggiornamento intermedio (posizione del file) prima di quello finale se l'utente lo sceglie.

DoSomething (bool interestedInIntermediateFile)

Ci sono due opzioni disponibili sulla tabella

  1. Rx.IObservable < OpResult > DoSomething (bool interestedInInmedia File)

  2. Attività < OpResult > DoSomething (Action < string > intermediateFile)

Dove OpResult {Enum CompletionReason, enum FileType, string FileLoc}

FileType - Intermediate, Final

CompletionReason - Reason (applicabile solo se FileType è definitivo)

Volevo sapere dagli esperti che sarebbe stato un buon progetto API.

Note: vediamo che alcune delle nuove API future sarebbero osservabili. Quindi non sarà il caso che questa sia solo API osservabile.

Aggiungere una nota aggiuntiva - poiché potrebbe non essere così ovvio da sopra.

CompletionReason contains a value only in the final update the intermediate update will have this as null. As the intermediate update, final result though related but not exact (in terms of populating fields) has been raised as a downside to observable. Is it a genuine downside.

Grazie in anticipo.

    
posta Shenron 27.04.2018 - 08:25
fonte

2 risposte

7

La decisione su quale tecnologia utilizzare sarà in gran parte relativa alle competenze del tuo team e al pubblico a cui è rivolto il tuo SDK, e in una certa misura se la tua API a lungo termine trarrà vantaggio dall'essere un fornitore di flussi osservabili.

Rx.NET è un modo molto potente e flessibile di fare le cose, e raccomanderei qualsiasi sviluppatore .NET che abbia bisogno di gestire simultaneità e / o flussi di eventi per esaminarlo.

(Suppongo che per "IObservable" intendi Rx.Net o stai guardando in streaming su Akka o qualcosa del genere?)

Tuttavia, entrare nel modo di pensare osservabile da parte di IO può essere una curva di apprendimento ripida.

C'è molta sovrapposizione tra Task e Rx.NET. Una spiegazione della sovrapposizione è qui ma secondo me è di parte a favore di Task.

Se prevedi che la tua API si occuperà di flussi asincroni, come il ritorno di lunghi elenchi di dati, o la guida di un modello push, o se desideri combinare più flussi, allora guarda in Rx.NET

Se si prevede che la propria API trarrà vantaggio da LINQ su flussi (con Rx.NET è possibile interrogare facilmente IObservables in quanto sono la versione "push" di IEnumerable, la versione "pull"), quindi esaminare Rx.NET. Per esempio, guarda. Dove. Seleziona. Seleziona Mamma. Esci. Scorri. Operatori di scansione in Rx.NET e decidi se ne avrai molti usi.

Se vedi che la tua API diventerà un servizio di streaming del modello push e se disponi delle competenze disponibili, potresti prendere seriamente in considerazione Rx.NET

Se è solo il piccolo problema che hai descritto nel tuo post originale, potrebbe non valere la pena di sovraccaricare l'apprendimento del modo Rx a meno che tu non abbia già competenze a portata di mano. In sostanza, la catena di compiti (vedere Attività secondarie associate qui ) è un IObservable Rx minimizzato. Il vantaggio è che questo codice è intuitivo per molti sviluppatori. Non è necessario visualizzarlo come IObservable vs Callback, un'attività non è un callback e le attività figlio (passaggi intermedi) possono essere restituite come una raccolta di attività (ad esempio: è possibile comporre le attività come un elenco come attività finale + task intermedio, quindi attendere When Any o alcuni di questi, magari allegare l'intermedio come task secondari).

Aggiornamento: la preoccupazione sollevata nell'aggiornamento secondo cui il messaggio di completamento dell'operazione verrà generato con un valore nullo durante le fasi intermedie non ha alcun senso. Indipendentemente dall'approccio adottato, i passaggi intermedi non descriveranno il motivo del completamento dell'operazione, a meno che, ovviamente, il passaggio intermedio sia post-hoc come fase finale. Nel 1 ° scenario (Attività): la tua azione intermedia non solleverà un motivo di completamento (null). Nel secondo scenario (Osservabili): le tue azioni intermedie non risolveranno un motivo di completamento. Qual è la differenza? Quello che dovresti fare nel caso dell'Osservable è dichiararlo osservabile come "risultato dell'azione". Questo è semanticamente equivalente a Task (un risultato futuro ). Dichiara X tipi di messaggio di risultato. Ad esempio:

public class ResultMessage

public class FinalResultMessage: ResultMessage

etc

Quindi puoi implementare Task o IObservable come desideri.

Se segui la rotta di Osservabile. Puoi offrire .Finally nel sottoscrittore o nell'osservabile per gestire FinalResultMessage.

In breve, non rendere l'API un IObservable ma IObservable se segui questa strada e applica lo stesso pensiero anche per Task.

    
risposta data 27.04.2018 - 09:53
fonte
1

Dipende dal tuo utente API.

Nel complesso Tuttavia, proverei a verificare che l'API corrisponda in qualche misura alle chiamate del server sottostante.

Fornendo un osservabile hai essenzialmente introdotto lo stato nell'equazione. Ho bisogno di aggrapparmi a quell'osservabile fino a quando non ha finito di inviarmi aggiornamenti. Il client deve associare quello Osservabile con gli aggiornamenti in arrivo dal server relativi alla richiesta originale.

Se il tuo server sta inviando un flusso costante di dati, questa sarebbe una buona corrispondenza. (anche se potresti voler guardare in un flusso)

Se il tuo server divide il lavoro in due operazioni, ad esempio Start e PollToGetResult. Quindi hai introdotto lo stato in cui non hai bisogno. Sarebbe meglio esporre le operazioni separate sulla tua API

    
risposta data 27.04.2018 - 12:30
fonte

Leggi altre domande sui tag