Kaushik Gopal
Kaushik Gopal Senior Android Engineer, Google Developers Expert, Fragmented Podcast Founder at Instacart
  • Video
  • Audio
  • Table of contents
  • Video
  • Audio
MBLTdev 18 EN
September 28 2018, Moscow, Russia
MBLTdev 18 EN
Video
Unidirectional State Flow Patterns — a Refactoring Story
Available
In cart
Free
Free
Free
Free
Free
Free
Add to favorites
237
I like 1
I dislike 0
Available
In cart
Free
Free
Free
Free
Free
Free
  • Description
  • Transcript
  • Discussion

About speaker

  • Kaushik Gopal
    Kaushik Gopal Senior Android Engineer, Google Developers Expert, Fragmented Podcast Founder at Instacart

About the talk

Topic: IT
Track: Android
The sound of the video is damaged.


Learn how to go to your existing old mobile app and refactor it into one with a powerful architecture.

Share

(Russian) Yeah, thanks. 00:10 Greetings everyone. 00:10 Welcome to the 5th International Mobile Developers Conference MBLT}DEV 2018. 00:10 I'm Alena. 00:22 And I'm Nikita. 00:22 We are going to be in this hall all day. 00:22 We are going to have a productive day. 00:22 We have two halls and the hall with a live stream and lounge zone. 00:27 Also panels with IOS developers, networking and many other activities with prizes. 00:27 Download the mobile app of our conference by QR-cod on your name tag. 00:41

Join our Telegram chat. 00:41 We are introducing our speaker. 00:47 Our first speaker is Kaushik Gopal. 00:47 He is Senior developer and engineer at Instacart. 00:50 He is going to talk about Refactoring. 00:50 Those who will ask the best questions from the audience will get a T-shirt. 01:01 Let's start. 01:01 My name is Kaushik. 01:11 I worked as an Android developer, 01:11 I've been told I speak extremely fast. 01:13

So I'm going to try and slow down as much as I can, 01:16 but if I'm going too fast just raise your hands and just tell me to slow down and I'll try to slow down. 01:19 Today I'd like to talk to you about unidirectional state flow patterns. 01:25 Now I like unidirectional state flow patterns. 01:30 So I might get a little excited and start to speak fast, 01:33 but again stop me, if I'm going very fast. 01:36

This is very difficult to even pronounce uni-directional state flow pattern, 01:39 it's complicated and it's a mouthful but it's not a new pattern. 01:44 I worked with the Web Development World Redux 01:44 very famously used this pattern and they popularized this pattern where they force all your state to go through a unit direction. 01:52 Now even in the mobile development world, 02:02 you have big companies like AirB&B, 02:05 Spotify. 02:08

They have come up with frameworks like Mavericks Mobius and a lot of different libraries and frameworks that, 02:08 achieve the same thing. 02:15 Now my problem is, 02:15 I'm not as smart as all these other people. 02:18 So I wanted to understand how can I use this pattern in my existing framework. 02:21 How many of you have heard of MVVM show of hands? 02:27 Do you know what NVM is so it's model? 02:31

It's a model ViewModel this is a pattern that most mobile applications today use and it's a pretty common pattern right. 02:34 I wanted to see can I take this MVVM pattern 02:42 and start refactoring it just a little start changing things now and then to get to a unidirectional Stateflow. 02:45

Because of this unidirectional Stateflow, 02:52 the concept itself is very difficult to sort of understand so I didn't want to learn the concepts, 02:55 then learn a library, then go back to my application at Instacart and change everything that's just like too much for me. 03:01 So what I try to do with this talk is take the MVVM pattern and slowly start to move things around. 03:09 So I can get to a unidirectional state flow pattern. 03:16

Before we start, 03:16 I just want a quick show of hands. 03:20 How many of you have used RX Java? 03:22 Yeah, there you go. 03:25 So the thing with RX Java is you don't need 03:25 RX Java to implement this pattern. 03:30 But it makes things easy, 03:32 thankfully. 03:34 I don't have to explain what RX Java is 'cause a whole bunch of you have used it already. 03:34 But the idea is converting everything to an observable or a stream of events make this pattern easy as we will start to see. 03:40

I'm going to be 03:40 using a lot of RX. 03:50 But before that, for this talk, I built a sample 03:51 application so it's a movie search app. 03:56 I have it running on my emulator, 03:58 but we try to work. 04:01 But it didn't work as well. 04:02 So instead what I'm going to do is I have some demo videos. 04:03 The first thing that we're going to see. 04:03 If you see, 04:03 there are 3 functionality is that I built into this app. 04:11 The first is very basic search functionality. 04:14

