Reactive programming by examples - Episode 1

Reactive World



Is almost one year that I have started to learn the reactive world, I began from its manifesto and i continued applying it in development of my Open Source projects and  in particular through the  languages JavaScript (and then RxJS), Java (and then RxJava) and Swift (and then RxSwift)

Why Reactive ?




Initially I approached reactive paradigm like a kid that open the gift box with a new and unknown toy, mostly fascinated by the technological wave that carried with it a lot of “new” stuff like: functional programming, stream/event oriented programming, backpressure, “callback hellsolver.


But as always “all that glitters ain't gold!” and our capacity to understand context of problems make the real difference and help us to choose the right approach, language, paradigm and frameworks to put on the table.

Better explain by examples


So I would share with you some problems in particular contexts that I have dealt with reactive programming hoping that, like for myself, the approach by example can be the most meaningful one


Assuming that you have acquired the basic concepts of Reactive Programming like Observer, Observable, Operators, Scheduler … let’s start

Context:  

TV Application that presents a slide deck

Problem:


Show Slides in automatic way but, whatever user event (related to navigation) occurs, the show should terminate

Example:

The example below is developed with Swift3 and works on Apple tvOS.


playPauseSlideShow =
Observable<Int>.interval(waitTimeInSeconds, scheduler: MainScheduler.instance)
           .map({ (index:Int) -> Int in

               guard let prevIndex = self._indexPathForPreferredFocusedView else {
                   return index + 1
               }
               return prevIndex.row + 1
               
           })
           .takeWhile({ (slide:Int) -> Bool in
               return slide < self.doc?.pagesCount
           })
           .takeUntil( pressesSubject.filter { (press:UIPress) -> Bool in
               press.type != UIPressType.playPause
           })
           .do( onCompleted:{
               self.playPauseSlideShow?.dispose()
               self.playPauseSlideShow = nil
           })
           .subscribe( onNext: { (slide:Int) in
               
               let i = IndexPath(row: slide, section: 0)
               
               self.showSlide(at: UInt(i.row))
 self._indexPathForPreferredFocusedView = i

               self.pagesView.selectItem(at: i, animated: false,
scrollPosition: UICollectionViewScrollPosition())
           })


The code above is part of my application SlidesOnTV and it is a “one statement” that solve the problem in reactive way.
Yes it is just one statement because the reactive frameworks typical use the “Builder Pattern” to compose the “stream processing chain”.


Let’s explain the code


Below, I will explain each link in the processing chain. Take note that such explanation don’t want cover the functional code but just the rules & responsibility of reactive operations.


Step 1
playPauseSlideShow =
Observable<Int>.interval(waitTimeInSeconds, scheduler: MainScheduler.instance)
This create an Observable that emit a tick ( ever tick is an integer incremented by one) every waitTimeSeconds on main thread


Step 2
.map({ (index:Int) -> Int in

  guard let prevIndex = self._indexPathForPreferredFocusedView else {
   return index + 1
  }
  return prevIndex.row + 1
               
})
This map operator transform each interval’s tick in a consistent slide number getting information from focused view


Step 3
.takeWhile({ (slide:Int) -> Bool in
  return slide < self.doc?.pagesCount
})
takeWhile operator takes emitted items whether the current slide number is still valid otherwise terminate


Step 4
.takeUntil( pressesSubject.filter { (press:UIPress) -> Bool in
    press.type != UIPressType.playPause
})
takeUntil operator allows to evaluate emitted items until a second Observable emits or terminates. This is a bit more complicated but in the same time very powerful and expressive. In this case the second observable “pressesSubject" emits every press on remote, filtered for all pressures not equal to "Play" or "Pause". (the code related to “pressesSubject” is out of scope)

This means that the slide show will continue until some action is performed by user through remote control

Step 5
.do( onCompleted:{
   self.playPauseSlideShow?.dispose()
   self.playPauseSlideShow = nil
})

do operator allows to perform an action during lifecycle of  items’ processing. In this case when the entire process is completed the observer will be cancelled


Step 6 (end)
.subscribe( onNext: { (slide:Int) in
               
   let i = IndexPath(row: slide, section: 0)
               
   self.showSlide(at: UInt(i.row))
   self._indexPathForPreferredFocusedView = i

   self.pagesView.selectItem(at: i,
                       animated: false,
                 scrollPosition: UICollectionViewScrollPosition())
})
Finally the subscribe method actives the reactive chain and is here we have to implement the business case for each given item. In this case the image related to the slide will be shown


Conclusion


That’s all for this first episode. This is an overview and for further details you have to go in deep into code but again, I hope that this gives an idea about this new paradigm and if it is suitable for your cases

* * *

The original article is on Google Docs

Comments

  1. Thanks for sharing this informative content , Great work
    Leanpitch provides online training in Advanced Scrum Master during this lockdown period everyone can use it wisely.
    Advanced Scrum Master Training Online

    ReplyDelete

Post a Comment

Popular posts from this blog

Google Web Toolkit Vs AngularJS

PlantText: The new "Online" UML Editor powered by PlantUML

PlantUML & Maven - Enrich your project's documentation