Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Reactive Programming
in the wild
Omer Iqbal
Yang Bo
Functional Reactive Programming
Why?
Listeners/Delegates/Observers/Callbacks!
DeathStarDelegate
DeathStar
didBlowUp:
[self fireStormTroopers]
Problems
1. Unpredictable Order
2. Missing Events
3. Cleaning up listeners
4. Accidental Recursion
5. Messy State
6. Multi...
"our intellectual powers are rather geared to master
static relationsand that our powers to
visualize processes evolving i...
Model events as composable values!
Signals/Observables
next next next
completed
next next
error
Creating a Signal
- (RACSignal *)login {
return [RACSignal createSignal:^(id<RACSubscriber> subscriber){
[LoginManager log...
Using a signal
[[self login] subscribeNext:^(id response){
} error:^(NSError *error){
} completed:^(){
}];
[vader login:^(id response, NSError *error) {
if (error) {
return;
}
[vader blowUpSomePlanets:^(id response, NSError *erro...
Composition!
[[[[vader login] flattenMap:^RACStream
*(id value) {
return [vader blowUpSomePlanets];
}] flattenMap:^RACStre...
flattenMap
merge
combineLatest
Network Requests
RACSignal *buddies = [self requestBuddyList];
RACSignal *chats = [self requestChatList];
[RACSignal combi...
Composable UI Flows
GCActionViewController *vc = [GCActionViewController new];
RACSignal *camera = [[vc addButtonTitle:@"T...
iOS
ReactiveCocoa vs RxSwift
● If you’re on objective C, you don’t have a choice -> ReactiveCocoa 2.0
● RxSwift follows standa...
Problems
Hot Signals
● Easy to miss events
● Beware of the phantom subscribe blocks
● Always unsubscribe when not needed!
[didUpdateUsers takeUntil:[self rac_willDeallocSignal]]
takeUntil is your best friend
Cold Signals
● Only perform work when subscribed to e.g Network Request, UI Flow
● Beware of multiple subscribers!
● Use R...
Android
Yang Bo
“modern apps are event-driven”
System Broadcast
○ Internet connectivity
○ Doze mode
○ Download progress
Lifecycle
App enters:
○ Foreground
○ Background
C...
EventBus
Hard truths
○ Throttling control
○ Grouping events
○ Higher-order events
○ Error handling and retry
○ Cache and replay
○ ....
R X J A V A
ANDROID
RxJava to the rescue!
Rx-based Framework Design
Push PullMix
Choices of protocol
Store Node
Latest snapshot of data
Push model
Store Node
Incremental update
Push model
Store Node
Invalidity
Pull model
Request data
Characteristics of “pull” model
✓ Throttling-friendly
✓ Controlled memory footprint
✘ Performance cost of requery
Building blocks
○ Network manager
public Observable<Response> send(Request request) {
...
}
○ Database manager
public <T> ...
Framework architecture
UI
Data Stream
Layer
Local Store
ACTION UPDATE
NOTIFY
FETCH
PUSH
Traditional approach
ContactUIData
Name: “44”
Icon: “xxxx”
...
Database
User #1
User #2
User #3
User #4
Converter
Task (on...
Data Stream Layer
ContactUIData
Name: “44”
Icon: “xxxx”
...
Database
User #1
User #2
User #3
User #4
Data Stream
Layer
Data Stream Layer
Database
User #1
User #2
User #3
User #4
Data Stream
Layer
Trigger
Filter + Throttle
Provider
Subscriber...
Data Stream Layer
Database
User #1
User #2
User #3
User #4
Data Stream
Layer
Trigger
Filter + Throttle
Provider
Subscriber...
#1. Setup once, always up-to-date
#2. Decouple UI from update logic
#3. Unidirectional data flow
Challenges
○ Backpressure
Cold observable
Observable.range(1, 1000000)
.observeOn(Schedulers.io())
.doOnNext(new Action1<Object>() {
@Override
publi...
Hot observable
BehaviorSubject.create(new Object())
.observeOn(Schedulers.io())
.doOnNext(new Action1<Object>() {
@Overrid...
BehaviorSubject.create(new Object())
.onBackpressureDrop()
.observeOn(Schedulers.io())
.doOnNext(new Action1<Object>() {
@...
Challenges
○ Custom operator?
map concat merge flatMap concatMap switchMap combineLatest from
range create just first firs...
Challenges
○ Memory leaks
Remember to unsubscribe, always
Subscription subscription = Observable.range(1, 1000000)
.subscr...
Summary
○ Intro to Reactive Programming
○ Practical application in mobile development
○ Pitfalls & Challenges
Thanks
GTS Episode 1: Reactive programming in the wild
GTS Episode 1: Reactive programming in the wild
GTS Episode 1: Reactive programming in the wild
Upcoming SlideShare
Loading in …5
×

GTS Episode 1: Reactive programming in the wild

317 views

Published on

You've probably heard of Reactive Programming. It’s a fashionable, new paradigm for modelling asynchronous events in a composable, declarative way. Our mobile developers decided to be trendy, and adopted the world of Observables (aka Signals, Streams) in production. It definitely helped them wade through complex async flows. As code became declarative, it became easier to reason about expected behaviour. Bugs began to flee. Our developers began finding spare time to gym and watch Game of Thrones. Life was good. Or was it?


As with any technology in production, they discovered a host of interesting issues that the tutorials and toy projects never mentioned...


This talk covers the fundamentals of Reactive Programming on iOS and Android. It also includes a much needed debate on issues with the paradigm in production.

Published in: Technology
  • You can ask here for a help. They helped me a lot an i`m highly satisfied with quality of work done. I can promise you 100% un-plagiarized text and good experts there. Use with pleasure! ⇒ www.HelpWriting.net ⇐
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

GTS Episode 1: Reactive programming in the wild

  1. 1. Reactive Programming in the wild Omer Iqbal Yang Bo
  2. 2. Functional Reactive Programming
  3. 3. Why?
  4. 4. Listeners/Delegates/Observers/Callbacks!
  5. 5. DeathStarDelegate DeathStar didBlowUp: [self fireStormTroopers]
  6. 6. Problems 1. Unpredictable Order 2. Missing Events 3. Cleaning up listeners 4. Accidental Recursion 5. Messy State 6. Multithreading is a PAIN
  7. 7. "our intellectual powers are rather geared to master static relationsand that our powers to visualize processes evolving in time are relatively poorly developed"
  8. 8. Model events as composable values!
  9. 9. Signals/Observables next next next completed next next error
  10. 10. Creating a Signal - (RACSignal *)login { return [RACSignal createSignal:^(id<RACSubscriber> subscriber){ [LoginManager loginWithSuccess:^(data){ [subscriber sendNext:data]; [subscriber sendCompleted]; } error:^(NSError *error){ [subscriber sendError:error]; }]; }]; }
  11. 11. Using a signal [[self login] subscribeNext:^(id response){ } error:^(NSError *error){ } completed:^(){ }];
  12. 12. [vader login:^(id response, NSError *error) { if (error) { return; } [vader blowUpSomePlanets:^(id response, NSError *error) { if (error) { return; } [vader haveBrekkie:^(id response, NSError *error) { if (error) { return; } [vader playWithKids:^(id response, NSError *error) { if (error) { return; } }]; }]; }]; }];
  13. 13. Composition! [[[[vader login] flattenMap:^RACStream *(id value) { return [vader blowUpSomePlanets]; }] flattenMap:^RACStream *(id value) { return [vader haveBrekkie]; }] flattenMap:^RACStream *(id value) { return [vader playWithKids]; }];
  14. 14. flattenMap
  15. 15. merge
  16. 16. combineLatest
  17. 17. Network Requests RACSignal *buddies = [self requestBuddyList]; RACSignal *chats = [self requestChatList]; [RACSignal combineLatest:@[buddies, chats] reduce:^id (NSArray<GxxUser *> *users, NSArray <GxxChat *> *chats){ // .. process here }];
  18. 18. Composable UI Flows GCActionViewController *vc = [GCActionViewController new]; RACSignal *camera = [[vc addButtonTitle:@"Take Photo"] flattenMap:^(){ return [self presentCameraAndTakeImage]; }]; RACSignal *picker = [[vc addButtonTitle:"Choose Existing"] flattenMap:^(){ return [self presentImageSelect]; }]; RACSignal *cancel = [[vc didTapCancel] flattenMap:^(){ return [RACSignal error:[GCErrorUtility userCancelled]]; }]; return [RACSignal merge:@[camera, picker, cancel]];
  19. 19. iOS
  20. 20. ReactiveCocoa vs RxSwift ● If you’re on objective C, you don’t have a choice -> ReactiveCocoa 2.0 ● RxSwift follows standard Rx conventions borrowed from RxJS, RxJava. ● ReactiveCocoa (Swift) has an awesome API with sexy operators which breaks over Swift versions ● ReactiveCocoa (Swift) distinguishes between hot and cold signals
  21. 21. Problems
  22. 22. Hot Signals ● Easy to miss events ● Beware of the phantom subscribe blocks ● Always unsubscribe when not needed!
  23. 23. [didUpdateUsers takeUntil:[self rac_willDeallocSignal]] takeUntil is your best friend
  24. 24. Cold Signals ● Only perform work when subscribed to e.g Network Request, UI Flow ● Beware of multiple subscribers! ● Use RACMulticast or convert to Hot Signal if multiple subscribers are needed
  25. 25. Android Yang Bo
  26. 26. “modern apps are event-driven”
  27. 27. System Broadcast ○ Internet connectivity ○ Doze mode ○ Download progress Lifecycle App enters: ○ Foreground ○ Background Custom Events ○ Connection established ○ User logged in ○ Data updated ○ ...
  28. 28. EventBus
  29. 29. Hard truths ○ Throttling control ○ Grouping events ○ Higher-order events ○ Error handling and retry ○ Cache and replay ○ ...
  30. 30. R X J A V A ANDROID RxJava to the rescue!
  31. 31. Rx-based Framework Design
  32. 32. Push PullMix Choices of protocol
  33. 33. Store Node Latest snapshot of data Push model
  34. 34. Store Node Incremental update Push model
  35. 35. Store Node Invalidity Pull model Request data
  36. 36. Characteristics of “pull” model ✓ Throttling-friendly ✓ Controlled memory footprint ✘ Performance cost of requery
  37. 37. Building blocks ○ Network manager public Observable<Response> send(Request request) { ... } ○ Database manager public <T> Observable<T> exec(Query<T> query) { ... }
  38. 38. Framework architecture UI Data Stream Layer Local Store ACTION UPDATE NOTIFY FETCH PUSH
  39. 39. Traditional approach ContactUIData Name: “44” Icon: “xxxx” ... Database User #1 User #2 User #3 User #4 Converter Task (one-shot)
  40. 40. Data Stream Layer ContactUIData Name: “44” Icon: “xxxx” ... Database User #1 User #2 User #3 User #4 Data Stream Layer
  41. 41. Data Stream Layer Database User #1 User #2 User #3 User #4 Data Stream Layer Trigger Filter + Throttle Provider Subscriber NOTIFY FETCH
  42. 42. Data Stream Layer Database User #1 User #2 User #3 User #4 Data Stream Layer Trigger Filter + Throttle Provider Subscriber PUSH
  43. 43. #1. Setup once, always up-to-date
  44. 44. #2. Decouple UI from update logic
  45. 45. #3. Unidirectional data flow
  46. 46. Challenges ○ Backpressure
  47. 47. Cold observable Observable.range(1, 1000000) .observeOn(Schedulers.io()) .doOnNext(new Action1<Object>() { @Override public void call(Object o) { // slow ops } }) .subscribe();
  48. 48. Hot observable BehaviorSubject.create(new Object()) .observeOn(Schedulers.io()) .doOnNext(new Action1<Object>() { @Override public void call(Object o) { // slow ops } }) .subscribe(); No backpressure support!
  49. 49. BehaviorSubject.create(new Object()) .onBackpressureDrop() .observeOn(Schedulers.io()) .doOnNext(new Action1<Object>() { @Override public void call(Object o) { // slow ops } }) .subscribe();
  50. 50. Challenges ○ Custom operator? map concat merge flatMap concatMap switchMap combineLatest from range create just first firstOrDefault last startWith zip join switchOnNext amb retry repeat debounce sample defaultIfEmpty skipUntil skipWhen switchCase takeUntil contains exists isEmpty distinctUntilChanged share publish refCount replay filter skip timeout max min reduce count collect toList toMap scan buffer window cast cache timestamp observeOn subscribeOn delay timer interval doOnNext doOnComplete doOnError onErrorReturn ... DON’T BOTHER
  51. 51. Challenges ○ Memory leaks Remember to unsubscribe, always Subscription subscription = Observable.range(1, 1000000) .subscribe(); subscription.unsubscribe();
  52. 52. Summary ○ Intro to Reactive Programming ○ Practical application in mobile development ○ Pitfalls & Challenges
  53. 53. Thanks

×