So I type the name of a movie. 04:17 I type the movie Blade Runner 2049, 04:19 I hit search. 04:21 What happens here is it's making a network request to this API called OMDB API. 04:21 It's a wonderful API. 04:21 It's free, so I highly encourage you to use 04:21 it with an API token and that's basically what I'm doing in the first piece of functionality. 04:31 So as you can see here. 04:31 I type a search type. 04:39 My movie title. 04:40 I hit search. 04:40

We make a network request and then we show 04:42 those results in the search result 04:45 view, nothing complicated. 04:47 So far pretty straightforward right. 04:47 I also have a second 04:51 functionality here. 04:52 Let me try to pause it, so it's not very distracting, 04:52 OK, the second piece of functionality is 04:57 I click the search results view and it adds to the bottom of a history list 05:00 view so it's almost like adding to the history. 05:05

So if you see in this second state, if I click 05:09 this poster image here clicking on the poster image will add it to the bottom in a history list 05:12 view. 05:18 So that's the second piece of functionality again 05:18 not too complicated. 05:22 It's pretty basic right now, 05:22 we go to the last bit of functionality. 05:25 Oh, I think I skipped it. 05:29 Let's see if I can get this running so the last bit of functionality is the reverse. 05:30 Give me a second I'm going to pause this. 05:38

I just explained the last one so in the last bit of functionality. 05:40 If you click, the histories result from view it will add it back into the search results so let me see if I can get that to work. 05:45 Up there, we go OK, 05:56 so if you see the last result you click on any of the history result fuses at the bottom populates it back into the search result 05:57 view. 06:05 So altogether not very complicated. 06:05

Right if you step back and think about, by the way, who've seen the movie Blade Runner 2 foreigner? 06:07 It's a brilliant way. 06:13 Even if you get nothing from this talk if you haven't seen this movie should go see this movie that itself will make your talk worth it. 06:13 . 06:21

It's a great movie, 06:21 I highly recommend it, but the point of this application is I wanted to build 06:23 a simple app that has some interesting state management right so it's not a stupid hello world application, 06:27 but it's also not very complex right. 06:33

I wanted to get an app, 06:35 that does some interesting things and the objective with this stock is I'm going to take this application and I'm going to see how we would build this application with 06:37 a unidirectional state flow pattern. 06:46 OK so this is what the activity looks like, by the way, the code for this sample application is available online completely open-source free you can do whatever you 06:49 want with it don't worry about it. 06:58

At the end 06:58 I have a slide for my resources, 07:01 and I'll point you to the GitHub link. 07:03 So you can feel free to look at the app and see all the different things that we talk about today. 07:05 So this is basically what the screen looks like right so I have an activity and if you see this is very similar to the movie search functionality up top, 07:12 I have the search bar. 07:20 I have the search results 07:21 view in the middle and finally at the bottom. 07:23

I have a history list 07:25 view right now. 07:26 If I were to build this in MVVM, 07:26 how would I do this? 07:29 We do not get moving to unidirectional Stateflow. 07:29 I want to quickly see why I would even bother with unidirectional state flow. 07:33 So let's look at this if I built 07:37 it with the MVVM. 07:39 I have a view model class. 07:39 Anytime I enter my search text, 07:42 it calls a method in my view model. 07:44

I'm calling it on search movie, 07:46 so you search the movie, 07:48 it places a network request, 07:50 it gets populated down as the search result and then it shows. 07:51 Nothing too complicated so far pretty straightforward. 07:56 The same thing happens also with the add to the history event. 07:56 So I clicked that poster image. 08:03 It calls a method on add to history in my new model and it sends down a search history result again nothing too complicated. 08:05

So far pretty straightforward. 08:12 And lastly 08:12 it's the reverse of this so I clicked. 08:15 The history result view it calls a method on restore from history and it sends down a result back into the search result view. 08:17 Alright so individually none of this seems complicated right if I built this in MVVM, 08:26 it doesn't seem like it would be too bad. 08:31 But where it gets a little tricky is if I step back as a developer and I start to see the different events. 08:33

This is a simple search app. 08:40 And already you can see, 08:41 there's a lot of crisscrossing between these events right. 08:43 What I wanted to do is this is a simple movie search app but I work at my company Instacart and what I did is I took a single screen 08:47 from our app. 08:55 So this is our dashboard app. 08:55 And I tried to do the same thing where I map 08:58 the different events. 09:01 I didn't even finish the whole screen and it got complicated right. 09:03 This is pure MVVM. 09:08

