As a solutions architect, Thomas helps enterprise teams reduce technical debt and deliver complex Angular applications. Formerly a solutions architect at Nrwl.io and Team Lead on Google’s AngularJS Material, Thomas not only mentors teams on RxJS and NgRx, he provides technical leadership to refactor product architectures and deliver Angular solutions.View the profile
About the talk
Like an alien invasion, everyone is telling you to use NgRx! You are fighting and resisting this Dark Lord mind-shift. What if you wanted to super-power your services without using NgRx?
With RxJS, you get all the super-powers of Observables and `data-push` features. And with View Facades + RxJS, you can radically simplify your view components; hiding all complexity in the Facades.
But designing these Facades can be tricky indeed!
Come learn about Facades and the best-practices for Facade APIs. And then see where & how NgRx can be easily added [later] without affect any of your View components. See where Facades + NgRx are most beneficial… and where NgRx is a perfect next-step, enhancement.
Follow us on twitter https://twitter.com/ngconf
Official Website: https://www.ng-conf.org/
For years you like that, huh? Thank you for years. You've been coding wrong. That's probably an arrogant statement, but it's meant to provoke some thoughts. And in this session, I want to resent some ideas what I hope will challenge you and convince you to shift the way you do application development angular. Today we're going to talk about push base architectures using rxjs and facades. And of course, my mouse doesn't work. classic so traditionally we
Implement code in the following way. This is what I call the pool based approach we can do things for example where we can call a service a pagination service and update the pagination and get a response back. We can iterate over to Ray and extract the full username and get an array of or a list of full usernames. We can also do a synchronous things where we could for example use a promise to listen for a mouse click event. We can even call the H-E-B service to get a list of remote users and where you're getting that list back via stream, but these are all pull based approaches you call them.
Once they respond they're done. They're not going to return values over the future. Let's take a look at this one a little bit more again. So here's our httpservice. We're making a pole Base called because what I'm saying here is the user dollar. It's a temporary stream. We make the call we get the string back. So the stream the stream is constructed one time. We get one response. Rice or even with rxjs and observables our users are there still implementing pull Based Services and pull based architectures?
So what about a new approach? What if we could change the way we were thinking do something that I called push Based Services now, there's been a lot of talk the last couple days about rxjs and ngrx and all these different approaches and you're going to see a lot of similarities to those patterns here in this approach. So this is nothing new but this is meant to be a paradigm change for the way you think so now what we can do is we can construct a stream are user stream using another stream that will extract our users out whenever that state changes
and this stream now is a long live stream one can say that sometimes has a permanent stream or maybe it's just a long one until someone reconstruction, but it's going to be around and be used for as long as we want. We build it once and we can get one and number of the missions or events that come out. And our views this is the most important thing our views can react to any time. The data comes out with a new list of users are views react to that. So here are some examples of some apis our usages of push based approach here were
using a user facade and we have a pagination stream. We're just getting a reference to it here. We're calling an update criteria method with some search criteria and we're getting a criteria stream back notice. How will the user Prasad we don't know what's happening underneath the hood, right? And we shouldn't care. We just know that we want these streams they're long-lived and they're just going to give us data when it's available hear some asynchronous calls, right? So the top two or synchronous. There's nothing that says these dreams are synchronous or asynchronous. I'm just letting you
know that the top or synchronous but the bottom ones could be synchronous. What if users facade stream doesn't have any day that yet. That's okay. We construct a reference to it. We now have user Stream Long Live and whenever the tables available that will be pushed through it. We can call search criteria with some new criteria and get a new stream, right? It doesn't matter when the date is there just that when is there it will be just to us through the Stream. So let's build an application of purely simple application with a pole based approach
and a push based architecture and we're not going to use rxjs in this application. We have a list of users that we're loading from a cloud service. We have a very simple you are right. We have an input control some pageant Nations. We have a button that says low the users that will trigger to load the users and we have a show page button to show page size to the API to the cloud services. So tell me what the criteria is the search term that you want to use. What's the page size for how many results do you want and I'll give you that was all set back. That's where we can implement or I've
already implemented and I'll walk you through. We'll start with the pull based approach. So here we already gone over the UI for for briefly here. We have actually an input stream from rui in this case were using a form control and using value changes. And that's an input stream whose data will be used in the UI to trigger a call to use their service. And when we trigger the call Louise or service were saying find all users with a new search term criteria. Again. This is Apple based approach. So in this
case, I don't want any data to be managed inside my view right with we know that one of the best patterns is if you're going to share day. Keep it outside of you keep it it was injury wrecks. We have some State Management excetera emulate that approach. So here we have a user interface. We have a pagination interface so we can find some of the data structures and we even have a time to find an interface for the response coming back from the server. Now will decline our service later. I'll change the name from user service to use her facade, but they're very close.
Right the terms can be intermixed hear. The service has some data state that is managing internal accept. This data is public right? So that means anyone can read these properties users criteria pagination again, once they read it. That doesn't mean it will change later that they'll get changes that that date has changed on the service. So again, it's a pool base API. We have a Constructor and we haven't met the right to find all users. So with find all users once you call it we're going to take the current Criterion pagination build URL make a call to the remote service when that
response comes back. We're going to extract a list of users and we're going to return that through the request dollar stream, but we're doing something a little bit more here, which is pretty nasty. But really, I noticed the top but app says Jesus also save it in our local internal state. Now for those of you who have gone down this route before, you know, there's already some problems Brewing. All right. Let's take a look at a live demo here. So in this demo if I refresh the page.
And this Vista classes are available online all the source codes available. You can look at it later. So notice the user list is empty. We have a search team that we populated because we initialized or state and when you I loaded it pulled that those that still settings out if I change here I could show the page size I can change here but nothing's happening. Right? Nothing's happening to reload the data. I have to actually write code to reload the user list. Okay, so I'll load the user list. That's cool. But now it's make some changes and I deliberately did that to say that when I
made changes I haven't made a call to the server. So I'm just going to clear the list. So now I have to reload the list. I can change the page size. But I have to reload the list again and granted this is a simple example, but this is the ideal pull-based right you make changes are going to the pool again. You're going to make another call to get the new data. We want to avoid that. We want to have a system where our views are super simple and they simply render whenever the day that changes for someplace else. We don't care how it changes. We just want to know when it changes.
So I contend that when you're using push base services or architectures, there's tons of dangerous. I'm not going to go over all of these but the two problems here are the following if the if the service is shared among multiple views of the views notified when the day that changes when they win the pipe pagination changes or the criteria changes or even the user list changes, right? That's that's problematic and how do you share the results for find all users? So let's take a look at a better approach. And this was sort of an epiphany for me this
idea to not just use rxjs. But to use it to build push base architectures is really a paradigm changer So with push base architectures, let's take a look at this diagram. We have her input control with a search term when the search term criteria changes were going to call or the pagination going to call a method update search criteria update confirmation that will win because that's a method on the facade facade make some changes internally and then we'll update it state that it will probably trigger a Reload for the users and then we have three
streams that come out notice the streams that come out or pagination Criterion users. So these are long live streams of the ui's using and regardless of what happens in the user Prasad inside or in some other layer or even on the server Windows user State changes. These streams would re-emit the current data. This is a very powerful concept. So it also helps us build apis because we can then say well, let's plan this right. So here's our user facade. Like I said, it's similar to the user service. But here's our public
API. We have three outputs are all streams. Right and remember a stream is up is a mechanism to channel data to you when it's changed. So we have a user stream a youth criteria stream in a pagination stream. We could Define a search criteria stream is an input. That's a really provoking provocative statement. We could have streams coming into our services of streams coming out notice. You don't know how it's working at inside and we have two methods update search criteria and update pagination. That is our API. That allows us to protect whatever we're doing on the
inside and you'll see in a few minutes some of the surprises we can have enough to the flexibility that we have. So again, let's define our API write in code. So now we have a user's facade. We have three streams and observable of the criteria pagination and users. We inject right to be serviced and we have two methods. That's pretty cool. Let's see now how we Implement that. 904 Performance reasons and change detection purposes and a few other things we're going to do something at Redux promotes that ngrx emphasizes and we're going to maintain our data as
immutable that means whenever the date of changes we're going to create a whole new instance of the data that gives us high performance. So we've defined our user state is analogous to what we had in the service, but now we're gathered into an object called user state or into an instance of user State. We've initialize it right here underscore State. It's private noticed that the let its private is private to the module 4 user Passat and then we have our user Prasad and this is where it gets interesting. We created behaviorsubject and we initialize it with the user State because
with a behavior subject anyone subscribe to it will get the last set of data that came out of it, which is the current user State and then we have a state stream. That's just an observable of that now for those of you who are abused. Using ngrx. This is very familiar, right? This is nothing radically new. So but there is something interesting happening underneath the hood the user of sod as I said has three public properties that are streams criteria pagination and users. And internally, it has the state criteria pagination users that's
light brown bar, but we can use those screams internally also, so when Criterion pagination change the people who are consuming the stream on the outside people be notified, but internally, we can also listen for the changes on either of those streams and auto call a remote service to load the users. And then once for users comes back internally, we update our user State and then again, we emit that out and now the user dollar stream and it's the new user list. So everything is hidden inside the user Prasad, but the API is super clean. I
apologize. If you can't see this quite clearly, but I'll just go over briefly. So notice here's our criteria pagination and user streams and we're doing something very similar to store selectors and your ex. We're actually saying State. Pipe and we're striking out the criteria for the pagination are the users whenever the state that use or state changes. Then in our Constructor we build we've combined those two streams internally and you'll see we use a switch map to call the remote service when the response comes back from the service. We actually create a whole new state object using
the spread operator. And then we assign it locally toilette variable and then we admit it through the store which then fires are selectors up above on criteria dollar pagination dollar and user dollar so very similar patterns that you've been used to already. Notice that our methods don't return anything, but they also create a whole new state instance and they also admit through the state. The outside world doesn't know anything about this. I'm also not using into your ex, right so I don't have all these files and everything else. Let's take a look
at this demo. I especially like this demo because it feels like the UI has fluid. So if I so I'm going to show the page. So I so you can just see it by change this it reloads. If I do a 5-3 loads if I change anything in here. It reloads and did you notice the grape liqueur where everything was sort of disabled? So even while it's loading internally I was able to see and and modify my UI to say wait that the date is is pending. So in this case the UI is very fluid
and I feel confident that whatever I'm doing with those controls. I'm seeing the proper set of data. And in fact, I won't show it just now, but in fact the UI code but look the imperative code at the in the UI component is very simple any of the complexities hidden within the facade. So with push base architectures unreactive Services, we have not only a fluid UI but we can build it's more it's easier to build wonderful user experiences. We have Auto searching for users when the criteria pagination changes we have that you wind up auto updates when the pagination of
criteria changes. We have UI components what are no passive they react to changes from hyperspace architectures. We can do all of our testing outside of the UI for all of our business logic and we can even use now Cypress or any of the other tools to do e2e testing just for rui layouts and our styling regressions. So using push base architectures makes it easy for us to do testing also, And let's say that we decide that the complexity we need to manage is a lot more than this simple use case. You can easily add and your ex under the hood you
can have the full power of affect and memo and memo my selectors and reducers and everything else that you want underneath the hood, but the Vue components in the API to the facade hasn't changed. So I'm hoping that this presentation has presented some new thoughts and maybe we'll convince you to experiment on shifting away. You try to design your services and couple to your components. Thank you very much.
Buy this talk
Access to all the recordings of the event
Buy this video
With ConferenceCast.tv, you get access to our library of the world's best conference talks.