Explaining some of the main characteristics of Reactive Functional Programming

Using some iOS context

Reactive Programming is usually used together with an MVVM architecture, but also can be used with others architectures. The main changes of the reactive programming paradigm are the change from an imperative paradigm to a declarative paradigm, less mutability and the “simplified” way of dealing with asynchronous code. Of course, this varies according to the perspective, because for those who are starting and have little experience with Reactive Programming undoubtedly this means that the code is more difficult to read, and it is harder to deal with the asynchronous events than using the traditional one methods.

Reactive Part

Streams

One fundamental concept of Reactive Programming is the concept of Streams. Streams are infinite values that arrive over time. One stream can represent, by example, the keys pressed in the keyboard over time, the text changed in text input box over time, click events triggered over time, messages in one Chat Room or other pure data changes.

And Reactive Functional Programming uses the Observer design pattern to observe these Streams. Besides that Reactive Functional Programming uses functional operators like Filter operator to manipulate, combine and control the flux of the Streams.

Simpler Asynchronous code

A click or tap event in iOS it is asynchronous code, because if you have an audio player playing music it does not stop working because of click events. When you implement certain delegates like TableView delegates or Text delegate that observe text changes that are an implementation that uses asynchronous code because the app does not stop because of these events.

Asynchronous code is central to app user experience to give a responsive response. Besides the delegates, you also use another mechanism that helps to deal with asynchronous communication like notification center or closures. To achieving asynchronicity you probably use these mechanisms together with Grand Central Dispatcher or NSOperationQueue or the abstracted asynchronous layer that a third party framework uses.

Using delegates requires you to adopt one pattern, another you’ll use for closures, yet another approach for subscribing to NotificationCenter, and so on. Since there is no universal language across all the asynchronous APIs, reading and understanding the code, and reasoning about its execution becomes difficult.

In the Reactive Programming, the different ways dealing with asynchronous events are abstracted for only one mechanism that deals asynchronously with Streams of data.

That simplifies the things. For example, the KVO (Key Value Observing) also uses the Observer Pattern but to achieve the same goal you need more code. We need to remove observers and create more boilerplate plate code.

And who was never confused with nested callbacks like callbacks inside callbacks in different classes associated with different layers?

This simplification of asynchronous code also makes it more testable.

“If you’ve ever used an asynchronous callback based API, you’ve probably dealt with handling the response data ad-hoc all across your codebase, and have most likely decided there was no way to unit test it all… But, let me tell you — there is a better way, and it’s called Rx!”

— Krunoslav Zaher, creator of RxSwift

Functional Part

Procedural Programming Paradigm and Object Oriented Programming Paradigm are imperative. Functional Programming Paradigm is Declarative and Less mutable.

There are programming languages that have structures for use in both Functional and not Functional code. Python is one example. Swift is another. Swift has functional operators like map, filter or reduce. If you want you still can implement a function with a for loop in an imperative way to get the same output that the map gives you.

In computer science, functional programming is a programming paradigm that treats computing as an assessment of mathematical functions and avoids changing states or data. It emphasises the application of functions, in contrast to imperative programming, which emphasises changes in the state of the program.

The principles of implementation are different according to this paradigm like says in theWikipédia:

“In functional code, the output value of a function depends only on the arguments that are passed to the function, so calling a function f twice with the same value for an argument x produces the same result f(x) each time; this is in contrast to procedures depending on a local or global state , which may produce different results at different times when called with the same arguments but a different program state. Eliminating side effects , i.e., changes in state that do not depend on the function inputs, can make it much easier to understand and predict the behavior of a program, which is one of the key motivations for the development of functional programming.”

Less Mutability

Less Mutable code create more coupling and more dependencies between different parts of the code.

There is never a situation where you solved a bug, but at the same time, you created another bug somewhere else? Where did you plug a hole and open another one at the same time?

If the system had built in a more isolated way this might not happen. The shift from the procedural paradigm to the object-oriented paradigm has created less mutability and less coupling. Object Programming Paradigm allows access control through access modifiers like the word private.

This change allowed encapsulation and the ability that one object interact with the another without knowing part of its inner functioning as if it were a black box. This change means that you cannot change specific parts of an object from outside and this causes less mutability. Despite this progress, some proponents of the functional paradigm still say that the object-oriented paradigm is still too much mutable.