This is as the experts recommend MVVM pattern implemented, 09:08 but it gets complicated because if a user calls me and says. 09:12 Hey, I have a bug in my app. 09:17 It gets very difficult because I don't even if you see, 09:18 some lines update the same view in my Android view and the events come from 3 different places. 09:22 This can get complicated in big apps. 09:29 This is one problem that the unidirectional state flow pattern hopes to solve. 09:32

The other big problem with besides state handling is debugging. 09:32 If someone reports an error. 09:42 I want an easy way to find out. 09:44 What event was launched? 09:46 What result 09:46 was caused as part of the event? 09:48 And finally testing. 09:48 All developers love to talk about testing, 09:52 but nobody writes tests. 09:54 That's like the truth of it. 09:56 So if you talk to anyone they are like testing is great, 09:56 you should be writing an espresso test you should be writing unit tests. 10:00

But if you open up their code base and ask them how many tests have written you don't have too many tests but this isn't you can't blame 10:04 developers for this. 10:11 It's because if you make tests easy to write people will write tests if you make tests hard to write nobody's going to write the test. 10:11 I don't write tests if they're hard to write. 10:19

The other thing that this pattern uni-directional state flow 10:19 helps is it makes testing easy and we're going to see how that works. 10:24 So this is what the movie search app 10:30 looks like in terms of MVVM. 10:32 What the unit 10:32 directional state flow pattern tells us is instead of this, 10:35 I'm going to take all my events. 10:39 I'm going to group them into one stream and I'm going to send them into the view model. 10:41

The view model will process each of these events individually. 10:48 It will send the results back into a pipe. 10:52 And this is sent as an RX Java observable towards the end of the view state. 10:56 This is the unidirectional state flow pattern. 10:56 Any questions? 10:56 No, I'm kidding, they're going to talk about the code we have to write all the code to do this so we're going to get to that in 11:08 a minute. 11:16

But what I want you do understand is the analogy that I think about is like security gates. 11:16 Like Russia has been very nice to me, 11:16 but when I came into the airport, 11:24 I was asked at the security gate to show my passport. 11:26 I think of the analogy in the same way so with the unidirectional state flow pattern. 11:30 If you want to know if Kaushik entered Russia or not the best place to check. 11:35 If coaches entered Russia or not is to go to the security gate. 11:39

'Cause anyone who travels in a plane goes through a security gate. 11:44 Question. 11:51 Exactly so it is, it's very similar to the same thing. 11:55 So that's like an equivalent analogy redux if you hear of the same concept as they apply 11:55 the same approach. 12:05 So my objective is to try and see if we can use this an Android use the same concepts in Android. 12:05

So that's the analogy and the advantage of forcing it through the same stream is because it makes debugging easy if you ask me what events were caused in my 12:13 app. 12:23 I all I have to do, 12:23 I just have to look at 12:24 this point, let me see where my mouse is there, 12:26 we go. 12:29 Well, you see that top pipe there if any event is launched. 12:29 I know that's where is going to come through. 12:33 If the user tried to do anything funny in my app? 12:33 Where do I look? 12:39

I just look at that pipe of that and it will? 12:39 Tell me what event came in. 12:43 In the other front, If I want to find out what was shown on the screen 12:43 all I have to do is look at the bottom pipe because any output any view state is only in 1 single place. 12:49 So if you compare this MVVM those 12:49 a lot of crisscrossing here and there, 12:57 but in this pattern, it's all forced through 12:59 in one pipe. 13:02

So that is the overarching sort of like the idea of unidirectional Stateflow, 13:02 but before like in this presentation 13:09 I'm going to be using a lot of terms, 13:12 so I want you to get familiar with these terms. 13:14 Anytime 13:14 I say events what I mean is from the activity anytime user 13:19 inputs are made as if I search text, 13:24 if I click 13:26 the history result view, if I click the search results. 13:28

All of these 13:28 are sent as events into my view model so if I say if I keep saying events. 13:34 This is what I mean. 13:38 And we look at how to generate or build these events in a short while. 13:38 The next aspect is 13:45 so I have my user inputs. 13:46 These are events. 13:48 Now I need to convert those events into results because the user wants me to do something. 13:48

