1 00:00:00,000 --> 00:00:00,060 2 00:00:00,060 --> 00:00:00,810 JORDAN JOZWIAK: Hi, everyone. 3 00:00:00,810 --> 00:00:02,760 Thanks for coming and welcome to this talk 4 00:00:02,760 --> 00:00:05,810 on reactive programming and RxJava. 5 00:00:05,810 --> 00:00:07,020 I'm Jordan. 6 00:00:07,020 --> 00:00:10,290 I'm part of the Harvard class of 2014. 7 00:00:10,290 --> 00:00:13,710 I was a social studies concentrator with a CS secondary, 8 00:00:13,710 --> 00:00:17,010 and I was a CS50 TF for three years, but probably 9 00:00:17,010 --> 00:00:19,500 before most if you took the class. 10 00:00:19,500 --> 00:00:24,120 And most importantly, I lived in the best house, Mather House. 11 00:00:24,120 --> 00:00:27,030 Just want to get that out there. 12 00:00:27,030 --> 00:00:30,660 Post-college, I worked at DoubleDutch and ERO as an Android app developer. 13 00:00:30,660 --> 00:00:34,650 And now, I'm at Google working on the API that help control car 14 00:00:34,650 --> 00:00:38,340 functionality in Android Auto. 15 00:00:38,340 --> 00:00:40,110 OK, so let's dive right in. 16 00:00:40,110 --> 00:00:43,380 Reactive programming is a programming paradigm 17 00:00:43,380 --> 00:00:47,580 that allows us to manipulate streams of data with functions. 18 00:00:47,580 --> 00:00:50,070 And everything works asynchronously, meaning 19 00:00:50,070 --> 00:00:52,980 that we don't have to wait for the result of operations. 20 00:00:52,980 --> 00:00:57,150 But we'll talk more about this as we go. 21 00:00:57,150 --> 00:00:59,730 So, what is reactive programming really? 22 00:00:59,730 --> 00:01:01,830 Well, it's an approach problem solving, and it 23 00:01:01,830 --> 00:01:06,030 focuses on three aspects, which were kind of conveyed in that sentence 24 00:01:06,030 --> 00:01:07,230 before. 25 00:01:07,230 --> 00:01:08,620 One, data streams. 26 00:01:08,620 --> 00:01:12,780 So this is a flow of data objects that start somewhere and are 27 00:01:12,780 --> 00:01:15,180 consumed elsewhere. 28 00:01:15,180 --> 00:01:18,990 Functional programming, and you're used to using functions 29 00:01:18,990 --> 00:01:23,430 in your normal style of imperative programming. 30 00:01:23,430 --> 00:01:25,080 We'll get into that term later. 31 00:01:25,080 --> 00:01:27,330 And so we use functions throughout programming, 32 00:01:27,330 --> 00:01:31,900 but functional programming means using functions in a certain way. 33 00:01:31,900 --> 00:01:34,590 And in this case, we're talking about applying functions 34 00:01:34,590 --> 00:01:37,360 to manipulate a stream of data. 35 00:01:37,360 --> 00:01:41,630 So for instance, we might combine multiple streams of data together. 36 00:01:41,630 --> 00:01:43,920 Maybe we'd filter out some results, or we 37 00:01:43,920 --> 00:01:49,380 might manipulate the data in some way to transform it to something else. 38 00:01:49,380 --> 00:01:54,270 Functional programming is kind of a central focus topic for CS51, 39 00:01:54,270 --> 00:02:00,270 so for those of you who are going to take that or will take it, 40 00:02:00,270 --> 00:02:03,990 this will maybe give you a little bit of a primer for it. 41 00:02:03,990 --> 00:02:06,720 And the last part is asynchronous observers. 42 00:02:06,720 --> 00:02:13,240 So unlike synchronous programming, where one line of execute waits until-- 43 00:02:13,240 --> 00:02:15,570 well, we wait for one line to finish executing 44 00:02:15,570 --> 00:02:17,670 before the next line executes. 45 00:02:17,670 --> 00:02:21,180 With asynchronous observers, it means that our code has-- 46 00:02:21,180 --> 00:02:23,930 47 00:02:23,930 --> 00:02:27,790 some parts of our code will execute at different times than other parts. 48 00:02:27,790 --> 00:02:30,240 So if you're familiar with callbacks, maybe you 49 00:02:30,240 --> 00:02:32,310 set an onClick listener for something and it 50 00:02:32,310 --> 00:02:34,200 calls back later, that's asynchronous. 51 00:02:34,200 --> 00:02:39,960 And with asynchronous observers, then we also 52 00:02:39,960 --> 00:02:44,860 have these callbacks that happen later. 53 00:02:44,860 --> 00:02:47,260 And we'll talk about all this more in a little bit. 54 00:02:47,260 --> 00:02:50,340 So what are the actual applications of this? 55 00:02:50,340 --> 00:02:53,250 Well, for instance, maybe we would want to retrieve data 56 00:02:53,250 --> 00:02:58,830 from a database, filter out some results based on the user setting. 57 00:02:58,830 --> 00:03:02,400 So one reason this would be a good example of reactive programming 58 00:03:02,400 --> 00:03:05,440 is because we have those few elements here. 59 00:03:05,440 --> 00:03:08,970 So for instance, we have a stream of data or some data coming out 60 00:03:08,970 --> 00:03:11,220 of a database. 61 00:03:11,220 --> 00:03:13,470 And because it's from a database, this is an operation 62 00:03:13,470 --> 00:03:15,011 that might take a little bit of time. 63 00:03:15,011 --> 00:03:17,550 Maybe we're making a request over a network. 64 00:03:17,550 --> 00:03:22,320 Or even just sometimes, database queries can require some time 65 00:03:22,320 --> 00:03:25,380 with joining and looking up in multiple tables. 66 00:03:25,380 --> 00:03:27,180 So because it takes a little bit of time, 67 00:03:27,180 --> 00:03:30,060 we would want to avoid blocking other operations. 68 00:03:30,060 --> 00:03:33,960 And it would be a good case for handling this asynchronously. 69 00:03:33,960 --> 00:03:37,140 We would also, in this case, want to manipulate 70 00:03:37,140 --> 00:03:39,690 our data by filtering out some results. 71 00:03:39,690 --> 00:03:41,700 So we might have some sort of filter function 72 00:03:41,700 --> 00:03:45,465 that says we will exclude certain values. 73 00:03:45,465 --> 00:03:47,970 74 00:03:47,970 --> 00:03:52,140 Some other examples might include rendering a UI that combines data 75 00:03:52,140 --> 00:03:57,090 from multiple data sources, creating a real-time model of stock prices, 76 00:03:57,090 --> 00:04:00,240 showing auto-complete search results for a user, 77 00:04:00,240 --> 00:04:04,630 and maybe logging data from a temperature, wind, or pressure sensor. 78 00:04:04,630 --> 00:04:07,230 In each of these cases, there's some sort of data 79 00:04:07,230 --> 00:04:11,460 and an opportunity for functional manipulation of that data stream. 80 00:04:11,460 --> 00:04:15,400 And they might benefit from being handled asynchronously. 81 00:04:15,400 --> 00:04:18,720 So they could probably be handled without reactive programming, as well, 82 00:04:18,720 --> 00:04:24,510 but reactive programming makes these sort of problems easier to deal with. 83 00:04:24,510 --> 00:04:29,070 And are there any questions on why these examples would 84 00:04:29,070 --> 00:04:31,500 kind of fall in the bucket that I'm talking 85 00:04:31,500 --> 00:04:34,000 about in terms of these three areas? 86 00:04:34,000 --> 00:04:37,560 That's OK, there were plenty of time for questions later. 87 00:04:37,560 --> 00:04:38,450 OK, we'll move on. 88 00:04:38,450 --> 00:04:41,530 89 00:04:41,530 --> 00:04:44,370 The reactive programming isn't just theoretical. 90 00:04:44,370 --> 00:04:45,810 People actually use it. 91 00:04:45,810 --> 00:04:49,009 It's great for mobile development, because there are many network 92 00:04:49,009 --> 00:04:50,550 requests that shouldn't block the UI. 93 00:04:50,550 --> 00:04:53,520 So we're frequently getting data from some server, 94 00:04:53,520 --> 00:04:56,240 manipulating it, and showing it in the UI. 95 00:04:56,240 --> 00:04:58,740 I know that Google uses it, in some cases, 96 00:04:58,740 --> 00:05:01,940 for data requests, database requests. 97 00:05:01,940 --> 00:05:06,050 And the reactive website, which we'll get into this more in a little bit, 98 00:05:06,050 --> 00:05:09,290 also lists a number of companies that use it. 99 00:05:09,290 --> 00:05:12,140 I know Netflix was an early adopter and has written some blog 100 00:05:12,140 --> 00:05:13,890 posts on how it's helped them. 101 00:05:13,890 --> 00:05:16,432 102 00:05:16,432 --> 00:05:18,890 And reactive programming, when I've talked about it so far, 103 00:05:18,890 --> 00:05:20,510 is kind of this theoretical idea. 104 00:05:20,510 --> 00:05:23,060 We have these principles and reasons that we 105 00:05:23,060 --> 00:05:28,250 might want to approach programming in a certain way. 106 00:05:28,250 --> 00:05:32,030 But many languages don't have these concepts built in. 107 00:05:32,030 --> 00:05:36,320 So maybe like Java, C, it doesn't necessarily 108 00:05:36,320 --> 00:05:43,757 cater to this paradigm and way of solving problems in its own nature. 109 00:05:43,757 --> 00:05:45,590 So we would need some sort of library that's 110 00:05:45,590 --> 00:05:48,970 an extension on the language itself. 111 00:05:48,970 --> 00:05:52,280 And anyone could implement a reactive extension library, 112 00:05:52,280 --> 00:05:57,560 but the most popular one is reactivex.io specification, 113 00:05:57,560 --> 00:06:01,610 and that's the one we'll be talking about today. 114 00:06:01,610 --> 00:06:04,530 And there are implementations for a number of languages, 115 00:06:04,530 --> 00:06:08,600 including Java Swift and JavaScript. 116 00:06:08,600 --> 00:06:13,310 So I'll be focusing on RxJava today. 117 00:06:13,310 --> 00:06:17,400 118 00:06:17,400 --> 00:06:20,720 So let's go for an example of a data stream. 119 00:06:20,720 --> 00:06:25,160 I've kind of tossed around this term, a flow of data, some events submitted. 120 00:06:25,160 --> 00:06:27,190 And we'll actually look at an example. 121 00:06:27,190 --> 00:06:30,800 So this line here represents a timeline of events. 122 00:06:30,800 --> 00:06:34,890 123 00:06:34,890 --> 00:06:38,630 Data will be emitted on this timeline of events, 124 00:06:38,630 --> 00:06:43,100 and there don't have to be any data items for this stream to exist. 125 00:06:43,100 --> 00:06:44,990 There could be nothing that ever happens. 126 00:06:44,990 --> 00:06:49,070 Kind of pointless, but there could just be one or a million. 127 00:06:49,070 --> 00:06:53,030 They could be emitted at any time and no regular intervals. 128 00:06:53,030 --> 00:06:55,670 So, for instance, suppose we have some imaginary data 129 00:06:55,670 --> 00:06:57,350 source that's emitting numbers. 130 00:06:57,350 --> 00:07:02,465 And here, it emits 4, 2, 1, 7, 6 at kind of a regular interval. 131 00:07:02,465 --> 00:07:05,460 132 00:07:05,460 --> 00:07:09,800 And now, with that data stream, as these events were being emitted, 133 00:07:09,800 --> 00:07:15,030 suppose that we had some function that could transform the data in some way. 134 00:07:15,030 --> 00:07:17,840 So maybe this function is called filter. 135 00:07:17,840 --> 00:07:20,690 And right here, we have the function filter 136 00:07:20,690 --> 00:07:25,180 that takes an input x, which would be any one of these individual values. 137 00:07:25,180 --> 00:07:29,210 And it will check if that value's even, because x mod 2 equals 138 00:07:29,210 --> 00:07:31,290 0 will check if the value is even. 139 00:07:31,290 --> 00:07:37,650 And so this will return true or false depending on the input of each value. 140 00:07:37,650 --> 00:07:41,390 So if we apply this function to each data item, 141 00:07:41,390 --> 00:07:43,800 only the even numbers will be in our output. 142 00:07:43,800 --> 00:07:48,620 So 4 mod 2 equals 0, this is an even number. 143 00:07:48,620 --> 00:07:50,390 2 is also an even number. 144 00:07:50,390 --> 00:07:53,810 1 is not, so no event would be emitted there. 145 00:07:53,810 --> 00:07:59,330 7 is not, but 6 is, so that one would also be emitted. 146 00:07:59,330 --> 00:08:01,730 And these data streams could live anywhere. 147 00:08:01,730 --> 00:08:06,410 So, for example, this stream emitting the events 148 00:08:06,410 --> 00:08:10,580 could be some cloud application, some server. 149 00:08:10,580 --> 00:08:15,140 And maybe we're subscribing to the events on a phone. 150 00:08:15,140 --> 00:08:19,640 And this could be like a mobile device rendering a UI. 151 00:08:19,640 --> 00:08:26,030 And the technical terms here to describe the stream that's emitting events 152 00:08:26,030 --> 00:08:27,380 is called the subject. 153 00:08:27,380 --> 00:08:31,010 So this is the one that's actually producing the events. 154 00:08:31,010 --> 00:08:34,460 It could produce zero items, one, or millions. 155 00:08:34,460 --> 00:08:38,000 In this case, it produces five. 156 00:08:38,000 --> 00:08:41,870 And the stream at the end that's actually consuming the event 157 00:08:41,870 --> 00:08:44,240 is called the observer. 158 00:08:44,240 --> 00:08:47,194 And we aren't limited to just one observer. 159 00:08:47,194 --> 00:08:49,610 This is one of the cool things about reactive programming, 160 00:08:49,610 --> 00:08:53,910 is we can actually have multiple ones. 161 00:08:53,910 --> 00:08:55,800 And I'll get into that in a little bit. 162 00:08:55,800 --> 00:09:00,220 So in this simple example, to come back to it now that we know these terms, 163 00:09:00,220 --> 00:09:04,720 there is a subject emitting data, a function manipulating the data, 164 00:09:04,720 --> 00:09:06,590 and an observer consuming the output. 165 00:09:06,590 --> 00:09:09,200 166 00:09:09,200 --> 00:09:13,220 This idea is also similar to publish/subscribe, 167 00:09:13,220 --> 00:09:15,590 or pub/sub, if you heard that before. 168 00:09:15,590 --> 00:09:17,480 It's technically called the observer pattern, 169 00:09:17,480 --> 00:09:20,060 because we have a subject producing data. 170 00:09:20,060 --> 00:09:22,550 And we can have multiple observers, which 171 00:09:22,550 --> 00:09:26,720 is one of the Gang of Four patterns, if you've heard of those before. 172 00:09:26,720 --> 00:09:29,230 But no worries if you haven't. 173 00:09:29,230 --> 00:09:31,790 And as I mentioned, we could have multiple observers. 174 00:09:31,790 --> 00:09:35,920 So this one, maybe it uses the same function, 175 00:09:35,920 --> 00:09:40,520 and this is just some other application, maybe a different element of the UI, 176 00:09:40,520 --> 00:09:42,350 that's also taking in the same data input. 177 00:09:42,350 --> 00:09:45,950 178 00:09:45,950 --> 00:09:48,990 So in our example, we used a function called filter, 179 00:09:48,990 --> 00:09:52,120 but there are many commonly built-in functions to reactive 180 00:09:52,120 --> 00:09:57,110 extension specification, which should cover pretty much all your use cases. 181 00:09:57,110 --> 00:10:02,660 So, for instance, there is also filter, map, count, max, min, delay, 182 00:10:02,660 --> 00:10:05,480 and they're probably pretty self-explanatory. 183 00:10:05,480 --> 00:10:08,210 Map, if you haven't heard that term before, 184 00:10:08,210 --> 00:10:14,902 is a way of saying that we want to transform a data into a different type 185 00:10:14,902 --> 00:10:16,110 of data or a different value. 186 00:10:16,110 --> 00:10:19,650 So maybe we take in an integer and we return a string. 187 00:10:19,650 --> 00:10:22,190 And that would be mapping data into something else. 188 00:10:22,190 --> 00:10:24,750 189 00:10:24,750 --> 00:10:28,310 So, basically, it's some function that takes some amount of time. 190 00:10:28,310 --> 00:10:30,230 And a lot of these operations, like filter, 191 00:10:30,230 --> 00:10:31,580 that'd be a very fast operation. 192 00:10:31,580 --> 00:10:34,237 But it would be OK if we do some operation 193 00:10:34,237 --> 00:10:35,570 they would take a bit more time. 194 00:10:35,570 --> 00:10:38,450 Because as I mentioned, these are asynchronous operations. 195 00:10:38,450 --> 00:10:42,370 So our observer doesn't necessarily expect the data to be emitted quickly. 196 00:10:42,370 --> 00:10:47,720 It'll handle it whenever it actually gets the result. 197 00:10:47,720 --> 00:10:52,370 And remember that there is no regular interval for the data items emitted. 198 00:10:52,370 --> 00:10:54,530 They could have been at totally different times, 199 00:10:54,530 --> 00:10:56,238 and there might not have been any events. 200 00:10:56,238 --> 00:10:58,610 201 00:10:58,610 --> 00:11:00,770 And our data event doesn't need to be numbers. 202 00:11:00,770 --> 00:11:04,970 It could be strings, floats, complex objects, maybe coordinates, 203 00:11:04,970 --> 00:11:07,490 or maybe some user data. 204 00:11:07,490 --> 00:11:09,350 In this case, characters. 205 00:11:09,350 --> 00:11:15,890 206 00:11:15,890 --> 00:11:21,680 And that data is manipulated by some function that transforms the data. 207 00:11:21,680 --> 00:11:26,520 It could even adjust the interval at which the data is output. 208 00:11:26,520 --> 00:11:30,270 So, for instance, here, maybe the data-- 209 00:11:30,270 --> 00:11:34,010 the observer doesn't see the exact same number of events at the same time. 210 00:11:34,010 --> 00:11:35,826 Notice here that it's shifted a little bit. 211 00:11:35,826 --> 00:11:37,700 And perhaps that's because there is some sort 212 00:11:37,700 --> 00:11:40,380 of like delay in that particular item. 213 00:11:40,380 --> 00:11:43,300 But we can basically do any sort of transformation we want. 214 00:11:43,300 --> 00:11:46,291 215 00:11:46,291 --> 00:11:48,040 And as I mentioned, furthermore, there can 216 00:11:48,040 --> 00:11:52,330 be multiple functions that can be chained together 217 00:11:52,330 --> 00:11:54,880 between the subject and the observer. 218 00:11:54,880 --> 00:11:57,340 So you might ask, why do we need multiple functions? 219 00:11:57,340 --> 00:12:00,250 Can't you just have one function that does all the transformations 220 00:12:00,250 --> 00:12:02,174 that you need all at once? 221 00:12:02,174 --> 00:12:04,090 Well, at the core of it, it's because we don't 222 00:12:04,090 --> 00:12:06,190 want our functions to be too complex. 223 00:12:06,190 --> 00:12:07,690 Functions should do one thing. 224 00:12:07,690 --> 00:12:12,730 And maybe to perform the final operation we want, 225 00:12:12,730 --> 00:12:16,360 we want to do some combination of filtering out some values, 226 00:12:16,360 --> 00:12:19,357 mapping some values, and maybe grouping things. 227 00:12:19,357 --> 00:12:21,940 These are all operations that we should think of as separately 228 00:12:21,940 --> 00:12:23,023 but we can chain together. 229 00:12:23,023 --> 00:12:28,210 230 00:12:28,210 --> 00:12:30,840 And so maybe this is an example output. 231 00:12:30,840 --> 00:12:35,710 232 00:12:35,710 --> 00:12:38,830 And what creates the subject data stream? 233 00:12:38,830 --> 00:12:42,470 Because I've kind of been saying like the data comes from somewhere. 234 00:12:42,470 --> 00:12:50,290 But something actually has to produce it with this idea of a stream in mind. 235 00:12:50,290 --> 00:12:53,410 And these streams in our Java are called observables. 236 00:12:53,410 --> 00:12:55,922 And don't worry about this observable nomenclature. 237 00:12:55,922 --> 00:12:57,880 It's more important that you kind of understand 238 00:12:57,880 --> 00:13:00,820 this high-level idea of reactive programming 239 00:13:00,820 --> 00:13:06,910 rather than the specific terms used in RxJava and the implementation. 240 00:13:06,910 --> 00:13:09,790 But when these streams are created, there's 241 00:13:09,790 --> 00:13:13,180 just some create method or some fromIterable, 242 00:13:13,180 --> 00:13:18,700 something that says we'll take in some input and start returning a stream. 243 00:13:18,700 --> 00:13:23,770 And applying this sort of principle to existing object-oriented code 244 00:13:23,770 --> 00:13:27,400 can be a little messy sometimes. 245 00:13:27,400 --> 00:13:31,000 So that's part of the reason that it's usually 246 00:13:31,000 --> 00:13:33,130 nice to kind of abstract that away. 247 00:13:33,130 --> 00:13:35,440 And there are many open source projects out there 248 00:13:35,440 --> 00:13:41,170 that have many stars on GitHub that just wrap some existing library in an Rx 249 00:13:41,170 --> 00:13:44,170 library, and then they're very popular. 250 00:13:44,170 --> 00:13:49,960 For instance, this one here is just a list of other Rx libraries, 251 00:13:49,960 --> 00:13:51,820 and it has 500 stars on GitHub. 252 00:13:51,820 --> 00:13:53,980 And kudos to that person who made it. 253 00:13:53,980 --> 00:13:58,240 But I'm just saying there's a lot of interest in reactive programming 254 00:13:58,240 --> 00:13:58,900 out there. 255 00:13:58,900 --> 00:14:06,390 And just sometimes applying this sort of clean-- 256 00:14:06,390 --> 00:14:10,540 abstracting this messy start away is really helpful, 257 00:14:10,540 --> 00:14:13,600 and people appreciate it. 258 00:14:13,600 --> 00:14:16,990 So, hopefully, now you understand high-level principles 259 00:14:16,990 --> 00:14:21,280 of reactive programming, some applications for when we'd use it, 260 00:14:21,280 --> 00:14:26,650 what a data stream is, how a function can manipulate a data stream, 261 00:14:26,650 --> 00:14:33,080 and how observers listen to asynchronous events and what that means. 262 00:14:33,080 --> 00:14:36,030 And so we'll get into some more background and examples later, 263 00:14:36,030 --> 00:14:38,660 but I do want to pause for questions here. 264 00:14:38,660 --> 00:14:44,010 I know that's a lot, and I threw out a lot of terms. 265 00:14:44,010 --> 00:14:49,100 So can I help clear anything up? 266 00:14:49,100 --> 00:14:49,830 Yeah? 267 00:14:49,830 --> 00:14:53,220 AUDIENCE: Java has map collective filter. 268 00:14:53,220 --> 00:14:56,509 Is it just inheriting that from something? 269 00:14:56,509 --> 00:14:58,300 JORDAN JOZWIAK: Yeah, that's a great point, 270 00:14:58,300 --> 00:15:00,216 and I don't think I talk about this elsewhere. 271 00:15:00,216 --> 00:15:07,960 So starting in Java 8, they added more functional aspects to Java. 272 00:15:07,960 --> 00:15:10,540 And Java itself does have some streams. 273 00:15:10,540 --> 00:15:14,492 One reason that it's still popular, RxJava 274 00:15:14,492 --> 00:15:16,450 happens to be popular in the Android community, 275 00:15:16,450 --> 00:15:19,000 is because a lot of that functionality isn't available. 276 00:15:19,000 --> 00:15:23,950 But in addition to that, streams in Java are pretty good, 277 00:15:23,950 --> 00:15:27,220 but I think people have some concerns about them. 278 00:15:27,220 --> 00:15:29,140 They could be easier to work with. 279 00:15:29,140 --> 00:15:34,240 At least in terms of contained within the stream, it might be fine. 280 00:15:34,240 --> 00:15:42,250 But RxJava here has the benefits of it has a little more flexibility in terms 281 00:15:42,250 --> 00:15:43,360 of the observer pattern. 282 00:15:43,360 --> 00:15:47,750 It has more options in terms of the threads that you can subscribe on. 283 00:15:47,750 --> 00:15:51,874 So I would say it's just kind of a next step up. 284 00:15:51,874 --> 00:15:55,590 285 00:15:55,590 --> 00:15:57,980 Anything else? 286 00:15:57,980 --> 00:15:59,390 Yeah? 287 00:15:59,390 --> 00:16:01,740 AUDIENCE: For the term functional reactive programming, 288 00:16:01,740 --> 00:16:06,450 where that term is kind of [INAUDIBLE]. 289 00:16:06,450 --> 00:16:09,960 JORDAN JOZWIAK: So I am not like a theorist in terms 290 00:16:09,960 --> 00:16:17,580 of understanding all the programming paradigms 291 00:16:17,580 --> 00:16:21,600 and how they relate to each other. 292 00:16:21,600 --> 00:16:25,630 I know when I've read the reactive extension specifications, 293 00:16:25,630 --> 00:16:28,050 they say this is not functional reactive programming. 294 00:16:28,050 --> 00:16:29,340 That is something else. 295 00:16:29,340 --> 00:16:34,320 But honestly, I don't think I could clarify you what exactly that is. 296 00:16:34,320 --> 00:16:36,845 But maybe we could talk afterward. 297 00:16:36,845 --> 00:16:39,457 298 00:16:39,457 --> 00:16:40,040 Anything else? 299 00:16:40,040 --> 00:16:42,650 300 00:16:42,650 --> 00:16:46,370 OK, well, we'll just keep going, then. 301 00:16:46,370 --> 00:16:50,450 So, before we get a little bit farther, I just 302 00:16:50,450 --> 00:16:53,060 am curious what languages are you all familiar with? 303 00:16:53,060 --> 00:16:55,155 You can just shout it out. 304 00:16:55,155 --> 00:16:57,280 And I know some of the languages you learn in CS50, 305 00:16:57,280 --> 00:17:00,380 so if you don't say those, I'm on to you. 306 00:17:00,380 --> 00:17:01,200 AUDIENCE: Python. 307 00:17:01,200 --> 00:17:02,315 JORDAN JOZWIAK: OK, nice. 308 00:17:02,315 --> 00:17:02,720 AUDIENCE: Java. 309 00:17:02,720 --> 00:17:03,140 JORDAN JOZWIAK: Java. 310 00:17:03,140 --> 00:17:03,950 AUDIENCE: Swift. 311 00:17:03,950 --> 00:17:05,241 JORDAN JOZWIAK: Swift, oh, fun. 312 00:17:05,241 --> 00:17:05,869 AUDIENCE: C++. 313 00:17:05,869 --> 00:17:06,750 JORDAN JOZWIAK: C++. 314 00:17:06,750 --> 00:17:07,636 AUDIENCE: R. 315 00:17:07,636 --> 00:17:08,522 JORDAN JOZWIAK: R. 316 00:17:08,522 --> 00:17:09,410 AUDIENCE: C. 317 00:17:09,410 --> 00:17:12,079 JORDAN JOZWIAK: C, yeah, there we go. 318 00:17:12,079 --> 00:17:13,579 The one everyone should be learning. 319 00:17:13,579 --> 00:17:18,710 320 00:17:18,710 --> 00:17:31,160 A lot of those languages mentioned come from imperative or multi-paradigmatic 321 00:17:31,160 --> 00:17:32,150 background. 322 00:17:32,150 --> 00:17:37,310 And what that means is they usually involve some sort 323 00:17:37,310 --> 00:17:42,620 of conditional logic and state. 324 00:17:42,620 --> 00:17:45,410 And we'll get into that more in a little bit. 325 00:17:45,410 --> 00:17:48,420 Some of these languages also have functional aspects to them, 326 00:17:48,420 --> 00:17:51,260 and that's part of what makes them multi-paradigmatic. 327 00:17:51,260 --> 00:17:55,640 So, for instance, Java now has functions built into the language, 328 00:17:55,640 --> 00:17:58,325 and Swift also has a lot of functional aspects. 329 00:17:58,325 --> 00:18:02,540 330 00:18:02,540 --> 00:18:05,990 And functional programming has a very steep learning curve 331 00:18:05,990 --> 00:18:08,310 I know that when I was first getting introduced to it, 332 00:18:08,310 --> 00:18:09,980 it took a while to understand. 333 00:18:09,980 --> 00:18:11,930 And RxJava, what I'm talking about today, 334 00:18:11,930 --> 00:18:14,400 took even longer to understand on top of that. 335 00:18:14,400 --> 00:18:20,030 So good for all of you for showing up today and grokking some of this. 336 00:18:20,030 --> 00:18:22,430 No worries if it's a little difficult to follow. 337 00:18:22,430 --> 00:18:26,430 That's also a little bit on me for presenting it. 338 00:18:26,430 --> 00:18:32,840 So when I was learning this, I also asked myself, 339 00:18:32,840 --> 00:18:35,360 why are there different language paradigms? 340 00:18:35,360 --> 00:18:38,430 Why isn't there one language that just works for everything? 341 00:18:38,430 --> 00:18:43,130 And part of this is there are different use cases for programming. 342 00:18:43,130 --> 00:18:44,340 It's just like a toolbox. 343 00:18:44,340 --> 00:18:47,423 There are different tools that you have to pick the right one for the job. 344 00:18:47,423 --> 00:18:50,195 But part of this is also kind of an organic immersion of ideas. 345 00:18:50,195 --> 00:18:53,660 346 00:18:53,660 --> 00:18:57,800 So, for instance, even in linguistic languages, 347 00:18:57,800 --> 00:19:02,120 there are differences in how people end up communicating. 348 00:19:02,120 --> 00:19:04,460 So, for instance, grammatical structures. 349 00:19:04,460 --> 00:19:08,360 In some languages, I might, say, refer to my house as Jordan's house, 350 00:19:08,360 --> 00:19:13,460 and in other languages, it might translate to be the house of Jordan. 351 00:19:13,460 --> 00:19:20,820 There's also, in Spanish, there are multiple tenses for the past tense. 352 00:19:20,820 --> 00:19:25,430 There's a recurring past tense and a finite one. 353 00:19:25,430 --> 00:19:29,030 And not all words have the same sort of translation across languages. 354 00:19:29,030 --> 00:19:31,280 You don't just have a single word. 355 00:19:31,280 --> 00:19:33,860 And there are also dialects within a language. 356 00:19:33,860 --> 00:19:36,810 So I kind of throw this out there as an example 357 00:19:36,810 --> 00:19:42,200 of just to say that in language, there's no one language that 358 00:19:42,200 --> 00:19:44,870 is suitable for all purposes. 359 00:19:44,870 --> 00:19:49,790 And also, we've all had similar life experiences globally, 360 00:19:49,790 --> 00:19:53,210 but different languages have emerged. 361 00:19:53,210 --> 00:19:57,460 And so, in some ways, that's similar to computer programming, 362 00:19:57,460 --> 00:20:01,160 that languages are multifaceted, but they also evolve over time. 363 00:20:01,160 --> 00:20:04,120 364 00:20:04,120 --> 00:20:08,310 So, for instance, imperative is one sort of language paradigm, 365 00:20:08,310 --> 00:20:11,280 and that's probably what you've used for a lot of the languages 366 00:20:11,280 --> 00:20:12,457 you've worked with. 367 00:20:12,457 --> 00:20:14,790 In reactive programming, what we're talking about today, 368 00:20:14,790 --> 00:20:19,410 is kind of a more specific programming paradigm. 369 00:20:19,410 --> 00:20:22,410 But that's based on, or partially inspired 370 00:20:22,410 --> 00:20:26,280 by, functional programming, which is used in reactive programming, 371 00:20:26,280 --> 00:20:29,280 and I'll talk more about it. 372 00:20:29,280 --> 00:20:31,710 So I just tossed out these terms-- 373 00:20:31,710 --> 00:20:33,780 imperative, functional. 374 00:20:33,780 --> 00:20:41,560 Imperative is, as I was saying, kind of based on state and conditions. 375 00:20:41,560 --> 00:20:44,170 So let's kind of compare these. 376 00:20:44,170 --> 00:20:47,820 And technically, imperative and declarative 377 00:20:47,820 --> 00:20:54,660 are the comparison points here, but we'll use functional for simplicity. 378 00:20:54,660 --> 00:20:58,080 Imperative programming, we describe how the program operates. 379 00:20:58,080 --> 00:21:02,310 And that means we have statements to change the state of the program. 380 00:21:02,310 --> 00:21:04,410 We have conditional statements, loops. 381 00:21:04,410 --> 00:21:08,250 We might even have inheritance and these ideas 382 00:21:08,250 --> 00:21:13,657 of components that can be put together to create the whole piece. 383 00:21:13,657 --> 00:21:15,240 It's usually an easier learning curve. 384 00:21:15,240 --> 00:21:20,280 That's kind of an intuitive way to think about programs, that there's 385 00:21:20,280 --> 00:21:22,980 some checkpoint that we understand this is the state we're in, 386 00:21:22,980 --> 00:21:25,680 and then we manipulate it. 387 00:21:25,680 --> 00:21:29,430 And some examples include C, PHP, and Java. 388 00:21:29,430 --> 00:21:31,740 But I'm not trying to pick a fight with anyone 389 00:21:31,740 --> 00:21:36,780 if someone would argue that these languages are more multifaceted. 390 00:21:36,780 --> 00:21:38,580 And this is a really simple example. 391 00:21:38,580 --> 00:21:44,680 We have if value mod 2, checking if it's even, we do something. 392 00:21:44,680 --> 00:21:49,050 And here, you can kind of see that we already have some idea of state. 393 00:21:49,050 --> 00:21:53,640 There was a variable coming in, and there's an if statement 394 00:21:53,640 --> 00:21:56,490 to manipulate something. 395 00:21:56,490 --> 00:22:01,080 In functional programming, we describe what the program should accomplish. 396 00:22:01,080 --> 00:22:04,770 And that means it's, ideally, stateless, and it's 397 00:22:04,770 --> 00:22:08,900 using functions that can create expressions instead of statements. 398 00:22:08,900 --> 00:22:11,760 So we can chain together functions that are, ideally, 399 00:22:11,760 --> 00:22:17,340 pure, meaning that they don't have any other side effects of changing state. 400 00:22:17,340 --> 00:22:19,650 It's usually more difficult to understand conceptually, 401 00:22:19,650 --> 00:22:24,760 because you don't have that idea of where am I right now, 402 00:22:24,760 --> 00:22:27,870 and what are the components involved? 403 00:22:27,870 --> 00:22:31,610 And some examples of languages that are pretty more strongly functional 404 00:22:31,610 --> 00:22:33,120 are Scala and Haskell. 405 00:22:33,120 --> 00:22:35,880 And honestly, I haven't used either, but I know some people 406 00:22:35,880 --> 00:22:38,790 who use them really love them. 407 00:22:38,790 --> 00:22:44,340 And for example, this is just a function that could be used anywhere. 408 00:22:44,340 --> 00:22:50,490 But I'm trying to convey here that rather than maybe just have 409 00:22:50,490 --> 00:22:54,330 some sort of if statement checking and manipulating the data, we could apply 410 00:22:54,330 --> 00:22:59,490 a function, which would be used elsewhere. 411 00:22:59,490 --> 00:23:05,460 And imperative programming, originally a computer utilized vacuum tubes 412 00:23:05,460 --> 00:23:07,980 and had limited memory. 413 00:23:07,980 --> 00:23:11,350 They were written with step-by-step instructions, 414 00:23:11,350 --> 00:23:16,560 including in FORTRAN, which was introduced in 1954. 415 00:23:16,560 --> 00:23:21,270 And my understanding is it was the first usage of compiled language 416 00:23:21,270 --> 00:23:23,490 with variables and complex expressions. 417 00:23:23,490 --> 00:23:26,800 So in the past, maybe it was easy to understand, 418 00:23:26,800 --> 00:23:30,240 especially in terms of how we use computers, 419 00:23:30,240 --> 00:23:35,860 that we would kind of manipulate a state and iterate on that state. 420 00:23:35,860 --> 00:23:39,120 And then there have been other languages since then. 421 00:23:39,120 --> 00:23:44,840 And object-oriented programming really grew in the 1980s. 422 00:23:44,840 --> 00:23:46,020 And we'll get back to that. 423 00:23:46,020 --> 00:23:49,950 So in functional programming, it's based originally on lambda calculus. 424 00:23:49,950 --> 00:23:55,110 And also, don't ask me about the nuances of that, because I'm no mathematician. 425 00:23:55,110 --> 00:24:01,030 But at its core, it's a study of computation with functions. 426 00:24:01,030 --> 00:24:05,460 And the first functional programming language 427 00:24:05,460 --> 00:24:08,860 was LISP, which was developed by IBM in the 1950s. 428 00:24:08,860 --> 00:24:11,760 And it stands for List Processor, LISP. 429 00:24:11,760 --> 00:24:15,090 It's still in use today, and it's only one year younger than FORTRAN. 430 00:24:15,090 --> 00:24:19,110 So from the beginning, there was already kind of a thought about different ways 431 00:24:19,110 --> 00:24:21,100 to approach these problems, an imperative 432 00:24:21,100 --> 00:24:23,910 style and a functional style. 433 00:24:23,910 --> 00:24:29,190 And back from the '70s, there was this guy 434 00:24:29,190 --> 00:24:34,650 named John Backus, who gave a lecture at the Turing Awards on why 435 00:24:34,650 --> 00:24:37,710 imperative programming is bad and functional programming is good. 436 00:24:37,710 --> 00:24:39,429 And if you read about this online, you'll 437 00:24:39,429 --> 00:24:41,220 see there's still a lot of people out there 438 00:24:41,220 --> 00:24:45,990 who pretty strongly believe that imperative programming is 439 00:24:45,990 --> 00:24:48,780 part of the reason we experience so many bugs in programming. 440 00:24:48,780 --> 00:24:51,360 And that if we all just use functional programming, 441 00:24:51,360 --> 00:24:54,690 we would have a better developer-- we would have better coding experience, 442 00:24:54,690 --> 00:24:59,090 and we would encounter fewer problems in the real world. 443 00:24:59,090 --> 00:25:05,430 And part of the reason that functional programming didn't take off 444 00:25:05,430 --> 00:25:11,790 in popularity is just Java and object-oriented languages with 445 00:25:11,790 --> 00:25:17,640 encapsulation really dominated for through the '80s and the '00s. 446 00:25:17,640 --> 00:25:21,700 But when JavaScript grew in popularity, especially as a web language, 447 00:25:21,700 --> 00:25:25,770 it is a multi-paradigmatic language which 448 00:25:25,770 --> 00:25:31,320 makes use of passing around functions as first class objects or first class 449 00:25:31,320 --> 00:25:32,310 citizens. 450 00:25:32,310 --> 00:25:35,340 And I think that's probably part of the reason 451 00:25:35,340 --> 00:25:40,530 that functional programming has regrown in popularity. 452 00:25:40,530 --> 00:25:44,700 So reactive programming, we talked about these three areas, of data streams, 453 00:25:44,700 --> 00:25:48,240 functional programming, and asynchronous observers. 454 00:25:48,240 --> 00:25:52,610 So data streams, it's the flow of data objects from one function to the next. 455 00:25:52,610 --> 00:25:56,400 Ideally, immutable, but that's a different discussion. 456 00:25:56,400 --> 00:26:00,010 It's focusing on the idea of objects shouldn't change. 457 00:26:00,010 --> 00:26:01,740 They should be stateless. 458 00:26:01,740 --> 00:26:03,280 Functional programming. 459 00:26:03,280 --> 00:26:06,660 460 00:26:06,660 --> 00:26:08,910 Well, I mentioned that functions are meant to be pure. 461 00:26:08,910 --> 00:26:11,618 In our example, we had a filter function that took in some input. 462 00:26:11,618 --> 00:26:13,000 It happened to be an integer. 463 00:26:13,000 --> 00:26:14,880 And it returned a Boolean for whether the value should 464 00:26:14,880 --> 00:26:16,463 be included in the rest of our stream. 465 00:26:16,463 --> 00:26:20,160 466 00:26:20,160 --> 00:26:23,490 And it had no additional side effects. 467 00:26:23,490 --> 00:26:27,850 All its logic was contained to that particular function. 468 00:26:27,850 --> 00:26:32,700 So, for example, we could also have an add function that takes in two values 469 00:26:32,700 --> 00:26:36,600 and returns the result. And we'll also look a little bit 470 00:26:36,600 --> 00:26:40,290 later at a map function, as I was mentioning, that could maybe 471 00:26:40,290 --> 00:26:42,810 take in an integer and return a string. 472 00:26:42,810 --> 00:26:48,700 It can transform the data in however way we want. 473 00:26:48,700 --> 00:26:51,150 And with the asynchronous observers, that 474 00:26:51,150 --> 00:26:56,820 uses the observer pattern with a subject for data sources that notify observers. 475 00:26:56,820 --> 00:27:00,990 And one thing that I just want to mention but we won't focus on much 476 00:27:00,990 --> 00:27:04,590 is that there are errors that can happen in these data streams, 477 00:27:04,590 --> 00:27:06,960 and those are propagated through the whole flow of data. 478 00:27:06,960 --> 00:27:12,405 479 00:27:12,405 --> 00:27:14,280 In the programming that you're familiar with, 480 00:27:14,280 --> 00:27:17,040 maybe you have some error checking at the beginning. 481 00:27:17,040 --> 00:27:20,340 In Java, maybe you throw an exception and you have to handle that. 482 00:27:20,340 --> 00:27:24,009 With these stream of data, the error goes all the way through, 483 00:27:24,009 --> 00:27:26,550 and it's up to the consumer to either handle it or ignore it. 484 00:27:26,550 --> 00:27:29,024 485 00:27:29,024 --> 00:27:31,940 And reactive programming is not its own language, I mentioned on that. 486 00:27:31,940 --> 00:27:35,210 It's a library that we apply to some languages, like Java. 487 00:27:35,210 --> 00:27:38,720 And it's also not React, ReactJS, or ReactNative, if you've heard of those. 488 00:27:38,720 --> 00:27:44,000 Those are some libraries that were made by Facebook and kind of focus 489 00:27:44,000 --> 00:27:52,180 on improving UI development in mobile and web applications. 490 00:27:52,180 --> 00:27:58,052 So RxJava, I've mentioned, is the reactive library 491 00:27:58,052 --> 00:27:59,760 that I'm the most familiar with, and it's 492 00:27:59,760 --> 00:28:04,740 the one we'll be using our examples with today. 493 00:28:04,740 --> 00:28:09,570 It's pretty popular, and I've used it in my own work for some side projects 494 00:28:09,570 --> 00:28:12,150 and at work, as well. 495 00:28:12,150 --> 00:28:15,820 496 00:28:15,820 --> 00:28:23,400 So this specification is also applied to other languages, like RxJs and Swift. 497 00:28:23,400 --> 00:28:27,210 And it is helpful due to complicated stream and asynchronous APIs 498 00:28:27,210 --> 00:28:29,520 that would otherwise exist in Java. 499 00:28:29,520 --> 00:28:32,760 And it brings functional design to a language 500 00:28:32,760 --> 00:28:35,100 that's traditionally object oriented, even though it has 501 00:28:35,100 --> 00:28:38,550 some more modern functional aspects. 502 00:28:38,550 --> 00:28:42,240 And RxJava is also very helpful for mobile development, 503 00:28:42,240 --> 00:28:43,710 as I mentioned for Android. 504 00:28:43,710 --> 00:28:48,540 On Android, developers normally have to work within the constraints of Java 7, 505 00:28:48,540 --> 00:28:52,370 with some Java 8 functionality. 506 00:28:52,370 --> 00:28:56,210 And so it's very helpful there. 507 00:28:56,210 --> 00:28:59,160 So that's enough discussion of the background and history. 508 00:28:59,160 --> 00:29:01,650 So let's look at some actual code. 509 00:29:01,650 --> 00:29:04,780 Maybe that will help this all sink in a little bit more. 510 00:29:04,780 --> 00:29:10,500 But before we move on, any questions on any of this? 511 00:29:10,500 --> 00:29:12,560 Making sense so far? 512 00:29:12,560 --> 00:29:13,486 Yeah? 513 00:29:13,486 --> 00:29:16,660 AUDIENCE: You mentioned that in JavaScript, 514 00:29:16,660 --> 00:29:19,027 for empty functions, that's first class citizens. 515 00:29:19,027 --> 00:29:20,490 Could you clarify that? 516 00:29:20,490 --> 00:29:21,630 JORDAN JOZWIAK: Yeah. 517 00:29:21,630 --> 00:29:26,650 So in JavaScript, which it's been a little while since I worked with, 518 00:29:26,650 --> 00:29:30,610 but you can pass a function from one thing to another. 519 00:29:30,610 --> 00:29:36,970 And in Java, everything has to be a class. 520 00:29:36,970 --> 00:29:39,300 So when we pass a function, we're actually 521 00:29:39,300 --> 00:29:42,210 passing a class, which has an implementation of a function. 522 00:29:42,210 --> 00:29:46,940 In JavaScript, you can just pass a function itself. 523 00:29:46,940 --> 00:29:49,050 And so that's the way that it's-- 524 00:29:49,050 --> 00:29:51,750 525 00:29:51,750 --> 00:29:55,710 so in the argument of something, you can pass in a function. 526 00:29:55,710 --> 00:29:57,740 And that's what I mean by first class citizen. 527 00:29:57,740 --> 00:30:02,530 528 00:30:02,530 --> 00:30:05,410 Anything else? 529 00:30:05,410 --> 00:30:06,028 Yeah? 530 00:30:06,028 --> 00:30:08,944 AUDIENCE: You also mentioned that functional programming is stateless. 531 00:30:08,944 --> 00:30:10,140 What does that mean? 532 00:30:10,140 --> 00:30:11,910 JORDAN JOZWIAK: So state means-- 533 00:30:11,910 --> 00:30:16,170 and we'll look at this in some examples later. 534 00:30:16,170 --> 00:30:21,510 In a class, you have some variables that might live 535 00:30:21,510 --> 00:30:23,470 outside of your particular function. 536 00:30:23,470 --> 00:30:27,469 So maybe you're working on something, and at the top of your file, 537 00:30:27,469 --> 00:30:29,010 maybe you have some global variables. 538 00:30:29,010 --> 00:30:30,690 Maybe you also have something that-- 539 00:30:30,690 --> 00:30:32,850 like let's suppose we're making some game, 540 00:30:32,850 --> 00:30:36,030 and we have some variable for like hasGameStarted. 541 00:30:36,030 --> 00:30:39,310 And that's something that will kind of live there 542 00:30:39,310 --> 00:30:41,550 and we can access elsewhere in our code. 543 00:30:41,550 --> 00:30:43,262 And that's some state. 544 00:30:43,262 --> 00:30:44,970 And so when we talk about stateless, that 545 00:30:44,970 --> 00:30:49,150 would mean we somehow eliminate all those problems, 546 00:30:49,150 --> 00:30:53,190 that there is no external state that we'll be reading in. 547 00:30:53,190 --> 00:30:57,310 And that all the data that we care about lives within our data stream. 548 00:30:57,310 --> 00:31:01,246 549 00:31:01,246 --> 00:31:02,230 Anything else? 550 00:31:02,230 --> 00:31:07,650 551 00:31:07,650 --> 00:31:14,190 So suppose we want to observe some data. 552 00:31:14,190 --> 00:31:18,720 We'll use this term subscribe to mean observe 553 00:31:18,720 --> 00:31:21,570 the final result of a data stream. 554 00:31:21,570 --> 00:31:25,140 And here, we'll get into comparing the imperative 555 00:31:25,140 --> 00:31:27,032 approach and the reactive approach. 556 00:31:27,032 --> 00:31:28,990 And so we look at the imperative approach here, 557 00:31:28,990 --> 00:31:32,250 and maybe this is something that would look somewhat familiar. 558 00:31:32,250 --> 00:31:33,630 We have some data source. 559 00:31:33,630 --> 00:31:34,620 We'll get the data. 560 00:31:34,620 --> 00:31:36,240 It's a list. 561 00:31:36,240 --> 00:31:42,450 If you're not familiar with Java, this is kind of like an array, 562 00:31:42,450 --> 00:31:47,650 and it means that we have integer types here or like int types. 563 00:31:47,650 --> 00:31:49,840 So we have some list of data in a for loop. 564 00:31:49,840 --> 00:31:52,300 We'll just go through all of it, and we'll print it out. 565 00:31:52,300 --> 00:31:55,750 And this is how we might take some data and take some action on it. 566 00:31:55,750 --> 00:31:59,400 And so, for example, our data input here could be 4, 2, 1, 7, 6, 567 00:31:59,400 --> 00:32:01,680 and we print out 4, 2, 1, 7, 6. 568 00:32:01,680 --> 00:32:07,040 569 00:32:07,040 --> 00:32:13,150 So that's the data source, and we print out the values. 570 00:32:13,150 --> 00:32:15,740 And because we're using a for loop, that's one of the signs 571 00:32:15,740 --> 00:32:18,780 that this might be an imperative approach. 572 00:32:18,780 --> 00:32:21,430 Now let's look at the reactive solution. 573 00:32:21,430 --> 00:32:24,840 So note already that instead of getting a list of data, 574 00:32:24,840 --> 00:32:27,420 we have a stream of data. 575 00:32:27,420 --> 00:32:31,780 Remember our subject and observer from earlier? 576 00:32:31,780 --> 00:32:34,160 Well, this data source is our subject. 577 00:32:34,160 --> 00:32:37,989 Technically, this is returning an observable in RxJava, 578 00:32:37,989 --> 00:32:40,530 but again, I don't want to get caught up in the nomenclature. 579 00:32:40,530 --> 00:32:44,690 So we'll just see that it has some data stream. 580 00:32:44,690 --> 00:32:50,330 And our data stream has this built-in function called subscribe. 581 00:32:50,330 --> 00:32:54,830 This is part of the functionality that comes with using the ReactiveX library. 582 00:32:54,830 --> 00:32:58,990 And the subscribe method takes an observer. 583 00:32:58,990 --> 00:33:01,640 So this means we're done transforming our data, 584 00:33:01,640 --> 00:33:04,610 and we want to do something with it. 585 00:33:04,610 --> 00:33:07,920 Of course, we don't have any transformations at this time, 586 00:33:07,920 --> 00:33:11,310 but we will in the next example. 587 00:33:11,310 --> 00:33:15,157 So the observer technically takes in a class called a consumer, 588 00:33:15,157 --> 00:33:17,240 but this is what I was actually getting to earlier 589 00:33:17,240 --> 00:33:22,832 when we were talking about the first class citizens for languages, where 590 00:33:22,832 --> 00:33:24,290 functions are first class citizens. 591 00:33:24,290 --> 00:33:28,220 In Java, at least Java 7 and earlier, we always 592 00:33:28,220 --> 00:33:31,679 have to pass in some class which has an implementation of a function. 593 00:33:31,679 --> 00:33:33,720 So we'll get rid of this in a second, and then we 594 00:33:33,720 --> 00:33:37,830 don't have to worry about this name called consumer. 595 00:33:37,830 --> 00:33:44,510 And this is the function that the anonymous class actually implements. 596 00:33:44,510 --> 00:33:46,730 And again, we'll get rid of that in second. 597 00:33:46,730 --> 00:33:50,420 The important thing is that this method takes an individual value from the data 598 00:33:50,420 --> 00:33:54,906 stream called value, an integer value, and it does whatever it wants with it. 599 00:33:54,906 --> 00:33:56,530 So in this case, it just prints it out. 600 00:33:56,530 --> 00:34:00,350 601 00:34:00,350 --> 00:34:02,850 And so to simplify this expression, we'll 602 00:34:02,850 --> 00:34:05,460 use something called a lambda in Java. 603 00:34:05,460 --> 00:34:08,219 Don't worry about the name if you're not familiar with Java. 604 00:34:08,219 --> 00:34:11,820 But see now that we can kind of clean up-- this 605 00:34:11,820 --> 00:34:15,040 is what you might think of as passing in a function as an argument. 606 00:34:15,040 --> 00:34:17,969 So here, we just have the input, and we take some action on it. 607 00:34:17,969 --> 00:34:21,330 The arrow means that we're expressing a function. 608 00:34:21,330 --> 00:34:23,830 So the argument value is on the left. 609 00:34:23,830 --> 00:34:26,179 The body of the function is on the right. 610 00:34:26,179 --> 00:34:29,850 And the code does the same thing as that previous consumer class, 611 00:34:29,850 --> 00:34:32,241 but this is easier to understand. 612 00:34:32,241 --> 00:34:34,949 We can also use a method reference here, but that's a Java thing, 613 00:34:34,949 --> 00:34:38,020 and don't worry about it. 614 00:34:38,020 --> 00:34:42,300 So these are the imperative and reactive ways to print out a list of data. 615 00:34:42,300 --> 00:34:45,630 In the imperative case, we get all the data at once, and we use a for loop 616 00:34:45,630 --> 00:34:46,860 to print it out. 617 00:34:46,860 --> 00:34:52,370 In the reactive case, we get a data stream, and we observe each item. 618 00:34:52,370 --> 00:34:55,555 And in each case, we would print out 4, 2, 1, 7, 6. 619 00:34:55,555 --> 00:34:58,110 620 00:34:58,110 --> 00:35:00,022 And we can do more than print out our values. 621 00:35:00,022 --> 00:35:00,980 That's just an example. 622 00:35:00,980 --> 00:35:06,390 We could maybe update a UI with these values or maybe save to a database. 623 00:35:06,390 --> 00:35:10,420 Reactive programming is an approach with many applications, 624 00:35:10,420 --> 00:35:13,260 so we can kind of do whatever we want with this. 625 00:35:13,260 --> 00:35:17,010 So now let's talk about a scenario that definitely merits a reactive approach 626 00:35:17,010 --> 00:35:21,530 suppose we want to get all data changes from a data source. 627 00:35:21,530 --> 00:35:25,950 So we want to observe the changes. 628 00:35:25,950 --> 00:35:28,710 In Java, there might be simpler ways to do this, 629 00:35:28,710 --> 00:35:34,680 but this is one that I found as a solution. 630 00:35:34,680 --> 00:35:36,660 And it's kind of long and complicated. 631 00:35:36,660 --> 00:35:42,960 It involves some threads for scheduling updates to listen for data changes. 632 00:35:42,960 --> 00:35:47,490 And honestly, I don't even understand how all of that works. 633 00:35:47,490 --> 00:35:50,650 Basically, it's complicated, and there's a better way. 634 00:35:50,650 --> 00:35:53,460 So here's the reactive approach. 635 00:35:53,460 --> 00:35:55,890 Does it look familiar? 636 00:35:55,890 --> 00:35:58,380 It's the same as the other example. 637 00:35:58,380 --> 00:35:59,160 Why? 638 00:35:59,160 --> 00:36:02,100 Well, our data source is already a stream. 639 00:36:02,100 --> 00:36:04,980 So there is a base assumption that the subject emitting data 640 00:36:04,980 --> 00:36:06,944 events will notify us of all changes. 641 00:36:06,944 --> 00:36:08,610 That's what it was doing the whole time. 642 00:36:08,610 --> 00:36:13,360 Every time we got a data event, we would have it emitted there. 643 00:36:13,360 --> 00:36:16,330 So our observer will be called for all data changes going forward, 644 00:36:16,330 --> 00:36:19,170 for the first one, for the second one, until we 645 00:36:19,170 --> 00:36:20,730 decide to stop listening to data. 646 00:36:20,730 --> 00:36:23,360 647 00:36:23,360 --> 00:36:26,750 OK, any questions on that before we move on? 648 00:36:26,750 --> 00:36:31,282 The subscribe idea, data changes, make sense? 649 00:36:31,282 --> 00:36:34,782 AUDIENCE: So those two examples you have, they aren't really equivalent, 650 00:36:34,782 --> 00:36:36,490 because the thing on the left is actually 651 00:36:36,490 --> 00:36:42,090 doing the work of pulling to obtain new data and so on and so forth. 652 00:36:42,090 --> 00:36:44,860 Whereas the one on the right, it's like, oh, magic happens. 653 00:36:44,860 --> 00:36:47,720 And I know that there's new data and I can act upon it. 654 00:36:47,720 --> 00:36:50,785 So there's a lot of framework that has to be surrounding that, right? 655 00:36:50,785 --> 00:36:51,910 JORDAN JOZWIAK: True, true. 656 00:36:51,910 --> 00:36:55,330 And that's why, earlier on, I was kind of mentioning 657 00:36:55,330 --> 00:36:58,636 that the subject of getting that data stream, there's 658 00:36:58,636 --> 00:37:00,010 a lot of work that goes in there. 659 00:37:00,010 --> 00:37:03,220 And so you're right that, in some ways, this isn't a fair example. 660 00:37:03,220 --> 00:37:06,970 Because this code, something like this code, 661 00:37:06,970 --> 00:37:11,260 might have to live somewhere else in how we create the data stream. 662 00:37:11,260 --> 00:37:14,140 Yeah, and that that is kind of up to the implementation of that. 663 00:37:14,140 --> 00:37:20,690 664 00:37:20,690 --> 00:37:22,600 In some of these examples, especially when 665 00:37:22,600 --> 00:37:26,059 I portray reactive programming as the great way of doing things, 666 00:37:26,059 --> 00:37:28,600 you do have to keep in mind that somewhere behind the scenes, 667 00:37:28,600 --> 00:37:30,266 there might be something messy going on. 668 00:37:30,266 --> 00:37:32,620 669 00:37:32,620 --> 00:37:33,330 Anything else? 670 00:37:33,330 --> 00:37:36,005 Any questions? 671 00:37:36,005 --> 00:37:36,505 Yeah? 672 00:37:36,505 --> 00:37:39,000 AUDIENCE: You mentioned earlier about multiple observers. 673 00:37:39,000 --> 00:37:39,875 JORDAN JOZWIAK: Yeah. 674 00:37:39,875 --> 00:37:42,710 AUDIENCE: So for that, [INAUDIBLE] subscribe, 675 00:37:42,710 --> 00:37:47,120 or would you do another [INAUDIBLE]? 676 00:37:47,120 --> 00:37:48,920 JORDAN JOZWIAK: Yeah, they're assuming we 677 00:37:48,920 --> 00:37:51,980 don't want to get multiple instances of the data stream. 678 00:37:51,980 --> 00:37:57,830 We could have saved this as a variable, which maybe then we're 679 00:37:57,830 --> 00:38:01,220 getting into some imperative approach, but we can talk about that later. 680 00:38:01,220 --> 00:38:03,587 So we save this as a variable, and we subscribe to it. 681 00:38:03,587 --> 00:38:06,170 And we could just have another thing right here for the same-- 682 00:38:06,170 --> 00:38:08,170 I mean, we could just get the data stream again. 683 00:38:08,170 --> 00:38:11,120 Kind of depends on what this reference is. 684 00:38:11,120 --> 00:38:15,260 But then we can just say subscribe and another one 685 00:38:15,260 --> 00:38:18,300 and take some other action on it. 686 00:38:18,300 --> 00:38:18,800 Yeah? 687 00:38:18,800 --> 00:38:20,660 AUDIENCE: Can you chain subscribe calls? 688 00:38:20,660 --> 00:38:22,850 JORDAN JOZWIAK: No, that's the terminal call. 689 00:38:22,850 --> 00:38:25,970 But there is this idea of doOnNext. 690 00:38:25,970 --> 00:38:30,050 So we could have multiple things that happen for each event. 691 00:38:30,050 --> 00:38:36,280 And then, you could just subscribe without any action, which means 692 00:38:36,280 --> 00:38:39,230 start doing everything I said to do. 693 00:38:39,230 --> 00:38:44,812 So you could chain multiple doOnNext and then have that subscription start. 694 00:38:44,812 --> 00:38:47,270 But if we want them totally independent, then they probably 695 00:38:47,270 --> 00:38:49,040 should be different subscriptions. 696 00:38:49,040 --> 00:38:52,280 Kind of depends on whether there might be an order to the tasks 697 00:38:52,280 --> 00:38:56,907 that we want to accomplish. 698 00:38:56,907 --> 00:38:57,490 Anything else? 699 00:38:57,490 --> 00:39:02,260 700 00:39:02,260 --> 00:39:06,610 So now, let's actually apply a function to our data stream. 701 00:39:06,610 --> 00:39:12,010 I mentioned filter a few times, so we'll use that as our example. 702 00:39:12,010 --> 00:39:16,390 In the imperative approach, we will do pretty similar to what we did before. 703 00:39:16,390 --> 00:39:24,220 But now, we include this if statement to only print out the even values. 704 00:39:24,220 --> 00:39:31,030 Because again, this value mod 2 equals equals 0 will check if a value is even. 705 00:39:31,030 --> 00:39:35,915 And so rather than 4, 2, 1, 7, 6, we'll print out 4, 2, 6. 706 00:39:35,915 --> 00:39:40,400 707 00:39:40,400 --> 00:39:44,550 I kind of showed an example of this before when I had the animations. 708 00:39:44,550 --> 00:39:49,290 This is an actual image from the reactive spec. 709 00:39:49,290 --> 00:39:54,060 And we call these marble diagrams, because they're these little circles 710 00:39:54,060 --> 00:39:55,350 that might resemble marbles. 711 00:39:55,350 --> 00:39:59,800 And some of them through, other ones don't. 712 00:39:59,800 --> 00:40:04,350 So rather than use that if statement, we could think of that check 713 00:40:04,350 --> 00:40:11,880 is a function, which we can always just write that function separately and use 714 00:40:11,880 --> 00:40:13,020 it as an imperative way. 715 00:40:13,020 --> 00:40:16,530 But we're going to think about it in terms of manipulating a data stream. 716 00:40:16,530 --> 00:40:20,830 So similar to the timeline and data events from the beginning, 717 00:40:20,830 --> 00:40:26,400 this marble diagram shows how we could filter based on values greater than 10. 718 00:40:26,400 --> 00:40:31,620 But in our example, we're going to filter based on even numbers. 719 00:40:31,620 --> 00:40:34,270 So this is the reactive code. 720 00:40:34,270 --> 00:40:37,910 And here, we'll apply a function called filter, 721 00:40:37,910 --> 00:40:44,150 which takes the valley from each item in the data stream as the input. 722 00:40:44,150 --> 00:40:46,130 And it checks if the value is even. 723 00:40:46,130 --> 00:40:48,840 It implicitly there returns true or false. 724 00:40:48,840 --> 00:40:53,190 Value mod 2 equals equals 0 will return true or false. 725 00:40:53,190 --> 00:40:58,440 And this Boolean result is used within the internals of the filter mechanism 726 00:40:58,440 --> 00:41:01,590 to limit which items are passed through to the rest of the data stream. 727 00:41:01,590 --> 00:41:06,369 So, again, the implementation of filter might-- 728 00:41:06,369 --> 00:41:08,160 well, it's probably fairly straightforward, 729 00:41:08,160 --> 00:41:12,000 but it could always have something that maybe looks like this under the hood. 730 00:41:12,000 --> 00:41:15,175 731 00:41:15,175 --> 00:41:17,300 And filtering is an interesting example, because it 732 00:41:17,300 --> 00:41:20,780 restricts which items are emitted into the rest of the stream. 733 00:41:20,780 --> 00:41:26,040 But suppose we wanted to change all values in a consistent way. 734 00:41:26,040 --> 00:41:31,250 So if we were to, for instance, double all the values in our stream, 735 00:41:31,250 --> 00:41:35,450 we might take an imperative approach like this, where we don't 736 00:41:35,450 --> 00:41:36,960 have to save a temporary value here. 737 00:41:36,960 --> 00:41:44,144 But we just multiply the value by two and print out the result. 738 00:41:44,144 --> 00:41:47,310 But again, we could think about this as a way of manipulating a data stream, 739 00:41:47,310 --> 00:41:49,590 and we'll apply some function called map. 740 00:41:49,590 --> 00:41:53,370 This example marble diagram has all the values multiplied by 10. 741 00:41:53,370 --> 00:41:55,920 742 00:41:55,920 --> 00:41:59,400 And so the reactive code looks like this, pretty similar. 743 00:41:59,400 --> 00:42:01,930 Instead of the filter function, we have a map function, 744 00:42:01,930 --> 00:42:06,480 which is also one of the built-in functions to the reactive extensions 745 00:42:06,480 --> 00:42:07,380 library. 746 00:42:07,380 --> 00:42:11,010 And it takes each value from the stream as input. 747 00:42:11,010 --> 00:42:12,600 We calculate the new value-- 748 00:42:12,600 --> 00:42:14,640 in this case, multiplying it by two. 749 00:42:14,640 --> 00:42:18,360 And the result of that expression is implicitly returned, 750 00:42:18,360 --> 00:42:22,240 and then we subscribe to the results and print them out. 751 00:42:22,240 --> 00:42:23,820 OK, last example. 752 00:42:23,820 --> 00:42:27,250 This one is maybe a little more complicated. 753 00:42:27,250 --> 00:42:30,320 So I just want to show maybe one of the times 754 00:42:30,320 --> 00:42:35,260 where reactive programming could save a little bit of trouble. 755 00:42:35,260 --> 00:42:39,714 So this is the imperative code for grouping some data. 756 00:42:39,714 --> 00:42:41,880 And there are a number of different ways to do this. 757 00:42:41,880 --> 00:42:43,890 This is just one example. 758 00:42:43,890 --> 00:42:47,550 At a high level, we'll just kind of gloss over this. 759 00:42:47,550 --> 00:42:50,590 We scan through each item in the list, put it 760 00:42:50,590 --> 00:42:58,400 into a map with the appropriate key for even or odd, 761 00:42:58,400 --> 00:43:00,780 and then we'll print out the results at the end. 762 00:43:00,780 --> 00:43:04,740 So loop through each value, find out what the key is, put in the value 763 00:43:04,740 --> 00:43:07,090 into the key. 764 00:43:07,090 --> 00:43:08,200 This code is fine. 765 00:43:08,200 --> 00:43:09,700 It works. 766 00:43:09,700 --> 00:43:13,940 But there also some sort of different functions and tasks involved. 767 00:43:13,940 --> 00:43:19,200 There's some maybe grouping here based on different values. 768 00:43:19,200 --> 00:43:20,370 There's looping. 769 00:43:20,370 --> 00:43:25,980 The keys are some variables that are used outside of the loop. 770 00:43:25,980 --> 00:43:31,410 And so, in some ways, you might say that this code is a little muddled together. 771 00:43:31,410 --> 00:43:33,960 And we could definitely clean it up in an imperative way. 772 00:43:33,960 --> 00:43:38,070 But we can also think about it maybe as kind of a-- if we have a stream of data 773 00:43:38,070 --> 00:43:43,080 and we really want to separate these streams, we could group by this-- 774 00:43:43,080 --> 00:43:47,130 use a function called groupBy and separate our original stream 775 00:43:47,130 --> 00:43:50,310 into two different ones. 776 00:43:50,310 --> 00:43:55,110 And since grouping is an important part of data processing, of course, 777 00:43:55,110 --> 00:43:59,620 it's built into the reactive specification. 778 00:43:59,620 --> 00:44:02,950 So the reactive solution looks like this. 779 00:44:02,950 --> 00:44:04,200 We start with our data stream. 780 00:44:04,200 --> 00:44:07,530 781 00:44:07,530 --> 00:44:13,000 We apply a grouping function that will create the name for each group. 782 00:44:13,000 --> 00:44:17,880 So if the value is even, then we'll return the string even. 783 00:44:17,880 --> 00:44:20,880 And if it's odd, we'll return the string odd. 784 00:44:20,880 --> 00:44:25,950 And that is going to be used as our key for the rest of the stream. 785 00:44:25,950 --> 00:44:28,620 And I am cheating a little bit here. 786 00:44:28,620 --> 00:44:31,370 The collectInto function, which is also built in 787 00:44:31,370 --> 00:44:36,360 and is a way of kind of merging the result of a stream, 788 00:44:36,360 --> 00:44:38,670 this ends up still looking a little messy, 789 00:44:38,670 --> 00:44:43,650 kind of because we're putting a stream back into some stateful-- well, 790 00:44:43,650 --> 00:44:45,030 into some object. 791 00:44:45,030 --> 00:44:46,720 So kind of gloss over that. 792 00:44:46,720 --> 00:44:52,860 But keep in mind that the grouping part there is pretty easy. 793 00:44:52,860 --> 00:44:55,580 So there are a lot of examples. 794 00:44:55,580 --> 00:44:57,630 There have been a lot of examples to get us here. 795 00:44:57,630 --> 00:44:59,630 But hopefully, this gives you a glimpse into how 796 00:44:59,630 --> 00:45:05,850 reactive programming can simplify the approach for certain problems. 797 00:45:05,850 --> 00:45:07,680 And there are many more operators. 798 00:45:07,680 --> 00:45:11,530 We talked about filter, map, and groupBy, 799 00:45:11,530 --> 00:45:13,140 but here are some of the other ones. 800 00:45:13,140 --> 00:45:14,940 Many are self-explanatory in their name. 801 00:45:14,940 --> 00:45:16,720 Hopefully, they make sense. 802 00:45:16,720 --> 00:45:19,860 I think a really powerful one that's especially 803 00:45:19,860 --> 00:45:23,340 helpful in mobile programming is called debounce, 804 00:45:23,340 --> 00:45:28,350 which means if a user is typing, for instance, in a search field, 805 00:45:28,350 --> 00:45:30,210 we wouldn't want to show them autocomplete-- 806 00:45:30,210 --> 00:45:32,440 we want to show them autocomplete results, 807 00:45:32,440 --> 00:45:35,970 but not for every new character they search, right? 808 00:45:35,970 --> 00:45:39,370 Especially if that's something that maybe involves querying some server. 809 00:45:39,370 --> 00:45:46,130 We don't want to send 20 server requests if they type a 20-character query. 810 00:45:46,130 --> 00:45:51,180 So debouncing allows us to set a window of time where we listen for changes 811 00:45:51,180 --> 00:45:53,190 and then take action on the most recent one. 812 00:45:53,190 --> 00:45:56,250 So if the user is typing really fast but then they pause, 813 00:45:56,250 --> 00:45:58,500 then we'll show the results for that. 814 00:45:58,500 --> 00:46:02,160 And this is, again, something that under the hood may be a little messy. 815 00:46:02,160 --> 00:46:05,470 But because we're using the reactive extensions library, 816 00:46:05,470 --> 00:46:06,610 debounce is just built in. 817 00:46:06,610 --> 00:46:10,650 818 00:46:10,650 --> 00:46:13,830 And if this all seems complicated, it is. 819 00:46:13,830 --> 00:46:15,390 It's hard to learn. 820 00:46:15,390 --> 00:46:17,880 It takes a little while getting used to. 821 00:46:17,880 --> 00:46:22,350 Even when I thought I understood RxJava and reactive programming, 822 00:46:22,350 --> 00:46:25,620 I look at a diagram like this and stare blankly. 823 00:46:25,620 --> 00:46:28,770 To be honest, I still don't really know what this is saying. 824 00:46:28,770 --> 00:46:34,200 I'm not sure why red circle comma cloud equals red cloud. 825 00:46:34,200 --> 00:46:36,990 826 00:46:36,990 --> 00:46:40,260 So if you become an expert in reactive programming and RxJava, 827 00:46:40,260 --> 00:46:41,370 please explain this to me. 828 00:46:41,370 --> 00:46:44,800 But this is one of the examples for the operator join. 829 00:46:44,800 --> 00:46:47,490 830 00:46:47,490 --> 00:46:50,100 So we started theoretical. 831 00:46:50,100 --> 00:46:53,700 Then, we looked at some code examples with actual functions. 832 00:46:53,700 --> 00:46:57,180 And so now, I want to do a quick demo to really emphasize 833 00:46:57,180 --> 00:46:59,850 how powerful RxJava can be. 834 00:46:59,850 --> 00:47:06,000 But first, before we dive into that, any questions on any of the examples 835 00:47:06,000 --> 00:47:08,880 or still what is a data stream, what am I talking about? 836 00:47:08,880 --> 00:47:13,120 837 00:47:13,120 --> 00:47:15,010 Anything? 838 00:47:15,010 --> 00:47:16,640 OK. 839 00:47:16,640 --> 00:47:19,140 There'll still be time for questions at the end. 840 00:47:19,140 --> 00:47:22,320 841 00:47:22,320 --> 00:47:25,450 I'm just going to mirror my displays now. 842 00:47:25,450 --> 00:47:47,010 843 00:47:47,010 --> 00:47:49,714 I made this. 844 00:47:49,714 --> 00:47:51,630 I have been an Android developer, so I thought 845 00:47:51,630 --> 00:47:54,675 it might be fitting to use an Android app as a quick example. 846 00:47:54,675 --> 00:47:57,394 847 00:47:57,394 --> 00:47:58,810 Pretty sure this is a similar one. 848 00:47:58,810 --> 00:48:07,850 OK so I made a little Android app here that is, hopefully, going to run. 849 00:48:07,850 --> 00:48:26,999 850 00:48:26,999 --> 00:48:28,480 There we go. 851 00:48:28,480 --> 00:48:31,150 That's what I get for setting it to be five seconds. 852 00:48:31,150 --> 00:48:35,500 So this little app here is taking in-- 853 00:48:35,500 --> 00:48:39,970 it's using a FlakyTemperatureSensor, a FlakyWindSensor, 854 00:48:39,970 --> 00:48:44,950 and it's showing us the current temperature, wind speed, 855 00:48:44,950 --> 00:48:46,840 and then what it feels like. 856 00:48:46,840 --> 00:48:48,790 And these are like fake temperatures. 857 00:48:48,790 --> 00:48:51,100 They're just generating some random values 858 00:48:51,100 --> 00:48:55,250 within a somewhat appropriate range. 859 00:48:55,250 --> 00:49:01,590 And the reason they're called FlakyTemperatureSensor and wind sensor 860 00:49:01,590 --> 00:49:05,680 is because sometimes, as you might have noticed here, 861 00:49:05,680 --> 00:49:08,860 they return the value negative one, which 862 00:49:08,860 --> 00:49:12,910 is just because they're some hypothetical cheap sensors that 863 00:49:12,910 --> 00:49:15,530 don't always return useful values. 864 00:49:15,530 --> 00:49:18,730 And in this, I'm using the term presenter here 865 00:49:18,730 --> 00:49:23,950 as just some way of taking in these values and updating our UI. 866 00:49:23,950 --> 00:49:30,350 We have a sensor view, which allows us to set the temperature, 867 00:49:30,350 --> 00:49:37,760 wind, and feelsLike speeds or values that we see there. 868 00:49:37,760 --> 00:49:45,370 And this presenter, when it starts, it's going to add a listener. 869 00:49:45,370 --> 00:49:50,320 This probably applies across multiple languages. 870 00:49:50,320 --> 00:49:54,016 In Java, note that we have this anonymous class here, 871 00:49:54,016 --> 00:49:56,390 which it's telling me it could be simplified to a lambda. 872 00:49:56,390 --> 00:50:01,390 But I just want to put in the whole anonymous class as the example. 873 00:50:01,390 --> 00:50:03,580 So we take our temperature sensor. 874 00:50:03,580 --> 00:50:06,370 We add some listener, and it's going to keep 875 00:50:06,370 --> 00:50:11,500 track of the last temperature value, the last wind value for the wind sensor. 876 00:50:11,500 --> 00:50:14,110 And then, whenever one of those is updated, 877 00:50:14,110 --> 00:50:17,020 it's going to say handleValuesUpdated. 878 00:50:17,020 --> 00:50:22,780 So notice already here, because you can see with the feelsLike temperature, 879 00:50:22,780 --> 00:50:27,070 it's actually combining the values of the temperature and the wind speed 880 00:50:27,070 --> 00:50:32,750 and calculating some other temperature value. 881 00:50:32,750 --> 00:50:36,620 So that's why we are keeping these as some state. 882 00:50:36,620 --> 00:50:42,530 And to get back to that comment about state and stateless, 883 00:50:42,530 --> 00:50:44,680 this is an example of having some state in a class. 884 00:50:44,680 --> 00:50:48,845 These are some values that are living kind of outside of any function. 885 00:50:48,845 --> 00:50:50,470 For some reason, they're in this class. 886 00:50:50,470 --> 00:50:51,470 Maybe they shouldn't be. 887 00:50:51,470 --> 00:50:55,240 But this is one implementation. 888 00:50:55,240 --> 00:50:57,730 And so we're listening to these values. 889 00:50:57,730 --> 00:51:04,150 And in our handleValuesUpdated function here, first of all, we check-- 890 00:51:04,150 --> 00:51:08,442 if we don't have a temperature value or wind value, 891 00:51:08,442 --> 00:51:10,150 then we're just not going to do anything. 892 00:51:10,150 --> 00:51:14,777 Because when I calculate the feelsLike temperature, I need both values. 893 00:51:14,777 --> 00:51:16,610 And they're both initially going to be null, 894 00:51:16,610 --> 00:51:22,390 so this is a way of saying we're just ignoring this stuff at the beginning. 895 00:51:22,390 --> 00:51:27,160 Then, we're going to show the raw values in the view, the temperature 896 00:51:27,160 --> 00:51:28,750 value and the wind value. 897 00:51:28,750 --> 00:51:31,750 And then, I also mentioned that these are flaky sensors, right? 898 00:51:31,750 --> 00:51:35,510 So we're going to ignore the negative one values. 899 00:51:35,510 --> 00:51:39,410 And so we have some conditions here, all just to kind of get set up. 900 00:51:39,410 --> 00:51:42,340 And then we're converting a Celsius temperature 901 00:51:42,340 --> 00:51:43,630 to a Fahrenheit temperature. 902 00:51:43,630 --> 00:51:45,550 We have some function for that. 903 00:51:45,550 --> 00:51:48,370 And then we're calculating the feelsLike temperature 904 00:51:48,370 --> 00:51:52,090 based on the Fahrenheit temperature and the wind value. 905 00:51:52,090 --> 00:51:53,960 And then we're finally setting the value. 906 00:51:53,960 --> 00:52:01,240 So in order to accomplish this, we had some state which lived in our class. 907 00:52:01,240 --> 00:52:04,630 We have some conditional checks, and we have some functions 908 00:52:04,630 --> 00:52:06,250 that are transforming some data. 909 00:52:06,250 --> 00:52:11,170 And you look at this and you say, well, this accomplishes what I want. 910 00:52:11,170 --> 00:52:14,760 But in some ways, it's a little imperfect. 911 00:52:14,760 --> 00:52:20,110 And so I'll just kind of go through this reactive example. 912 00:52:20,110 --> 00:52:25,830 913 00:52:25,830 --> 00:52:30,010 So I'll try to go through this kind of quickly. 914 00:52:30,010 --> 00:52:30,680 Yeah, sorry. 915 00:52:30,680 --> 00:52:34,002 If any of you have to go somewhere, you're free to leave. 916 00:52:34,002 --> 00:52:36,540 917 00:52:36,540 --> 00:52:41,640 So if suppose, maybe, we have our temperature sensor. 918 00:52:41,640 --> 00:52:46,780 And instead of setting a callback, we'll get the data stream. 919 00:52:46,780 --> 00:52:48,570 And this will be our temperature stream. 920 00:52:48,570 --> 00:52:52,560 921 00:52:52,560 --> 00:52:54,591 And this happens to be an observable. 922 00:52:54,591 --> 00:52:57,750 923 00:52:57,750 --> 00:53:09,900 And for our wind sensor, we'll get our wind stream. 924 00:53:09,900 --> 00:53:14,350 And so now we're already subscribing to all changes in the data. 925 00:53:14,350 --> 00:53:17,700 And if we want to actually print out these values, like the raw values, 926 00:53:17,700 --> 00:53:20,400 as we were doing in the imperative approach, 927 00:53:20,400 --> 00:53:23,080 now we can do one subscription to them. 928 00:53:23,080 --> 00:53:26,760 So, for instance, in the temperature stream, we can subscribe. 929 00:53:26,760 --> 00:53:31,052 And for each value, we will set the temperature. 930 00:53:31,052 --> 00:53:34,220 931 00:53:34,220 --> 00:53:36,150 So here, we have one subscription. 932 00:53:36,150 --> 00:53:47,400 And for the wind one, we can also set the wind value. 933 00:53:47,400 --> 00:53:50,730 934 00:53:50,730 --> 00:54:02,440 And so if I just change to use our reactive presenter and run this, 935 00:54:02,440 --> 00:54:08,995 we won't get the feelsLike temperature yet, but we will get the other values. 936 00:54:08,995 --> 00:54:14,301 937 00:54:14,301 --> 00:54:16,050 And so now with the feelsLike temperature, 938 00:54:16,050 --> 00:54:18,030 we want it to actually filter out some values 939 00:54:18,030 --> 00:54:21,640 and convert a Celsius temperature to Fahrenheit. 940 00:54:21,640 --> 00:54:26,880 So another function that we have with our reactive observables 941 00:54:26,880 --> 00:54:28,440 is combineLatest. 942 00:54:28,440 --> 00:54:31,740 And this will allow us to take two different streams 943 00:54:31,740 --> 00:54:33,790 and combine them together. 944 00:54:33,790 --> 00:54:37,680 So, for instance, with our temperature stream, 945 00:54:37,680 --> 00:54:42,870 we can first we'll filter out the values that we don't want, 946 00:54:42,870 --> 00:54:50,085 which will be all negative one values. 947 00:54:50,085 --> 00:54:55,300 948 00:54:55,300 --> 00:55:00,490 And we also want to convert the values to Fahrenheit. 949 00:55:00,490 --> 00:55:08,460 And we'll still use that helper function we had before for convert. 950 00:55:08,460 --> 00:55:14,400 951 00:55:14,400 --> 00:55:20,030 And then, we'll also use our wind stream and filter out 952 00:55:20,030 --> 00:55:28,420 the values that we don't want, which is the negative one values. 953 00:55:28,420 --> 00:55:30,940 954 00:55:30,940 --> 00:55:34,880 And then, lastly, we have to combine these two streams together. 955 00:55:34,880 --> 00:55:41,140 So if we have a tempWind, we can use some function on them. 956 00:55:41,140 --> 00:55:43,930 957 00:55:43,930 --> 00:55:50,340 We can calculate the feelsLike temperature 958 00:55:50,340 --> 00:55:59,040 and, lastly, actually subscribe to all this 959 00:55:59,040 --> 00:56:01,132 with whatever the feelsLike value is. 960 00:56:01,132 --> 00:56:10,990 961 00:56:10,990 --> 00:56:12,145 So now, if we run this-- 962 00:56:12,145 --> 00:56:17,878 963 00:56:17,878 --> 00:56:20,368 AUDIENCE: There's a bracket that's not closed or something. 964 00:56:20,368 --> 00:56:21,862 JORDAN JOZWIAK: Oh, thanks, yeah. 965 00:56:21,862 --> 00:56:35,850 966 00:56:35,850 --> 00:56:38,160 Now, we also calculate the feelsLike temperature. 967 00:56:38,160 --> 00:56:42,277 So remember, in the other example, we had some callbacks. 968 00:56:42,277 --> 00:56:43,860 We were listening to some data values. 969 00:56:43,860 --> 00:56:47,700 We had some state for the last values, some conditional checks. 970 00:56:47,700 --> 00:56:51,450 And here, this is an example where we have two subscriptions. 971 00:56:51,450 --> 00:56:54,840 We just show the raw values here with the observable. 972 00:56:54,840 --> 00:56:59,440 But separately, we also use this combination function combineLatest, 973 00:56:59,440 --> 00:57:01,830 which is taking these two different streams, 974 00:57:01,830 --> 00:57:04,230 merging them together with this function, 975 00:57:04,230 --> 00:57:06,135 where we have temperature and wind. 976 00:57:06,135 --> 00:57:11,070 977 00:57:11,070 --> 00:57:13,530 And we calculate the feelsLike temperature on that. 978 00:57:13,530 --> 00:57:19,334 And then we subscribe to this particular value and set it on the view. 979 00:57:19,334 --> 00:57:20,250 Any questions on that? 980 00:57:20,250 --> 00:57:32,110 981 00:57:32,110 --> 00:57:40,300 So, to wrap up, reactive programming has data streams, functional programming, 982 00:57:40,300 --> 00:57:41,944 and asynchronous observers. 983 00:57:41,944 --> 00:57:42,860 When would you use it? 984 00:57:42,860 --> 00:57:45,776 Well, you'd use it when you're dealing with some of these things, when 985 00:57:45,776 --> 00:57:50,240 you're working with streams of data or you want to notify some set of things 986 00:57:50,240 --> 00:57:53,240 asynchronously. 987 00:57:53,240 --> 00:57:56,070 And so I'd like to thank you all for coming. 988 00:57:56,070 --> 00:57:59,600 I know this went a little long, so thanks for sticking around. 989 00:57:59,600 --> 00:58:03,084 Thank you, Ryan, for organizing; the CS50 staff for having me; 990 00:58:03,084 --> 00:58:05,000 and for all of you for showing up and learning 991 00:58:05,000 --> 00:58:09,310 about something that is maybe kind of different from what you normally do. 992 00:58:09,310 --> 00:58:12,960 I'll be around afterward to answer any questions. 993 00:58:12,960 --> 00:58:13,940 Thank you. 994 00:58:13,940 --> 00:58:15,790 [APPLAUSE]