• Keine Ergebnisse gefunden

Reaktive Programmierung

N/A
N/A
Protected

Academic year: 2022

Aktie "Reaktive Programmierung"

Copied!
2
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Reaktive Programmierung

Vorlesung 8 vom 10.06.14: Reactive Streams II

Christoph Lüth & Martin Ring Universität Bremen Sommersemester 2014

1 [15]

Fahrplan

I Teil I: Grundlegende Konzepte I Teil II: Nebenläufigkeit

IFutures and Promises

IReaktive Datenströme I

IReaktive Datenströme II

IFunktional-Reaktive Programmierung

IAktoren

IAktoren und Akka

I Teil III: Fortgeschrittene Konzepte

2 [15]

Rückblick: Observables

I Observables sind „asynchroneIterables“

I Asynchronität wird durchInversion of Controlerreicht

I Es bleiben drei Probleme:

I Die Gesetze der Observable können leicht verletzt werden.

I Ausnahmen beenden den Strom -Fehlerbehandlung?

I Ein zu schneller Observable kann den Empfangenden Threadüberfluten

3 [15]

Datenstromgesetze

I onNext*(onError|onComplete)

I Kann leicht verletzt werden:

Observable[Int] { observer⇒ observer.onNext(42) observer.onCompleted() observer.onNext(1000) Subscription() }

I Wir können die Gesetze erzwingen:CODE DEMO

4 [15]

Fehlerbehandlung

I Wenn Datenströme Fehler produzieren, können wir diese möglicherweise behandeln.

I Aber:Observer.onErrorbeendet den Strom.

observable.subscribe(

onNext = println, onError = ???,

onCompleted = println("done"))

I Observer.onErrorist für die Wiederherstellung des Stroms ungeeignet!

I Idee: Wir brauchen mehr Kombinatoren!

5 [15]

onErrorResumeNext

defonErrorResumeNext(f:⇒Observable[T]): Observable[T]

6 [15]

onErrorReturn

defonErrorReturn(f: ⇒T): Observable[T]

7 [15]

onErrorFlatMap

defonErrorFlatMap(f: Throwable⇒Observable[T]): Observable[T]

8 [15]

(2)

Schedulers

I Nebenläufigkeit überScheduler

trait Scheduler {

defschedule(work:⇒Unit): Subscription }

trait Observable[T] { ...

defobserveOn(schedule: Scheduler): Observable[T]

}

I CODE DEMO

9 [15]

Littles Gesetz

I In einer stabilen Warteschlange gilt:

L=λ×W

I Länge der Warteschlange=Ankunftsrate×Durschnittliche Wartezeit

I Ankunftsrate= Länge der Warteschlange Durchschnittliche Wartezeit

I Wenn ein Datenstrom über einen längeren Zeitraum mit einer Frequenz> λDaten produziert, haben wir ein Problem!

10 [15]

Throttling / Debouncing

I Wenn wirLundWkennen, können wirλbestimmen. Wennλ überschritten wird, müssen wir etwas unternehmen.

I Idee: Throttling

stream.throttleFirst(lambda)

I Problem: Kurzzeitige Überschreigungen vonλsollen nicht zu Throttling führen.

11 [15]

Throttling / Debouncing

I Besser: Throttling erst bei längerer Überschreitung der Kapazität:

stream.window(count = L) .throttleFirst(lambda * L)

I Was ist wenn wir selbst die Daten Produzieren?

12 [15]

Back Pressure

I Wenn wir Kontrolle über die Produktion der Daten haben, ist es unsinnig, sie wegzuwerfen!

I Wenn der Konsument keine Daten mehr annehmen kann soll der Produzent aufhören sie zu Produzieren.

I Erste Idee: Wir können den produzierenden Thread blockieren

observable.observeOn(producerThread)

.subscribe(onNext = someExpensiveComputation)

I Reaktive Datenströme sollen aber gerade verhindern, dass Threads blockiert werden!

13 [15]

Back Pressure

I Bessere Idee: der Konsument muss mehr Kontrolle bekommen!

traitSubscription { defisUnsubscribed: Boolean defunsubscribe(): Unit defrequestMore(n: Int): Unit }

I Aufwändig zu Implementieren!

I Siehehttp://www.reactive-streams.org/

14 [15]

Zusammenfassung

I Die Konstruktoren in der Rx Bibliothek wenden vielMagiean um Gesetze einzuhalten

I Fehlerbehandlung durch Kombinatoren ist einfach zu implementieren

I Observables eigenen sich nur bedingt umBack Pressurezu implementieren, da Kontrollfluss unidirektional konzipiert.

I Dafür sind Aktoren sehr gut geeignet! (Coming Soon)

I Nächstes mal: (Rein-)Funktional-Reaktive Programmierung

15 [15]

Referenzen

ÄHNLICHE DOKUMENTE

I Wird durch Haskell Tysystem unterstützt (keine UI ohne IO) I Nützlich für andere UI mit Kontrollumkehr. I Beispiel: ein GUI für das Wörterratespiel

I Cold Observables fangen erst an Werte zu produzieren, wenn man ihnen zuhört.. Für jeden Observer

[r]

I Promises sind das Gegenstück zu Futures trait Promise {. def complete(result: Try[T]) def

I Werte vom Typ IO (Aktionen) können kombiniert werden wie alle anderen. I

I Aber: zentrales Konzept sind unendliche Listen (Ströme) mit nicht-strikte Auswertung. I Implementation mit Scala-Listen

[r]

I Nachdem onCompleted oder onError aufgerufen wurde wird onNext nicht mehr