Best practice per i parametri nelle API asincrone in Java

6

Esiste una best practice per l'utilizzo di ListenableFuture di Guava nei parametri nelle chiamate API? Confronta queste due versioni di un'interfaccia che internamente fa un confronto-e-set (sto usando il ListenableFuture di Guava):

interface MyDao {
    ListenableFuture<Data> getData(String id);
    ListenableFuture<Boolean> updateData(ListenableFuture<Data> data, int newFieldValue);
}

interface MyDao {
    ListenableFuture<Data> getData(String id);
    ListenableFuture<Boolean> updateData(Data data, int newFieldValue);
}

La prima sembra un po 'caotica, e l'implementazione probabilmente coinvolgerà un Futures.transform del proprio, ma si potrebbe anche sostenere che si tratta di un'API asincrona, quindi prendere i future in quanto i parametri potrebbero avere senso. Dove è bello è che riordina la logica di business quando si utilizza l'interfaccia in modo che legga come codice sincrono:

ListenableFuture<Data> data = dao.getData("123");
ListenableFuture<Boolean> success = dao.updateData(data, 10);

Confrontalo con

ListenableFuture<Data> data = dao.getData("123");
ListenableFuture<Boolean> success = Futures.transform(data, (Data d) -> dao.updateData(d, 10));

E questo è con un lambda. È orribile in Java 7.

L'ovvio inconveniente è che l'interfaccia sembra incoerente. Perché data è un futuro, ma newFieldValue non lo è? Anche il id dovrebbe essere un futuro? Accanto a queste linee, rende una chiamata banale incredibilmente complicata, quasi come gli oggetti wrapper Java prima dell'autoboxing.

Inoltre non fa nulla per ripulire le orribili tracce dello stack quando i futures falliscono; sono ancora in cascata ogni transform .

    
posta David Ehrmann 24.09.2015 - 02:56
fonte

1 risposta

1

Penso che avere un ListenableFuture in un metodo di firma API non lo renda incoerente.

È solo lì per dichiarare explicity all'utente un calcolo asincrono mentre nasconde la logica del threadplateplano. Come Optional dichiarerebbe esplicita all'utente la possibilità di perdere dati mentre nasconde la logica "se non nulla".

Questi 2 link spiegano un po 'di più i miei pensieri: Monadic Java e Uso di

facoltativo

Tuttavia, se ritieni che qualsiasi utente della tua API desideri potenzialmente chiamare updateData ma abbia solo un'istanza di Data potresti prendere in considerazione l'aggiunta del metodo corrispondente alla tua API.

public interface MyDao {
    ListenableFuture<Boolean> updateData(ListenableFuture<Data> data, int newFieldValue);
    ListenableFuture<Data> getData(String id);
    default ListenableFuture<Boolean> updateData(Data data, int newFieldValue) {
        //TODO: wrap data in a ListenableFuture and call updateData
    }
}
    
risposta data 24.09.2015 - 11:18
fonte

Leggi altre domande sui tag