Charles: Hey everybody and welcome to Episode 110 of the Adventures in Angular show. this week on our panel we have Lukas Ruebbelke.
Charles: Ward Bell
Ward: Hello everybody.
Charles: I’m Charles Max Wood from Devchat.tv and this week we have a special guest and that’s Nate Murray.
Nate: Hey, everybody.
Charles: Nate, I know you from the emails I get about NG Book, are there other things that we should mention when we introduce you?
Nate: Yeah. No, NG book is our main dig right now, I’m the co-founder of fullstack.io so we wrote the original NG book and then over the last year we’ve been working on NG book 2 and then we’ve been venturing out a little bit more, we even started a book on react this year.
Lukas and I are actually working on a new book, a new top secret book that’s about doing modern Angular 1.0. A lot of teams are still stuck on Angular 1.0 and how do you use what you’ve learned in Angular 2.0 and in React and back with that to Angular 1.0. Some of that includes Redux, actually. That’s what we’re working on.
Charles: Very cool. Well, we brought you on because I read this article, it was actually a tutorial building Redux in typescript with Angular 2.0. Anyway, we’ve had a little bit of back and forth here about whether or not this is a good idea or at least how useful it is and so I’m a little bit curious myself just from the standpoint of where you see Redux fitting in with Angular 2.0 because Angular 2.0 for me, well Angular in general, is mostly about the interactions that the user has with the page. I wind up putting in my own stuff that for example gets data from the back end and things like that.
It looks like Redux can do some of that stuff but also the idea of reducers and functions that manage state is really interesting. I’m not familiar enough with that to go, “Oh it’s a slam dunk here.”
Nate: Yeah. I think there are definitely things that you get around the edges that are difficult with Redux. Sometimes like server interaction, you have to put in things like Redux thunk core. There are definitely things on the edges that are tricky but I think one of the benefits that you get is it’s very understandable especially with one way data flow, you can really trace changes down through the system.
There’s a big win there in being able to have a system where you can create an event and then trace through everywhere that that’s handled and the state that it affects in your system.
Ward: You know, I keep hearing that. I’ve been a programmer for a while and my boss never came to me and said, “I really want to be able to trace the data flow.” I just don’t know why that’s important so maybe you can tell us why that’s important.
Nate: It’s not necessarily that I would defend Redux as the end all be all of all data architecture paradigms but I think that it grew out of a response. For instance like two way data binding I think is an idea that its time has come and gone. The idea is well, we’ve got our views that show our views and we just manipulate our data in our controllers for instance in Angular 1.0 or in our services and then we just change the data on our code side and our templates will automatically be updated and then our forms will update our data and that will automatically update our backend and then everything will just work for us automatically.
That sounds really nice in theory, I think one of the things you find with two way data binding is just that you end up with a rat’s nest of this cascading side effects that as your app grows, it’s really difficult to trace back like tracing what changes when you submit that form or when you press that button becomes extremely difficult.
Ward: Really? I keep hearing that, Nate. I keep hearing that as an assertion. When you say its time has come and gone, that’s like saying breathing, the time for breathing has come and gone, we got to just inhale and forget about exhale. What’s the experience that you have that was useful to this problem that I’ve gone through, let’s not think it as a problem.
When you have, say, typescript and you say this variable is absolutely going to be a string, then that gives you a certain benefit, a compile time. I think with Redux what you get is an expectation across your team around this is how we do changes in our app and this is how we mutate state in our app is that. You instill your team with this culture that we’re not going to mutate our objects, we’re going to create a copy of this object with a new value in place.
Exactly what I mean by that, in Redux, what you’ll often do is if you say you have an object that has keys. You won’t necessarily say, “Okay, on this original object, I’m going to set the key to a new value.” You actually clone the object and then set the key to a new value on this new object. There is a certain freedom that you get in not having to make those decisions all the time about is it safe to mutate this object or not, you just know. We always return a new copy of the state. I think that that sort of constraint can be useful.
Ward: Tell me how it’s made a difference in the apps that you worked on.
Nate: Sure. I’ve used two way data binding and I find it, if you find that maintainable and you haven’t gotten to a situation where you find two way data binding to be cumbersome, then I don’t know. I guess, Lukas, you’re also a person who has used Redux, have you found yourself on apps where you find two way data binding results in a rat’s nest, cascading of changes that are difficult to trace through the system?
Lukas: I think two way data binding is really the wrong thing to zero in on. I think rather you have to look at the real underlying problem which is complexity. One of the biggest problems with complexity is state and especially when you have shared mutable states.
For instance if you have an object that’s being shared by two controllers, it’s coming from a service but two controllers have the ability to mutate that state or that object when they have a problem because if you change it in one place, how do you guarantee that it’s not going to explode in the other place like there’s no way to put any constraints over something that is in a sibling component.
Generally, what you have to do then is something like defensive copying, in other words, okay, I’ve created a copy local to my controller and I’ve made a change but now I need to find some way to communicate this back up. The service can then let every other piece within my application that knows about this update to the latest.
I found that not only with state creates complexity and so for every piece of mutable state that you now have to consider the permutations that your application can end up in but you also have to consider really the control flow of your application. In other words, if I modified this before I mutate this, is this going to break my application? This is for instance why we have initialization like life cycle hooks in our components because there’s things that you cannot do until a certain predetermined time.
By introducing one or focusing on or being cognizant of control flow is well seemed on the state of moving parts you have. For me, what Redux brings to the table is a way to simplify those.
For instance, instead of having state in multiple places, it’s in a single place that then gets propagated through my application. With Angular 2.0, that’s really easy thanks to observables. You just essentially subscribe to an observable and when something changes, it pushes those changes through your application.
But to answer Ward’s question about is it really simpler, I think that the analogy would be it’s much simpler to cross a one way street than a two way street. In other words, if I know that data is always coming from one direction and I don’t have to worry about any control flow in any other direction then it’s a lot easier to reason that it’s about always coming from parent to child.
For me, it’s about reducing complexity by reducing the amount of state in your application but also simplifying the control flow in the sense that it’s always in one direction and that is how data always flows, top to bottom.
Nate: Yeah. I think part of that conflict too comes at a high level around these ideas between object oriented versus functional programming. There’s a deep worldview tied into one way or the other. Someone who likes Redux probably is a fan of functional programming in a really deep way.
When you have an object for instance, all of the state that’s encapsulated with those objects, if you pass an object in as an argument and that object has five instance variables, it’s really as if you have a function that’s taking five arguments, not just one.
When you encapsulate state in objects, you’re spreading state throughout your system and those objects themselves can also change which means when you pass an object into a system, you’re passing more arguments than it seems like at first blush. Whereas when you have functional systems you say, “The output of this function is deterministic and the output of this function is always the result of this. When you have a pure function, the result of pure function is always the same output given the same inputs.”
By not hiding away any state or any extra parameters either way in objects or in other places of your system, you get more predictability because pure functions are very predictable because you know all the inputs and you know that the output will always be the same every time you call it with the same inputs.
Lukas: Let me give you an example. For instance if you have a method and that relies on some other internal state, do you have a method that does something if one thing happens or something else happens? How do you test that in isolation? What is going to be the result of that method? Well, you don’t know because it depends on some other piece of internal state.
Now, you have to factor in what is the two possible permutations that this exists and now what happens if you have yet even another piece of internal state that you need to factor, now you have even more permutations that you have to consider.
This is the struggle with object oriented programming in mixing state with functionality is that it makes it really hard to reason with the output of a method, thus making it hard to test. With unit test, it’s slightly deceptive because what we’re doing a lot of times is resetting the state and or before each block and really kind of controlling this in a vacuum.
Every time we run a unit test, we clear the desk and set new state for it and it works like we expect because we’ve controlled the state. But then once you will put it out into the wild, you cannot guarantee that the users are not going to get it into a state that you have not taken into account which is why a lot of times when something goes wrong, our first response is, “Hey this thing broke, well can you refresh the page or restart your computer,” is essential.
What we’re doing is we’re clearing a state and so therefore I think that’s where, even having these deterministic constructs and application where it’s like I put one thing in and I’m always going to get the same thing out. How you accomplish that is by reducing internal state which this is not a Redux thing but having container presentational components or components that relieve our state list on the inside is you know that if I put something in, this is going to happen and there’s not any kind of internal state to introduce any variables within that.
I think really having referential transparency within your test and everything that is deterministic and that you put one thing in and you’re always going to get, you can expect something else to get out every single time. I think outside of Redux, I think that’s really, really important for writing stable systems. I think moving to immutable, pure functions, paradigm really facilitates that.
Ward: As a practical matter, you do have state, it’s the state of, let’s get concrete. Let’s say we have a person who has a first name and last name and a social security number. It’ll be so much easier to talk about it that way. We get that out of the store in Redux, the controller that’s going to present that thing gets it, makes the call to some service, gets the thing. Now, it’s got an object and it’s got to put it on the screen. Am I good so far?
Ward: Alright. I’m not allowed to change that thing. I effectively make a copy of it because I know that the user, it’s a form now, they’re going to change the first name, the last name or the social security number. By the way, this object has no intrinsic business rules. Am I right? It’s just a data bank, for the most part.
Nate: Yes. There’s certain patterns around forms where it depends on if you want to fire the event on key change or whether you want to fire the form being changed on submit affects the design pattern but go ahead, continue with your example.
Ward: I want you to stop me. I’ve got an object out of the store because I asked for it. I’ve got to present it in such a way that the user can type the keystrokes. Obviously when they type the keystrokes, I’m not going to use data binding to update the object because I’m not allowed to do that so I have to capture it in some intermediate object. Is that a fair statement?
Ward: It’s usually effectively the control model, the model that’s actually interacting with the widgets on the screen. The user does whatever the user does and I had better have some controller logic that decides when the user is done doing whatever the user’s done and it’s time to call this an update, is that a fair statement?
Nate: That’s right, yup.
Ward: Right. By the way, do I have any business rules that are providing on form validation at this time? And if so, where do they come from? Because there’s this object that I got that has no notion of being an entity. See in classic, my old faddy daddy way, we actually had entity objects we just intertwined in entity, and that object was the entity had business roles associated with it.
They governed its own validations so it knew what it could and couldn’t do. That whole logic, all that reasoning about what you could and couldn’t do was part of what it meant to be a person in this system because we are talking about a person object.
For example, if I tried it knew that the first name was required, was it going to let that not happen? Anyway, I got some rules, I presume that I can’t have that so I have to get my validation rules from somewhere. I don’t get them from the store, do I?
Nate: Sure. No, but you’d still have a class that was around what business logic applies to your person object. You would just pass values, you would pass the set of properties that can make up this person, you’d pass that into a function that says, “Is this about a person, why or why not?” You’d still have that for sure.
Ward: Okay. But the thing that they’re mutating is a copy of my object, is that right? My object, the one I got from the store.
Lukas: You’re going to want to isolate. Mutable state, there’s nothing wrong with it. You have to have mutable state in other words to for users to do meaningful things. What you do not want is shared mutable state. In this case, you’d have the form data, the users, everything, the form data which would be separate from the user object.
Ward: Right. The user, the object, the person object that came in was the source of truth and I projected that onto the form in some way. The users making their changes into this temporary mutable thing that nobody else sees and now it’s time to do something, by the way this is actually what’s going on in two way data binding too.
Just as it’s affected, it gets back to the other. What happens is when the values that the user enters go back somewhere. But here, in the Redux world, those values do not go back, they instead are shipped in a kind of a message to the store. Is that a fair statement?
Nate: Yes. You form an action from the new value that formed.
Ward: Yeah. That’s called a message in traditional programming speech.
Nate: Yeah. In Redux you would create an action in Redux parlance and you would file that off to the reducer and the reducer is what would take the action plus the old state and then update the store.
Ward: Now this is all happening synchronously at this point, correct? The object goes to the store, it’s then manipulated by what they call producers and the result of that is an update to the store and a returned object because we haven’t mutated the old app to get a new object back. Is that right? The new person.
Nate: That’s correct.
Ward: Now, I must flow that back onto the screen, discarding my old one, put the new one and reset the form and the RAM, they go. Is that right?
Nate: Sounds about right.
Ward: Okay. That’s the basic pattern that we’re getting across. I can see that. Now, how does everybody who’s interested in that particular person, let’s call him Lukas, how or when does everybody find out about the fact that Lukas has changed?
Nate: Well, you’re subscribed to the store and the minute that the reducer returns a new value, that is then propagated to everybody that has a reference to that particular item in the application store. In the case of NGRX store, it is an observable that gets pushed out to everybody.
Ward: We have another view on that, that’s just the list of the people, it’s kind of just master detail thing that we’ve got so we’re making our change in the detail, we have a master list. Does that sound fair?
Ward: I made my change, it went to the store, the store, when I built my lists, I built it as an observable that listing for changes into that list and so the new list comes back at me with the new version of Lukas, is that how it works?
Ward: Everybody is listening to the store and getting an update. Now, when I listen to the store, maybe I’ve got a filter on it. They’re actually interested only in the people who work in the print department and Lukas doesn’t work in the print department, they’re still gonna hear the message right?
Nate: That’s right.
Ward: And they have to filter it out again.
Ward: Because this is an enterprise app, they’ve got a thousand things on the screen and they have to filter that each time because the list got updated.
Nate: Yeah. Of course. There’s certainly other ways that maybe you could optimize that but yes, in the case you set up for sure.
Ward: Okay. If I’m taking inventory in my head vault with little pieces that go head around and around and around here, let’s contrast that. Let’s contrast that with that old way. I got the Lukas person object and we changed Lukas, his first name to Betty and I just changed the darn property and everybody gets Betty. Suddenly, Lukas is Betty.
I didn’t have to write anything. I didn’t have to write a single line of code to bring that off because the two way data binding is already doing that. I’m trying to figure out just from the start, taking inventory in the complexity that’s involved and going around the circle and we haven’t even introduced a synchrony yet.
I keep listening to this and I keep wondering why that’s simpler. By the way, I haven’t even talked about the nature of the object and whether the object could be constructed in such a way that it was just as observable actually when you made changes as anything else.
Nate: Yeah. I think that there is maybe a case of over prescription in Redux where you find folks using it blindly in cases where it’s unnecessary. The Redux creator, he works for Facebook now, he even talks about on Twitter pretty frequently that if you’re just getting started, if you’re a lone developer, maybe one or two developers, Redux is really made for React and he’s speaking mainly in the react context places.
He says, “If you’re just starting off learning React and you’re just building your first app, you don’t need Redux right out of the gate.” Redux is a tool that is built for teams that have grown outside like one developer who’s keeping everything in his head and like a smaller app. The problems that flex originally and then distilled into Redux were addressing was this idea that we have lots of different components that are all over the page, that are all trying to interact with the same data and we’re getting raised conditions.
I think one of the original motivating apps for flux as I understand it was Facebook Messenger, that you’ve got this chat window and then you’ve got the threads window and then you’ve got the unread messages count. A new message comes in and you’ve got things that need to be updated in all of those components and it’s repeats of the same data. You can’t necessarily just update the user name in the chat window for the object that is in the chat window component because you also have the username in the threads component and you also have the unread count up in the menu bar. If you just change the local object in one window, those aren’t necessarily going to be propagated.
What you need to do is you need to have it read from some outside service and that’s a good strategy. You could have that list of data out in some outside service and then have all of the objects that are like the threads window and chat window can also be watching that list to see if the objects changed for instance.
When you build on that and say, “Well, why do we need to reimplement the data flow for every single service, what if we can structure the data flow in a way that instead of being unique for every different type of service, it’s actually consistent throughout our whole application.” I think that’s how you end up with the Redux flux pattern of this action store dispatcher.
Ward: That is not the only way to roll. We’ve long had services that had cached data that have object identity so that I always knew that Lukas was the Lukas object. Then everybody who wanted the Lukas object got the Lukas object. No matter how many times I read the database to find the Lukas object, whether I look for people by the first letter of L or by the last name R or people who are in the print department, and I query the database and then it came back, it’s an object identity so I’ve always got however I go at it, I got the same Lukas object and anybody who wants to display the Lukas object just gets it from the cached object.
Looking good to me. This is a pretty standard pattern that’s been followed for a long time. The entity would work repository pattern. I’m thinking, where’s my problem? I’m displaying the same Lukas everywhere on three or four different places, I can see Lukas just by following the navigation, a relationship between Lukas and messages. I can see his messages in his messaging window. If those change, that’s all good and they’re still attached to the Lukas object. I’m just sitting here thinking to myself what’s my problem? What is my problem that this is solving?
Nate: I think if you are happy with mutable state, I don’t necessarily know that I can convince you.
Ward: Don’t convince me, convince our audience. You started it, you guys all started this thing by saying that it’s time to give up mutable state and it’s passe and the reason we have to do it is because we all want to get on the functional bandwagon and we’re going to understand something and cure cancer here. I am still waiting for the problem when every time I look, I see the claims to a problem that doesn’t actually exist.
Lukas: I just have to understand here, are you telling me that you see no problem with having shared mutable state like just strolling across your application, that you think it’s totally fine to have across multiple components a single object that everybody is sharing and they’re able to mutate?
Ward: I think that this is true for all systems including Redux. If I’m not careful and I allow two different screens with two different sets of business rules to mutate the Lukas object, there’s a potential for trouble and I don’t care what system it is, I don’t care if it’s Redux or anything else. Somebody has to stand guard. That’s the validation rule and they have to sit in some commonplace.
If you’re asking me whether I would just have a free for all, of course I wouldn’t do that. Do I think that free for all systems exists? Absolutely. But that’s not intrinsic to the architecture of mutable state. It’s intrinsic to bad design. You can do that in Redux too. I can have a gazillion things, I can have multiple screens that are all trying to update the Lukas object and they’re using different and they all send reducer, they all send messages to the store and I ask one wins or whatever. Doesn’t that create some kind of chaos? Isn’t that a potential for chaos?
Lukas: When you say you have multiple screens that are updating what?
Nate: One thing that I think is challenging like, I do think that there are certain challenges in Redux. Starting with the fact that sometimes it feels like you do feel there’s a little bit of ceremony especially when you have smaller apps. Let’s start there. You’ve got to set up your store, you’ve got to set up your actions, you’ve got to set up your reducers.
The first time that I saw a reducer that had 30 case statements in one giant producer function, I was like really, this is the modern state of web design as we have these massive case switch statements. I do think that there’s challenges there, you do wish that you got almost call a function instead of firing an action.
Instead of turning the action into a data object first, there is an aspect of which it would be nice to be just to call a function instead of creating an intermediate action object.
One of the things that I think could be interesting for Lukas and I to talk about is using NGRX. Lukas, you and I have talked a little bit about this offline but maybe we could bring it on here.
Tell me about what you like about NGRX. Just to set the stage, I’m actually a really big fan of pure Redux, I like calling functions on objects and I’m not actually a huge observables fan, I’m a little bit of an outlier where I’m a big fan of Angular 2.0.
I’ve got this book in Angular 2.0 and I actually don’t really love observables, I understand them but I feel like there’s really high barrier to entry. But Lukas on the other hand loves NGRX. Lukas, can you tell us a little bit about what NGRX is and what you like about it?
Lukas: Sure. Let me start out and say one of the things that I like about Redux is that you can write a version of Redux from memory in about ten minutes. First is you take your reducers, there’s something special about that, it’s just a function that take a state object and action object and based on your action type, it will perform some operation in return a new object.
That’s very simple to write and then you need a place to actually store that state and that goes into the store and that’s also very simple to write. Using action creators, there’s a way to abstract out some of that business logic of when this action happens or that this is how we need to prepare the payload to go back into the reducers.
In a sense, I think that just like you explained for instance NBC in about less than ten minutes, I think Redux is a pattern you can also explain fairly easy.
Nate: That’s a super important point too. I think that this idea that flux and Redux are patterns like NBC is so important. I think that the flux pattern is as important as NBC because there are a lot of ways in that regular NBC falls down.
We’re talking about client side web apps that are coupled with the server. I know that I was confused about that early on. I was like what is flux or what is Redux and it is a pattern like you’re saying.
Lukas: To that sense, patterns are good but I will make a concession toward your friend, Ward, is that when you get caught up shoving things into containers or ideas for the sake of doing it. I’ve seen the stem with NBC where you’re trying to basically force it into a NBC pattern because that’s what you’re doing and maybe an NBVM pattern is a better fit. I think Redux for me, it just gives me a pattern and approach to simplify shared state or state in general and control flow which the side effect of that is it really reduces a lot of code that I would’ve written to manage a lot of those things. That’s Redux.
And then, the next question is how do you actually propagate state to your applications. When I change it in one place, how does the rest of the application know? The beauty of observables is that it pushes state to the consumer as new data comes in. It will do it overtime, the promise that resolves only one time and that’s it. Observable will continue to push out data.
To me, that’s really the core beauty of NGRX is that the store is built up on top of observables that I can then basically wrap a surface around subscribed to my data model and I can basically use it right, bind directly to it in my template using the acing pipe.
Now really, my controllers or my component classes become really very small. It’s almost just a pass through where I’m almost using an observable binding directly from the store, write into my component. But on top of that with an observable is you’re always getting a piece of data but then you can transform it using observable operators, RXJS operators, however you see fit.
Not only you can take a single data stream and say, I want to filter out this and I need to do this and maybe I want to debounce or I want to throttle this input, whatever or I want to reduce these results into a single result, you can transform that and prepare that data however you need into your component but then you can also combine streams together.
For instance, using combine latest is you can have two basically data models in your store. Well, let’s say that you have a table of users and a table of events and you want to say, “For this event, these users are attending this.” Now you can say take these two streams, you can combine them together and say, “When either one of these emits a new value, we need to calculate this new observable data and hand it to our view.”
Now, we have some really powerful ways to, in a functional manner, pass or take data from essentially the beginning of assembly line and pass it all the way through to the end and transform it just the way that we need or our components to display.
Again, talking about stores or rather reducers and being this mutable operations, that same pattern applies to observables and you want to also avoid side effects using observables. If you need to do side effects, there’s some ways to do that and there are reasons for that but as a whole, seeing a reducer as pure functions that just modify state, seeing observable methods that also just take and transform data but they’re not mutable operations in so much that Japher, who is saying he wrote a lot the observable stuff has even came out with the pretty awesome gold plugin that will go to your code and actually analyze like these are mutable operations hit and then call those out just like you would do a lint on your project.
That is for me minimizing state, minimizing control flow, and doing it in a safe predictable manner that is easy to test, that one of the biggest side effects of that is I write a lot less code because I’m not having to do defensive copying or trying to manage state or these different particular nuances at a local component level.
Nate: Can you talk a little bit more about what NGRX is and how it works and how it’s different for instance than pure Redux?
Lukas: There’s very little difference. We watched the Dan Abramov videos on GitHub almost doing a dry quote. He watched them, then he watched them again and he wrote NGRX pretty much over the weekend, the only difference is that it uses observables instead of with regular straight Redux, it’s this event passing to facing communicates [0:50:32.2]. I think Ward’s right is here.
Ward: That was my commentary.
Lukas: Rob literally wrote NGRX in a weekend after watching Dan Abramov’s video. Other than the observable piece, it’s pretty comparable in so much that even major pieces of the ecosystem just port right over. That is a pattern and it’s not a strict react thing.
If I need to basically make a service side call, I’ll just do that within a service just in front of it and then on completion then I’ll pass the new state up to the store and then on the other side of any computed values of users and events, then I’ll have another service sitting on the other side of that to compute observables and really apply any kind of business rules or logic to transform my data with that I need.
I might have a user event service that will take users in events and I’m using combined latest handed off. That’s just a straight observable RXJS, that thing at that point.
Ward: Yeah. One of the things I love about NGRX is your reducers pour over pretty much exactly. You can just reuse the same reducer that you are using with the regular Redux.
That’s another thing I like is that it’s a pattern and it’s not a framework thing and you’re abstracting out your business logic into Geneva, Switzerland neutral place that you can import whatever you want.
Ward; Nate, I have a question for you. How in Redux do you flow the changes to back all the screens that want to listen, how do people listen?
Nate: The first step is that you subscribe to the store and. The most naive implementation is you subscribe to any change in the store. If anything changes, then you want to peel out the data that you are listening to and then re-render it on your view.
Of course you don’t always want to listen to, there’s two problems with that. One is just performance wise, you don’t necessarily need to listen to everything that ever changed in your store. The other is that you don’t want the thing that is rendering the view to know about the internal structure of your state. We’re talking about putting almost your entire application state into one giant object at the center of your application.
Handling you to those intern, one is just the performance issue. How do you only be notified of the particular change that you’re interested in? There’s different ways, it depends on what the central data structure is. If you’re using observables, there’s certain ways to peel off just the string that you’re interested there. A lot of folks will use immutable.js which is a very performant way to say, “I only want to know when this particular key changes to fulfill the subscription,” or, “Give me the call back.”
In terms of the problem of knowing about the internal of your state, there’s a pattern that’s part of Redux called selectors. The idea is that a selector takes a tree of state, it’s a function that takes the state as input and then returns the data object that you need for your view.
For instance in this case where we have our user management app and the form needs to show you the first and last name, you wouldn’t want your component, your form component, that shows that form to have to understand the entire internal structure of your central state tray. To bridge that gap, that’s why you create selectors, it’s the pattern that use you Redux. You write a selector that says, “Well, I know how to read the state and I’m gonna read the state and pull an object out and then I’ll give that to the view.”
Ward: Why would you wanna write that by hand? See, this is where I really think that observables do come to the form because it’s an entire language for doing filtering, mapping, selecting, projecting. You don’t have to make up your own way to do it. It’s pretty much what observables are good at.
Nate: Yeah, that’s true, observables are good at it. I think observables are super powerful if you have a team that is willing to take the time to learn. I’m talking about RXJS. If you have a team that is good enough to learn RXJS and they’re willing to put in the the time to learn the top ten or 20 operators that you need to know and they’re willing to stop and learn what is between a hot and cold observable and they can think functionally, RXJS is a very concise way and a very powerful way that you can use to do those operations. I think the challenges with RXJS in particular is that the API and the surface area is so large, there’s so many different functions that it takes time to get into. You have to really want to do it.
Using streams in RXJS also reminds me lot of a similar problem that you run into when you use streams with Node.JS. If you’re trying to use streams everywhere in your Node.JS apps. It feels very similar, you have this pipe that when everything goes through the pipe perfectly, once you get the pipe figured out, it’s beautiful, it’s like a short concise code that everything flows through. As soon as you have any edge case or you want to do a debugging or you start getting like you want to apply that pressure or you have the edge cases that invariably show up. I always find it’s super hard to separate these long train of pipe operators and then really dig in to debug when something goes wrong.
I think that’s one of the pragmatic challenges that I’ve had with observables is, even though I understand them very well, I understand it really, really well and I’m still having a really hard time working with it practically, I’ve done trainings at certain companies where the average level of developers is not at a level where they’re willing to really understand RXJS.
I think that’s a risk for widespread adoption. It doesn’t mean you shouldn’t use it but I just think it’s a difficulty that were going to see with adoption for RXJS more broadly.
Lukas: It’s interesting if I can interject is you can essentially replace Redux with just a few lines of observable code. Dan Abramov actually makes, he admits this somewhere in the official documentation. He said that it’s been said that you can do Redux with RXJS and two line using scan, he said that this is probably true.
Nate: Yeah. The subject. Yeah.
Lukas: He said, you could do that. For me, being in the middle of this is I love observables, I love the power and that it gives you. Once you wrap your mind around streams and how that works in React interfaces, it’s really cool but there are things that I would actually probably prefer to do in observable as opposed to handling that in straight Redux.
For instance, two things coming off of the store, I am going to use RXJS combined latest to perform the data transformation. What I like though is that the operators and the reducers still follows that immutable peer of function pattern and so there’s quite a bit of overlap there in terms of the essence of it.
That’s really important about that. But again, I think one of the issues is the reality is RXJS is really, really hard. I’ve been working on it for almost a year and there’s still times where I’m just like I know there’s an operator to do this. I have no idea what it is and I spent 40 minutes reading through the documentations, getting on the eggheads, slouching, begging for help and it’s really powerful but there’s a steep learning curve whereas I think Redux has a pattern, you can explain that in ten minutes and it’s quite a bit easier to wrap your mind around.
That’s it. I think it also is one, what is the learning curve and where’s one is technology or library. One is just a pattern that you can even choose to say I’m going to use just a little bit of it and leave the rest alone. In my case, I tend to use the Redux pattern liberally with observables and that works well but they are apples to oranges just a bit but at the same time they complement each other quite well.
Nate: Yeah. In that article that we wrote recently with using Redux and typescript, we actually provide a minimal implementation of Redux both in typescript in the straightforward function way and then also the observables way where we’re just using a subject with scan and reduce and they’re both super similar.
I think that’s a really important point that you keep making. It’s just that it’s a pattern and it’s a very simple pattern, it’s a tool that you use to organize the complexity. It’s not necessarily the be it all end all data architecture.
Lukas: We still love Ward no matter what.
Ward: I’m a guy who looks at it and says, “Yes, it’s absolute. I can see the appeal.” For one, it talks about a single source of truth and a lot of people aren’t ready for that. That’s a revelation to people and it is a simple, you can learn Redux pattern as you say in an hour or less.
What’s interesting is the idea that because the pattern is simple, the net result at scale is simple. That claim is the one that I haven’t found to be imperially true. Every time somebody shows me their solution in a Redux file or NGRX file, they say, “See, here, look at this code,” I look at it and it’s got six times the moving parts that I need and I can write it in half the code. Yes it was simple, but like many simple things, it gets exponential.
Nate: I’m super interested in your thoughts in the time that we have left around. So far with Angular 2.0, there is less widespread to a data binding and of course you can do it with NG model for instance but that’s really the only part built into Angular 2.0 where they’re doing two way data binding. What are your recommendations for ways that we can make our data architectures simpler without using Redux?
Ward: That’s a different show. Of course I happen to be in full disclosure an open source project called Breeze.js is something that I’ve been deeply involved in for a long time which also takes the single source of truth idea and it also has a rich notion of identity maps and pan objects that are actually observables, it turns out.
As a practical matter, that’s the kind of app that we’ve been building. We’ve been building apps that use Breeze, that uses entity model, and that screams component binds too. Use two way data binding and it works just fine. NG model is pretty much what you need to bind any form input like a textbox or select box and so forth. Where else do I need it? Although actually in Angular 2.0, it’s not actually hard to use the two way data binding same text without NG model.
I’ve got a kind of it just works feeling with it and what I find is that people spend almost no time at all working with the model and how they got the model. They don’t talk like people in the Redux talking about the reducers and all the stuff all the time. Nobody is talking about the data model, nobody is talking about how they’re getting the data, people are talking about what they’re putting on screen, how they’re interacting with the user.
They spend almost zero time talking about how they made Breeze work, how they make their entity models work. That seems to me about where I want to see people spend their time because that’s where the eyeballs are. When I see people talking about their reducers, when I see people wrestling with complex observable manipulations and their heads are all wrapped around that and they can’t stop talking about that and they’re not talking about what goes on screen, that’s when you lose me. That’s my nutshell.
Lukas: I think I know what our next episode is going to be.
Charles: Yeah and Alondo, a good guest for Breeze.
Lukas: I hear they’re jerk faces.
Ward: They are totally jerk faces.
Nate: I’d love to hear more about it for sure.
Charles: Alright. Let’s do picks then. Ward, what are your picks?
Ward: Well I’m in New York City at the moment and I’m about to see Hamilton. I’ve been reading the biography of Hamilton by Chernow, it’s really good biography and it was actually the book that inspired the play and I’m picking that book. It’s called Hamilton which is hard to remember but that’s what it is.
Charles: Cool. Lukas, what are your picks?
Lukas: I want to pick the out of the tar pit paper, I know I did that the last time I was on by Victor Savkin, he’s the one that pointed me to it. I think that I’ve since went back and read it again and it’s just really, really good. It changed a lot of my world view about or rather the things I said in the show about state and control flow and the code volume that comes out of that. It’s really affected that and caused me to think about those things.
The other pick that I have is, speaking of RXJS, if you go to their website, they have a really great overview of RXJS. It’s quite a long document, I put it in the download and it was about 22 pages but it’s a really good read about the high level RXJS stuff and I will put that link in the show notes. The RXJS overview on their new site is excellent.
Charles: Alright. I’ve got a pick real quick. This last week, or yesterday actually was Labor Day and I took my kids fishing. It was at a trout farm which means that you’re pretty much guaranteed to catch something. The other bonus is that they actually clean and fillet the fish for you. I didn’t need to get my hands dirty which is a nice way to fish. Then we had the fish fry at my brother’s house. I’m gonna pick fishing and fish fries with family. Nate, what are your picks?
Nate: Nice. Well, my first pick is definitely Lukas’s new Angular 2.0 patterns Git Book, it’s totally awesome because it shows you how to do Angular 2.0 stuff and Angular 1.0, it’s super good.
Another person that I think is really good, it feels like up and coming, his name is Houssein Djirdeh and he works for Deloitte and he has a article pretty recently called Building Angular 2.0 Applications with Immutable JS and Redux, it’s also pretty good. Can I have a third?
Charles: Yeah, go.
Nate: There’s another one that’s really good, you guys like Pokémon Go? There is a super interesting article by Venkatesh Rao, the Ribbon Farm guy, it’s talking about consensual realities. The idea is that augmented reality has basically lowered the barrier for writing onto reality.
That used to be that like those are shared realities that we have. We all agree to that money is valuable or that the United State exists. It’s an idea but we all agree to it. What does it mean when we all have the shared hallucination of Pokémon Go?
One of the things that he talked about is that as developers, we can write onto reality. Augmented reality provides this brand new tool where we can say, “Oh yes, there’s a Pokémon over there, there’s a creature over there, hold up your phone and you can see it.”
The article is called the Cambria and Explosion of Consensual Realities and it’s super interesting especially as creators to see these new ways of impact that is developers are gonna be able to have on the world.
Lukas: Woah, that was super deep.
Charles: Do you want to give us just a quick rundown on where people can follow you or see what you’re up to or buy a book from you or something?
Nate: Yeah, sure. On Twitter my handle is @eigenjoy and you can follow our company on Twitter on fullstackio and you can get a copy of NG Book 2.0 at ng-book.com/2 it’s all the way up to date with RC 6, we try to keep up to date with everything that’s coming out within a week of when they released it.
Check it out, it’s more up to date than the docs actually in some places so it’s really, I think one of the best ways to learn Angular 2.0.
Lukas: If I can interject, I’ve actually read NG Book 2 just as a consumer, this is not a paid testimony or anything like that. Nate and RE and company have done a really, really good job on the Angular 2.0 book and I really think it’s in terms of books in that way of consume materials, I think it’s the best on the markets. I’m giving a thumbs up for you. It’s very, very good.
Ward: I just want to say that I think it’s great and that there shouldn’t be a single voice and there can’t be a single voice or single position on Angular 2.0. There’s so many ways to go at it and so many perspectives and I think it’s just fantastic that you’re doing a great job on that.
Nate: Thank you.
Charles: Alright. Let’s go and wrap the show up. Thanks for coming, Nate.
Nate: Thank you very much.
Charles: We’ll go ahead and end and we’ll catch you all next week.
Nate: Right. Thank you.