So I'll take those events and I'll convert those into like results now in the common were like people call these use cases, 13:55 which is basically for business logic. 14:02 You have given input and you get an output so this is what they also call use cases and we'll get to that in a second. 14:05 But if I say results. 14:12 This is what I mean, 14:13 I mean, the events that were taken and 14:14 transformed into results. 14:16 And lastly, we have view state. 14:16

This is probably the most important part of this pattern. 14:21 The idea with view state is 14:25 I want a single object that maps to all the fields in my activity screen. 14:26 If I give you a view state object, 14:26 you should just be able to look at that 14:33 view state object and tell what should be displayed in my activity screen and we're going to go into code so it will make more sense 14:35 what I mean by that. 14:43

But just remember when I keep talking about view state, 14:45 this is what I mean. 14:48 So you have inputs that come into the events. 14:49 These get transformed into results. 14:52 Results get transformed into a view 14:52 state and the view state is sent back into the activity. 14:56 So these are the terms 15:00 I'm going to be using pretty frequently. 15:02 All right, so let's go back to what the view state looks like. 15:05 Now I'm going to go in reverse. 15:09

Usually, when I refactor stuff, 15:11 the way I like to think about is what is my output then go to the input and then worry about all the things in between. 15:12 So even when 15:12 I build this pattern, I'm going to try and use the same approach. 15:20 We're going to talk about what this view state is looking at what the output is and then we're going to trace back and see how I can reach this 15:24 point in my application. 15:32 All right, 15:32 so what is the view state look like? 15:35

This is my activity and in Kotlin. 15:37 How many Kotlin users here? 15:39 Thank you. 15:41 Hopefully, all of you are using Kotlin if you're not using Kotlin forget 15:41 Uni directional Stateflow first go learn Kotlin. 15:46 Kotlin is just amazing. 15:49 So I'm using a data class here and with data cloud in this data class its view 15:49 state object and the idea is 15:56 I want every term in my view, 15:58 state object every property in my view, 15:59 state object to map to what I see in this screen. 16:02

So if you see the first thing is the search box text. 16:05 So if I give you a view state object, 16:05 you should look at the search box text and say. 16:10 My edit text view in my activity should have 16:13 that search box text. 16:15 So that's what it maps do. 16:15 In the same fashion 16:15 I have a movie title and that will be in this search result 16:19 view. 16:23 I have a movie rating. 16:23

The movie poster I send down an image URL and I use the image loading library glide you see this in the code. 16:24 So I sent down the 16:24 poster URL and I set it on the image view. 16:34 And now I got a little lazy so within Android for Android developers typically when you have a list view 16:37 it's driven by adapters. 16:43 If I'm being a good developer, 16:43 if I'm not being lazy, what I really should do is send a list of not the movie objects. 16:46

But just what you see on screen because that's basically what the view state is 16:51 But I became lazy and I just sent the movie objects and I let the list 16:56 view deal with rendering these views. 17:00 So if you go back to the repository and look at the code you'll notice that I send the movie object. 17:00 But what you should be doing is sending another view state kind of object that shows just what you see on the screen. 17:08

Alright so that's what it is that's the data class object what I'm quickly going to do is this view state is sent from the view model to the activity 17:16 right So what is the activity do with this? 17:24 It's the same thing that we talked about is very similar binding logic so VS is my view, 17:26 state that's being generated. 17:31 I look at the search box. 17:31 Edit text view. 17:34 I set the text on that. 17:34 The movie titled the rating so this is if you look at the code. 17:36

This is very standard stuff. 17:39 This is what we just talked about. 17:41 I also use glide here as I mentioned you can use Picasso. 17:43 You can use many of the utilities and this is the adapter where I set the list. 17:46 So far like pretty straightforward right. 17:50 There's only one thing that I want to point out now. 17:53 I'm not sending a single view state object. 17:56 I'm converting that to an observable of view state so it has to be a stream. 17:59 Why is that? 18:03

It's because I have multiple events coming in. 18:03 So I'm not going to keep sending just one view 18:07 state object. 18:10 What I want is an observable of view state that gets sent from the view model to the activity. 18:10 And the idea is basically since you have multiple events coming in you want to bind this. 18:16 So do 18:16 I need RX Java for like an observable? 18:22 I don't need RX Java if you've used Google's live data and data binding that might work in this process, 18:24 too. 18:31

But the idea is I have a view state. 18:31 I want to bind this to my activity and I'm doing that in an observer so that it starts listening to any update. 18:33 So anytime 18:33 I send any difference in the view state, 18:41 it just binds to that and it updates the view 18:44 automatically so that's by enlarging the process here. 18:47 So the return type is an observable of a movie View State. 18:50

