Skip to content

Commit 6cd6bb9

Browse files
committed
2 parents 5036e70 + 340ff24 commit 6cd6bb9

File tree

7 files changed

+567
-0
lines changed

7 files changed

+567
-0
lines changed

CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
eng.moldedbits.com

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
source 'https://rubygems.org'
2+
gem 'github-pages', group: :jekyll_plugins

Gemfile.lock

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
GEM
2+
remote: https://rubygems.org/
3+
specs:
4+
activesupport (4.2.8)
5+
i18n (~> 0.7)
6+
minitest (~> 5.1)
7+
thread_safe (~> 0.3, >= 0.3.4)
8+
tzinfo (~> 1.1)
9+
addressable (2.5.2)
10+
public_suffix (>= 2.0.2, < 4.0)
11+
coffee-script (2.4.1)
12+
coffee-script-source
13+
execjs
14+
coffee-script-source (1.12.2)
15+
colorator (1.1.0)
16+
ethon (0.10.1)
17+
ffi (>= 1.3.0)
18+
execjs (2.7.0)
19+
faraday (0.13.1)
20+
multipart-post (>= 1.2, < 3)
21+
ffi (1.9.18)
22+
forwardable-extended (2.6.0)
23+
gemoji (3.0.0)
24+
github-pages (157)
25+
activesupport (= 4.2.8)
26+
github-pages-health-check (= 1.3.5)
27+
jekyll (= 3.5.2)
28+
jekyll-avatar (= 0.4.2)
29+
jekyll-coffeescript (= 1.0.1)
30+
jekyll-default-layout (= 0.1.4)
31+
jekyll-feed (= 0.9.2)
32+
jekyll-gist (= 1.4.1)
33+
jekyll-github-metadata (= 2.9.1)
34+
jekyll-mentions (= 1.2.0)
35+
jekyll-optional-front-matter (= 0.2.0)
36+
jekyll-paginate (= 1.1.0)
37+
jekyll-readme-index (= 0.1.0)
38+
jekyll-redirect-from (= 0.12.1)
39+
jekyll-relative-links (= 0.4.1)
40+
jekyll-sass-converter (= 1.5.0)
41+
jekyll-seo-tag (= 2.3.0)
42+
jekyll-sitemap (= 1.0.0)
43+
jekyll-swiss (= 0.4.0)
44+
jekyll-theme-architect (= 0.1.0)
45+
jekyll-theme-cayman (= 0.1.0)
46+
jekyll-theme-dinky (= 0.1.0)
47+
jekyll-theme-hacker (= 0.1.0)
48+
jekyll-theme-leap-day (= 0.1.0)
49+
jekyll-theme-merlot (= 0.1.0)
50+
jekyll-theme-midnight (= 0.1.0)
51+
jekyll-theme-minimal (= 0.1.0)
52+
jekyll-theme-modernist (= 0.1.0)
53+
jekyll-theme-primer (= 0.5.2)
54+
jekyll-theme-slate (= 0.1.0)
55+
jekyll-theme-tactile (= 0.1.0)
56+
jekyll-theme-time-machine (= 0.1.0)
57+
jekyll-titles-from-headings (= 0.4.0)
58+
jemoji (= 0.8.0)
59+
kramdown (= 1.13.2)
60+
liquid (= 4.0.0)
61+
listen (= 3.0.6)
62+
mercenary (~> 0.3)
63+
minima (= 2.1.1)
64+
rouge (= 1.11.1)
65+
terminal-table (~> 1.4)
66+
github-pages-health-check (1.3.5)
67+
addressable (~> 2.3)
68+
net-dns (~> 0.8)
69+
octokit (~> 4.0)
70+
public_suffix (~> 2.0)
71+
typhoeus (~> 0.7)
72+
html-pipeline (2.7.0)
73+
activesupport (>= 2)
74+
nokogiri (>= 1.4)
75+
i18n (0.8.6)
76+
jekyll (3.5.2)
77+
addressable (~> 2.4)
78+
colorator (~> 1.0)
79+
jekyll-sass-converter (~> 1.0)
80+
jekyll-watch (~> 1.1)
81+
kramdown (~> 1.3)
82+
liquid (~> 4.0)
83+
mercenary (~> 0.3.3)
84+
pathutil (~> 0.9)
85+
rouge (~> 1.7)
86+
safe_yaml (~> 1.0)
87+
jekyll-avatar (0.4.2)
88+
jekyll (~> 3.0)
89+
jekyll-coffeescript (1.0.1)
90+
coffee-script (~> 2.2)
91+
jekyll-default-layout (0.1.4)
92+
jekyll (~> 3.0)
93+
jekyll-feed (0.9.2)
94+
jekyll (~> 3.3)
95+
jekyll-gist (1.4.1)
96+
octokit (~> 4.2)
97+
jekyll-github-metadata (2.9.1)
98+
jekyll (~> 3.1)
99+
octokit (~> 4.0, != 4.4.0)
100+
jekyll-mentions (1.2.0)
101+
activesupport (~> 4.0)
102+
html-pipeline (~> 2.3)
103+
jekyll (~> 3.0)
104+
jekyll-optional-front-matter (0.2.0)
105+
jekyll (~> 3.0)
106+
jekyll-paginate (1.1.0)
107+
jekyll-readme-index (0.1.0)
108+
jekyll (~> 3.0)
109+
jekyll-redirect-from (0.12.1)
110+
jekyll (~> 3.3)
111+
jekyll-relative-links (0.4.1)
112+
jekyll (~> 3.3)
113+
jekyll-sass-converter (1.5.0)
114+
sass (~> 3.4)
115+
jekyll-seo-tag (2.3.0)
116+
jekyll (~> 3.3)
117+
jekyll-sitemap (1.0.0)
118+
jekyll (~> 3.3)
119+
jekyll-swiss (0.4.0)
120+
jekyll-theme-architect (0.1.0)
121+
jekyll (~> 3.5)
122+
jekyll-seo-tag (~> 2.0)
123+
jekyll-theme-cayman (0.1.0)
124+
jekyll (~> 3.5)
125+
jekyll-seo-tag (~> 2.0)
126+
jekyll-theme-dinky (0.1.0)
127+
jekyll (~> 3.5)
128+
jekyll-seo-tag (~> 2.0)
129+
jekyll-theme-hacker (0.1.0)
130+
jekyll (~> 3.5)
131+
jekyll-seo-tag (~> 2.0)
132+
jekyll-theme-leap-day (0.1.0)
133+
jekyll (~> 3.5)
134+
jekyll-seo-tag (~> 2.0)
135+
jekyll-theme-merlot (0.1.0)
136+
jekyll (~> 3.5)
137+
jekyll-seo-tag (~> 2.0)
138+
jekyll-theme-midnight (0.1.0)
139+
jekyll (~> 3.5)
140+
jekyll-seo-tag (~> 2.0)
141+
jekyll-theme-minimal (0.1.0)
142+
jekyll (~> 3.5)
143+
jekyll-seo-tag (~> 2.0)
144+
jekyll-theme-modernist (0.1.0)
145+
jekyll (~> 3.5)
146+
jekyll-seo-tag (~> 2.0)
147+
jekyll-theme-primer (0.5.2)
148+
jekyll (~> 3.5)
149+
jekyll-github-metadata (~> 2.9)
150+
jekyll-seo-tag (~> 2.2)
151+
jekyll-theme-slate (0.1.0)
152+
jekyll (~> 3.5)
153+
jekyll-seo-tag (~> 2.0)
154+
jekyll-theme-tactile (0.1.0)
155+
jekyll (~> 3.5)
156+
jekyll-seo-tag (~> 2.0)
157+
jekyll-theme-time-machine (0.1.0)
158+
jekyll (~> 3.5)
159+
jekyll-seo-tag (~> 2.0)
160+
jekyll-titles-from-headings (0.4.0)
161+
jekyll (~> 3.3)
162+
jekyll-watch (1.5.0)
163+
listen (~> 3.0, < 3.1)
164+
jemoji (0.8.0)
165+
activesupport (~> 4.0)
166+
gemoji (~> 3.0)
167+
html-pipeline (~> 2.2)
168+
jekyll (>= 3.0)
169+
kramdown (1.13.2)
170+
liquid (4.0.0)
171+
listen (3.0.6)
172+
rb-fsevent (>= 0.9.3)
173+
rb-inotify (>= 0.9.7)
174+
mercenary (0.3.6)
175+
mini_portile2 (2.2.0)
176+
minima (2.1.1)
177+
jekyll (~> 3.3)
178+
minitest (5.10.3)
179+
multipart-post (2.0.0)
180+
net-dns (0.8.0)
181+
nokogiri (1.8.0)
182+
mini_portile2 (~> 2.2.0)
183+
octokit (4.7.0)
184+
sawyer (~> 0.8.0, >= 0.5.3)
185+
pathutil (0.14.0)
186+
forwardable-extended (~> 2.6)
187+
public_suffix (2.0.5)
188+
rb-fsevent (0.10.2)
189+
rb-inotify (0.9.10)
190+
ffi (>= 0.5.0, < 2)
191+
rouge (1.11.1)
192+
safe_yaml (1.0.4)
193+
sass (3.5.1)
194+
sass-listen (~> 4.0.0)
195+
sass-listen (4.0.0)
196+
rb-fsevent (~> 0.9, >= 0.9.4)
197+
rb-inotify (~> 0.9, >= 0.9.7)
198+
sawyer (0.8.1)
199+
addressable (>= 2.3.5, < 2.6)
200+
faraday (~> 0.8, < 1.0)
201+
terminal-table (1.8.0)
202+
unicode-display_width (~> 1.1, >= 1.1.1)
203+
thread_safe (0.3.6)
204+
typhoeus (0.8.0)
205+
ethon (>= 0.8.0)
206+
tzinfo (1.2.3)
207+
thread_safe (~> 0.1)
208+
unicode-display_width (1.3.0)
209+
210+
PLATFORMS
211+
ruby
212+
213+
DEPENDENCIES
214+
github-pages
215+
216+
BUNDLED WITH
217+
1.14.6

