Nun, funktionaler Ansatz meiner Meinung nach wird Try
Monade zu verwenden, die leider für uns in jdk nicht gibt es 8 :(
Trotzdem noch Sie better-monads library, die es bietet. Mit, dass Sie verwenden können, mit einigen Umsetzung kommen wie diese können:
public static <Out> Try<Out> tryTimes(int times, TrySupplier<Out> attempt) {
Supplier<Try<Out>> tryAttempt =() -> Try.ofFailable(attempt::get);
return IntStream.range(1, times)
.mapToObj(i -> tryAttempt)
.reduce(tryAttempt, (acc, current) ->() -> acc.get().recoverWith(error -> current.get()))
.get();
}
Lange Rede kurzer Sinn diese Funktion nur Ketten Anrufe von tryAttempt
und bei gescheiterten Versuch, versucht, den nächsten cal recoverWith
l von tryAttempt
. Client-Code wird wie folgt aussehen:
tryTimes(10,() -> {
// all the logic to do your possibly failing stuff
}
);
Als Ergebnis Client-Code wird Try<T>
erhalten, die durch direkten Aufruf von .get()
entpackt werden kann (im Erfolgsfall liefert den Wert, im Fall des Scheiterns Würfe zugrunde liegenden Ausnahme) oder mit anderen in der Bibliotheksdokumentation beschriebenen Methoden.
Ich hoffe, es hilft.
UPDATE:
Dies auch in funktioneller Art und Weise getan werden kann, mit den filter
, findFirst
und limit
und ohne externe Bibliotheken:
interface ThrowingSupplier<Out> { Out supply() throws Exception; }
public static <Out> Optional<Out> tryTimes(int times, ThrowingSupplier<Out> attempt) {
Supplier<Optional<Out>> catchingSupplier =() -> {
try {
return Optional.ofNullable(attempt.supply());
} catch (Exception e) {
return Optional.empty();
}
};
return Stream.iterate(catchingSupplier, i -> i)
.limit(times)
.map(Supplier::get)
.filter(Optional::isPresent)
.findFirst()
.flatMap(Function.identity());
}
Der Client-Code bleibt gleich. Beachten Sie auch, dass der Ausdruck times
nicht ausgewertet wird, sondern beim ersten erfolgreichen Versuch gestoppt wird.
Was ist in diesem Code hässlich? Um es erneut zu versuchen, müssen Sie eine Schleife (oder Rekursion) durchführen. (verwandt: http://stackoverflow.com/questions/34740091/apply-retries-in-a-rxjava und http://stackoverflow.com/questions/30989558/java-8-retry-a-method-until-a -condition-is-in-intervalls erfüllt) – Tunaki
Ja, ich weiß, vielleicht bin ich hier zu pingelig, aber ich frage mich nur, ob das "funktional" oder "deklarativ" gemacht werden kann, weil das oft mehr ist lesbar ... – Moonlit
Was hässlich ist, ist, dass es den Code für eine bestimmte Aufgabe mit der Wiederholungs-/Fehlermanagementlogik zusammenfasst. Das bedeutet, dass Sie die Wiederholungslogik überall kopieren würden, wahrscheinlich durch Ausschneiden und Einfügen, wodurch es praktisch unmöglich wird, Ihr Wiederholungsverhalten später konsistent anzupassen. –