And again if you're talking about naming is one of the hardest things for most developers coming up with a good name is like impossible. 18:55 Even these names. 19:02 I don't know if there are good names, 19:02 but I just came up with these. 19:04 Wars have been waged. 19:06 People have quit companies because they couldn't come with like proper naming so I chose this name, 19:06 so don't get too worried about it. 19:14 But I call it rendered. 19:16

This method is called rendered and it's in the ViewModel, 19:16 so the activity will call this method directly and if you're familiar with how RX Java works. 19:21 You subscribe to this observable and then you have the same code that we talked about so if you look at the GitHub repository and look at the movie 19:27 app. 19:36 This is what you'll see. 19:36 I have my observable that's returning of View state. 19:38 I'm doing the binding so far, 19:41 so good. 19:43 This is so far. 19:44

I want to take a quick point. 19:46 You know how I said testing has become easy now? 19:46 This is why testing is easy, 19:51 because if I look at my activity code all the activity is super dumb now. 19:53 All it does is look at the view 19:59 state and it binds. 20:01 I'm just taking my Android views and I'm setting it based on what I see in the view state. 20:04 So in production, 20:04 if I have this, all I have to do is just write a single UI 20:11 test. 20:15

How many of you have used espresso for your UI testing? 20:15 Not as many hands. 20:19 So you are either not writing tests or you're not writing espresso tests. 20:19 So in any case, 20:19 if you use UI instrumentation tests espresso just tests to see what you see in the view. 20:25

As Android developers the problem is these you have to run 20:25 these in multiple devices as well because you can't just run it on one device and say, 20:34 I'm done because you have 20:38 Samsung you have me Mi. 20:40 I don't know if you in Russia 20:40 have different phones as well. 20:43 Each of them implement the Android operating system differently, 20:44 which means you can just write a thing. 20:48 You have to run these tests 20:48 on multiple devices. 20:51 So if you think about 100 20:51 UI tests. 20:54

That's pretty problematic. 20:54 But in this pattern, all I'm doing is an interesting set text 20:57 view. 21:00 Google already has engineers testing to see if you know the set text 21:00 view works or not. 21:04 I don't have to worry too much about it all. 21:04 I have to care about is this view state is it being linked to the correct field in my activity, 21:07 so that's just a matter point on why testing is made a little easy. 21:12

That's pretty much it so that's the first step right so this is the output the view state. 21:18 Now what I'm going to do is I'm going to step back and look at the events portion. 21:24 So I told you in general in refactoring 21:24 it's good to see the output then look at the inputs right so don't worry about what comes in between. 21:31 Let's look at the inputs now. 21:36 How do I generate these events? 21:38 We are going to quickly take a look at this. 21:38

So if you look at the movie search up. 21:43 I told you like it would be nice to take all these events and put them into like a single observable that gets sent into the ViewModel, 21:45 So what exactly are events? 21:55 Events are objects that are sent into the view model that is triggered by user inputs, 21:57 So what does that mean? 22:03 If I enter a search if I enter the text in my search box 22:03 I don't want to send a string into my view 22:07 model. 22:10

Because that could change later on. 22:10 What I want to do is I want to create a wrapper object. 22:10 I want to create an event object, 22:16 you all know what events mean now. 22:18 I want to create a custom event and I want to send that into my view 22:20 model. 22:24 I would maybe create like a search movie event for example. 22:24 Let's take the example that I talked about. 22:29 Assuming I entered the search text Blade Runner 2049 22:29 with the edit text view. 22:36

I can just call dot text to string and I can pluck the string content 22:38 from there, but I don't want to send the string into my viewer ViewModel. 22:42 Instead 22:42 I'm creating this new object called a search movie event. 22:47 This search movie event is again. 22:51 If you've used sealed classes in Kotlin, 22:54 I'm using a sealed class here. 22:57 It doesn't have to be assailed class. 22:59 It can also just be an abstract class. 23:01 The point 23:01 I want to stress here is this. 23:05

Search movie event should be of the same type of movie event. 23:06 They should have the same base class. 23:10 Why do they need to have the same base class? 23:12 You seen the next step. 23:12 If I want to merge these into the same stream, 23:16 they have to be of the same type. 23:19 I can't just simply use any base type right so that's why I'm extending from the same base class called movie event. 23:21 Again if you look at the RX 23:21 in Java world. 23:30