_posts/2017-08-28-the-rx-way.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
layout: post
3+
title: "The Rx way of doing things"
4+
date: 2017-08-28 8:00:00
5+
author: abhishek
6+
categories: Reactive-Programming
7+
---
8+
We have been trying to include more and more reactive approach in apps that we build at [moldedbits](http:///www.moldedbits.com). Now that I am little more comfortable with reactive way of doing things I decided to write a blog on reactive vs imperative way of solving a problem. I will try to explain how reactive programming makes developer's life easy by doing more in less code.
9+
10+
### Problem Statement
11+
Consider following problem statement
12+
13+
1. You have to make an API call which returns a map of ObjectId to Object
14+
2. You need to convert this map to a list of objects which contain object-id
15+
3. Now you need to filter some objects from this list
16+
4. For each of these filtered objects you need to do another API call.
17+
5. Above API calls should be done sequentially and each subsequent API call should be done after a delay of 100 ms.
18+
19+
This is a real life scenario. I had written implementation for this in one of our Android app. We use [Retrofit](http://square.github.io/retrofit/) for networking, [RxJava-2](https://github.com/ReactiveX/RxJava) for reactive programming and [Retrolambda](https://github.com/orfjackal/retrolambda) for Java8 like syntax and boilerplate reduction.
20+
21+
Now think about how you will implement this in imperative world.
22+
23+
### The Imperative Way
24+
25+
Let me help you. In an imperative world
26+
27+
1. You will probably do an API call with help of Retrofit(if you are using retrofit) or in a AsyncTask.
28+
2. When this API returns you will iterate the map and convert it in a list on main thread (off-course you can do it in a different thread but I want to keep things simple).
29+
3. After which you would do a second iteration for filtering out desired objects.
30+
4. Now things get interesting as you need to perform API calls for each of these remaining objects in list. You probably will need to write a Service or AsyncTask which now performs synchronous API calls after a sleep of 100ms.
31+
32+
Now that is lot of work and I am not even considering edge cases and error handling for sake of simplicity. Think of the case when API returns a large list of objects and you can't afford to process that on main thread.
33+
34+
Well, Rx does all this heavy lifting for you. Lets see how.
35+
36+
### The Rx Way
37+
38+
Reactive programming is totally a different approach towards writing code. Everything in reactive world is considered a stream. These streams are immutable and there are plethora of operators available which operate on these streams. Real power of reactive programming lies in these tried and tested operators.
39+
40+
Rx makes task of switching between the thread as easy as having an apple pie. Our above said problem statement can be accomplished by mere 10 lines of code with RxJava. Here is a sample from production code
41+
42+
{% highlight java %}
43+
APIProvider.getInstance().getService().getMyObjects(userName)
44+
.subscribeOn(Schedules.io())
45+
.map(MyObject::toList)
46+
.flatMap(rx.Observable::from)
47+
.filter(myObject->myObject.getName().equals(Constants.SOME_NAME))
48+
// adding a 10ms delay in subsequent api calls
49+
.flatMap(myObject -> Observable.timer(100, TimeUnit.MILLISECONDS).map(y -> myObject))
50+
.doOnNext(rule -> {
51+
// deleting my object one by one
52+
APIProvider.getInstance()
53+
.getService().deleteMyObject(userName, rule.getId())
54+
.subscribe();
55+
}).subscribe();
56+
{% endhighlight %}
57+
58+
lets understand this code line by line
59+
60+
```
61+
APIProvider.getInstance().getService().getMyObjects(userName)
62+
```
63+
Its `Retrofit` way of doing an API call. This API returns a map of `MyObjectId` to `MyObject`. An example JSON looks like this
64+
{% highlight json %}
65+
{
66+
"1": {
67+
"name": "object1"
68+
},
69+
"2": {
70+
"name": "object2"
71+
}
72+
}
73+
{% endhighlight %}
74+
75+
```
76+
.subscribeOn(Schedules.io())
77+
```
78+
`subscribeOn` is an Rx operator which directs RxJava to start processing on scheduler thread (a background thread). Just this line lets you switch your processing to a background thread. How cool is that!
79+
80+
```
81+
.map(MyObject::toList)
82+
```
83+
`Map` is transformation operator which allows us to convert things. Here we are converting `Map` to `List`. `toList` is a static method written in `MyObject` class. This method converts a `Map<ObjectId, MyObject>` to `List<MyObject>`. List version has object id's in object itself. `MyObject::toList` is Java 8 way of calling this method, Its named as [Method Reference](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html). Transformed data structure now looks like this
84+
{% highlight json %}
85+
[
86+
{
87+
"id": "1",
88+
"name": "object1"
89+
},
90+
{
91+
"id": "2",
92+
"name": "object2"
93+
}
94+
]
95+
{% endhighlight %}
96+
97+
```
98+
.flatMap(rx.Observable::from)
99+
```
100+
101+
This statement allows us to receive each `MyObject` as separate event on observable stream. Before this we were having whole List or Map as single event on observable stream. To perform filtering and API calls on each of these separately we need to have them as independent events on stream.
102+
103+
```
104+
.filter(myObject->myObject.getName().equals(Constants.SOME_NAME))
105+
```
106+
107+
This is pretty obvious. `filter` operator allows us to filter out events which do not match filtering criteria. Any object whose name does not match with `Constants.SOME_NAME` is not allowed to propagate further in stream.
108+
109+
```
110+
.flatMap(myObject -> Observable.timer(100, TimeUnit.MILLISECONDS).map(y -> myObject))
111+
```
112+
113+
This interesting piece of code is allowing us to add a delay of 100 milliseconds between subsequent results. Inside `flatmap` we are creating another stream using [`Timer`](http://reactivex.io/documentation/operators/timer.html) observable. As per documentation `Timer` returns an Observable that emits a single number zero after a delay period you specify. Since, we do not want to loose our `MyObjects` we need to map this zero back to `MyObject`. Outer `flatmap` is making sure that event are received on current stream.
114+
115+
```
116+
doOnNext(myObject -> {
117+
// deleting my object one by one
118+
APIProvider.getInstance()
119+
.getService().deleteMyObject(userName, myObject.getId())
120+
.subscribe();
121+
})
122+
```
123+
124+
Finally, since we have nice stream of `MyObjects` including a delay of 100ms we can perform our API calls. That is what is happening inside `doOnNext` operator. `doOnNext` operator allows us add a hook on each event in a stream.
125+
126+
```
127+
.subscribe()
128+
```
129+
Fire! this is what this operator does. This the simplest version of [`Subscribe`](http://reactivex.io/documentation/operators/subscribe.html) operator that we have used here. You can read more about it in docs.
130+
131+
If you have noticed, all this work is happening in a background thread without us having to worry about anything. In my case I had no need to process API results in Android main thread but in case if you do you can just use [`ObserveOn`](http://reactivex.io/documentation/operators/observeon.html) operator to switch threads any time.
132+
133+
So what do you think about it? Let me know in comments.
134+
135+
Happy Coding !!

0 commit comments

Comments
 (0)