The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle. — Joe Armstrong

In fact, Apple has encouraged protocol oriented paradigm in a WWDC conference and many programmers have changed more from an object-oriented paradigm to a more protocol oriented paradigm, protocol-oriented paradigm.

And this change in a specific way means less mutability. Swift does not support multiple inheritances, so you only can inherit of one class and that causes coupling because you end up inheriting things you do not need. Protocol-oriented programming allows code sharing in a more isolated way.

The protocols inherit from several protocols at the same time and this is called protocol composition. Each protocol has just what it needs and nothing more. This bigger division is a good practice for reducing the coupling and is stated in Interface segregation principle from SOLID.

In Swift with protocols, you can share methods with protocol extensions but you cannot share variables or constants content. This constraint that you cannot share variables and constants content between protocols can be good because this means that you cannot share state between types and this causes less mutability.

You still can force the code that implements the protocol to use the same type, but the instance, individual state or implementation (by example in the case of a more complex getter) is different. This way you share behavioural or form (methods), but you do not share state between types (variable and constants content).

Mutability is directly related to the coupling concept. For example, Singletons should be avoided if they are not needed because they create coupling and propagate state changes by the whole app. In a Unit Test set this means that the result of one unit test can affect the result the next unit test which goes against the own concept of Unit test that is to test each component in isolation.

Structs can not inherit but still can implement protocols. If the purpose of Structs is to be something less mutable why it would inherit from something with more mutability? This would defeat its purpose

In some cases, Struct types are preferred to classes because Structs are Values types and Classes are Reference Types. This means that if you are passing the same class instance to different methods they can all change their value and this causes greater mutability.

If you pass a struct to a method, by default you cannot change its value unless you explicitly use inout word. Also if you have a struct inside a method and you want to change his values, you should use the mutating keyword. If you want to understand more about the mutating keyword read here.

In Rx, streams are immutable, you can react to changes and through this way create objects that are open to extensions and closed to modifications. For manipulating the original streams, you use functional operators that generate new data instead of mutating the original data.

Some people may ask if this lower mutability does not result in lower code performance. Sometimes it’s the other way around. For example, in the case of the asynchronous code, the fact that programming code is mutable implies that the code needs locks to synchronize the code which by his turn affects the performance. Sometimes that locks are abstracted by some api, sometimes the programmer has to implement them.

Declarative Expressions

Functional Programming uses a declarative programming paradigm, which means programming is done with expressions or declarations instead of statements.

Here are other useful definitions of declaritive programming:

“Declarative programming is “the act of programming in languages that conform to the mental model of the developer rather than the operational model of the machine”.”

Or

“Declarative languages contrast with imperative languages which specify explicit manipulation of the computer’s internal state; or procedural languages which specify an explicit sequence of steps to follow.”

A declarative paradigm usually means less code and more code readability.

How example imagine that you arrive at Black Pearl Tavern, approach the employer and say …

An imperative approach (HOW): I see that table located under the Deep Treasure ‘sign is empty. My husband and I are going to walk there and sit down.

A declarative approach (WHAT): Table for two, please.

The imperative approach is concerned with HOW you are actually going to get a seat. You need to list the steps to be able to show HOW you are going to get a table. The declarative approach is more concerned with WHAT you want, a table for two.

In Swift, terms imagine the difference between an imperative map function implementation and the original functional map Swift function.

var originalArray = [1, 2, 3] func castToString(number: Any) -> String { return String(describing:number) } func map(originalArray : [Int], function: (Any) -> Any) -> [Any] { var result : [Any] = [] for number in originalArray { let transformedValue = function(number) result.append(transformedValue) } return result } let result = map(originalArray: originalArray, function:castToString)

Native Swift map:

let result = originalArray.map( { return String($0) })

Do you see the difference?

In the imperative paradigm, you need to know more inner workings of a system like the for loop mechanism, the append function, and keep the state of operation with an array. You have more computer logic that says that happens in each step and how elements integrated together in the whole.

Note: Some of the declarative examples that i used in this article are adapted of this excellent article. I have made a branch of his article and reused some things :) .

Last Words

This is a very simplistic way of explaining some concepts of Reactive Programming. However I hope it has been helpful in some way.

Thank you for reading! If you liked this article, please clap

👏🏻 so other people can read it too :)