I'm going to send these search movie event into this ViewModel, 23:30 but before we do that. 23:35 Have you used RX bindings? 23:37 How many of you have used RX bindings? 23:38 Yeah, Jake Wharton built this 23:40 sort of library. 23:43 The idea is you can take Android views and you can transform them into observables. 23:43 So I'm using the same thing here. 23:48 I have RX view that listens to the click on search buttons. 23:50 Anytime you click the search button, 23:54 I use a map operator. 23:56

I'm creating this event object that I talked about and I'm sending this search string inside right again. 23:57 So very straightforward if you look at the code again. 24:03 It will also show you how I create 24:06 the other event stream, so I have added to the history and restore as well. 24:07 The point, though, is don't get too caught up on how the implementation 24:12 details work just yet. 24:15 You can go back and look at it in the repository. 24:15

Right now, 24:15 what I would like is if you understand what we're trying to do here. 24:19 And what we're trying to do is we're trying to take the input events, 24:19 converting them into observable streams and I'm going to send this stream into the view model. 24:26 So that's the objective here. 24:26 But if you remember, I told you the whole security gate analogy right. 24:33 I want all of these to go in the same view. 24:37 How do I do this? 24:37

RX Java gives me observer dot merge and I can just merge 24:37 these input streams. 24:44 If you know how the merge operated works. 24:44 It won't allow me to do it if they're different event types. 24:48 That's why I stressed they have to be of the same base class is because you can now RX server allows you to do this so you can just merge 24:52 all of these and send them into the view model. 25:00 So that's pretty much what you would see so if you look at the code. 25:04

It just has these events, 25:09 the activity generates these observable events. 25:11 This is sent into the view model and so the ViewModel now takes as a parameter. 25:15 This observable of events, so that's the input stuff. 25:20 Now I want to do a quick recap as to what we have done so far. 25:25 We talked about the output. 25:28 That's The Observer of the view state. 25:30

We talked about the input now, 25:32 which is the events and that sends an observable so I have an absorber coming out. 25:33 I have an observer going into the ViewModel. 25:37 Now, 25:37 we have to do this is where the interesting stuff happens. 25:40 Now I'm going to convert the events to the results. 25:43 That's the first part and then I have to take the results and convert them into the view state. 25:46 How is everyone feeling so far making sense? 25:51 You want to get up and stretch? 25:54

We just have 2 more steps so if you want to feel like you're going to stretch or something is a good time 25:54 to do it. 25:59 Alright so let's focus on how I convert the events into the results. 25:59 We all know what events means we all know what results means. 26:05 Now you want to think I'm a little crazy because what I'm going to do is I have a single stream of events right. 26:10 I sent this into the view model and it's a single observable of events. 26:17

If you notice I've merged those streams together, 26:22 but what I want to do is I'm going to split the streams again. 26:25 I'm not crazy. 26:30 I'll tell you why I'm doing this in a quick second. 26:30 So I have use cases right if I'm writing my business logic and I'm 26:30 writing an application. 26:38 If I give you a search event. 26:38 I want to search result. 26:42 I don't want to go. 26:42

Cackle comments for the website

Buy this talk

Access to the talk “Unidirectional State Flow Patterns — a Refactoring Story”
Available
In cart
Free
Free
Free
Free
Free
Free

Video

Get access to all videos “MBLTdev 18 EN”
Available
In cart
6 900 ₽
6 900 ₽
$104
$104
€ 92
€ 92
Ticket

Interested in topic “IT”?

You might be interested in videos from this event

September 28 2018
Moscow
16
122
app store, apps, development, google play, mobile, soft

Similar talks

Laura Morinigo
Chief Innovation Officer, Google Developers Expert at DMod Labs
Available
In cart
690 ₽
690 ₽
$11
$11
€ 10
€ 10
Mihail Funikov
Android Developer at e-Legion
Available
In cart
690 ₽
690 ₽
$11
$11
€ 10
€ 10
Evgeniy Zubkov
Android-разработчик at Revolut
Available
In cart
690 ₽
690 ₽
$11
$11
€ 10
€ 10

Buy this video

Video

Access to the talk “Unidirectional State Flow Patterns — a Refactoring Story”
Available
In cart
Free
Free
Free
Free
Free
Free

Conference Cast

With ConferenceCast.tv, you get access to our library of the world's best conference talks.

Conference Cast
505 conferences
19653 speakers
7164 hours of content