Is reactive programming worth it?


#1

I recently got interested in reactive programming with Kotlin . But , I was forced to rethink when I saw the following code for a calculator which can be normally written in much fewer lines .

Are all reactive codes so huge and difficult?

class ReactiveCalculator(a:Int, b:Int) { 
  internal val subjectAdd: Subject<Pair<Int,Int>> = 
    PublishSubject.create() 
  internal val subjectSub: Subject<Pair<Int,Int>> =
    PublishSubject.create() 
  internal val subjectMult: Subject<Pair<Int,Int>> =
    PublishSubject.create() 
  internal val subjectDiv: Subject<Pair<Int,Int>> =
    PublishSubject.create() 

  internal val subjectCalc:Subject<ReactiveCalculator> =
    PublishSubject.create() 

  internal var nums:Pair<Int,Int> = Pair(0,0) 

  init{ 
    nums = Pair(a,b) 

    subjectAdd.map({ it.first+it.second }).subscribe
    ({println("Add = $it")} ) 
    subjectSub.map({ it.first-it.second }).subscribe
    ({println("Substract = $it")} ) 
    subjectMult.map({ it.first*it.second }).subscribe
    ({println("Multiply = $it")} ) 
    subjectDiv.map({ it.first/(it.second*1.0) }).subscribe
    ({println("Divide = $it")} ) 

    subjectCalc.subscribe({ 
      with(it) { 
        calculateAddition() 
        calculateSubstraction() 
        calculateMultiplication() 
        calculateDivision() 
      } 
     }) 

     subjectCalc.onNext(this) 
    } 

    fun calculateAddition() { 
      subjectAdd.onNext(nums) 
    } 

    fun calculateSubstraction() { 
      subjectSub.onNext(nums) 
    } 

    fun calculateMultiplication() { 
      subjectMult.onNext(nums) 
    } 

    fun calculateDivision() { 
      subjectDiv.onNext(nums) 
    } 

    fun modifyNumbers (a:Int = nums.first, b: Int = nums.second) { 
      nums = Pair(a,b) 
      subjectCalc.onNext(this) 
   } 

   fun handleInput(inputLine:String?) { 
    if(!inputLine.equals("exit")) { 
        val pattern: Pattern = Pattern.compile
        ("([a|b])(?:\\s)?=(?:\\s)?(\\d*)"); 

        var a: Int? = null 
        var b: Int? = null 

        val matcher: Matcher = pattern.matcher(inputLine) 

        if (matcher.matches() && matcher.group(1) != null 
        &&  matcher.group(2) != null) { 
          if(matcher.group(1).toLowerCase().equals("a")){ 
             a = matcher.group(2).toInt() 
          } else if(matcher.group(1).toLowerCase().equals("b")){ 
             b = matcher.group(2).toInt() 
           } 
        } 

        when { 
          a != null && b != null -> modifyNumbers(a, b) 
          a != null -> modifyNumbers(a = a) 
          b != null -> modifyNumbers(b = b) 
          else -> println("Invalid Input") 
       } 
    } 
  } 
}

#2

The preferred style strongly depends on what exactly do you need to do and reactive programming is only one of those styles. It is very convenient for cases with unpredictable workflow (parallel user interactions, multi-client server, etc), but for straight forward application it is not always good (for command line application it almost always will be bad choice due to additional complexity and resource consumption).
One can’t say that one style is superior to another. Even despised procedure style is useful when one does direct number crunching and performance is the issue.

Luckily, Kotlin is not locked on one exact style like, say, Haskell or Fortran, so you can adjust your own style according to the task at hand.


#3

I think this is dead-on correct. I looked into reactive with Spring, and it had a nicer way of defining the initial endpoints. Once I got into it, though, and realized that I don’t have a reactive database, or any need to return active streams, it made way less sense.

To me, reactive is no different from NoSQL or asynchronous: it’s a tool to solve specific problems.