You might not need NgRx | Mike Ryan | AngularConnect 2018

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] all right good afternoon did everyone get some good lunch today yeah true story the last time I gave this talk the conference served everyone turkey beforehand and so everyone was completely asleep the entire talk so I was really excited to see the spread today so my name is Mike Ryan you can find me on Twitter github and medium at Mike Ryan dev I'm a software engineer at synapse where I'm working on illuminating dart data with industrial Internet of Things I'd love to talk about that if you come find me I'm also a Google developer expert for web technologies in angular an ng RX core team member and if I'm being completely honest with all of you right now I don't particularly care for the film avatar but I don't want to talk about that cuz I could take all day with that topic instead I'm gonna talk about in grx an NG Rx is this open source libraries for angular it was founded by Rob Wormald with the goal of introducing reactivity into the angular ecosystem its primary library's handle state management and side effects of which we're going to talk a little bit about today and it's completely community driven it's all volunteer work done by people just like yourselves so please get involved with the project if you're excited about it and then directs kind of came in to formation by trying to answer this question how does my application change well from my apps it changes when my app makes an HTTP request and I get a response back or maybe an error it also changes when I get a WebSocket message from a connection to my back-end server and of course it changes when the user is interacting with the components that my application is composed of and to model these changes and share them with components traditionally before in grx I would have used a number of services like HTTP client WebSocket all service user service so on and so forth and in those applications that I was writing it was really difficult to follow how data was moving throughout this entire application often causing me to stare at these kinds of apps with well a confusion if I might and this makes it harder and harder to introduce new changes to these application as you lose the ability to think through this application so in grx tries to introduce a solution it tries to solve this problem with this concept of a global data store all of your applications date as in the things that change as your application runs goes into this store then each of your components dispatch changes to the store in the form of actions the store makes these changes to state and shares that new state back down to the components and all this is completely built reactively with rxjs so how's this actually working underneath the hood well first your components going to inject a service called the store they then dispatch change it to the store using a common interface called an action special functions called reducers take that action in the previous state and produce a new state which has relievers two components using an observable and if this is your first time seeing this circle then I can also probably guess what your expression is it's kind of really hard to understand and I like to kind of call this elegant complexity its elegance because I can put the entire circle on a slide and you could probably rebuild in grx and 20 lines of code but it's extremely complex because the implications for how you build an angular app within grx are massive and that's mostly because in grx prescribes an architecture it's all about giving you these tools to write explicit applications with well isolated responsibilities it also asks you to fully embrace reactiveness which means you have to understand rxjs and really lean into it in your application and with these two properties plus an insane amount of growth this year it's been downloaded over seven million times one of the most common questions that I get asked at conferences like these is do I need in jar X and the answer is I have no idea you see I know that I need in jar X because I know the business requirements of the applications that I'm writing in my day job in jerax and angular provide me the building blocks to successfully build applications that fulfill those requirements and I also know that my requirements of my applications aren't your Apple aren't your requirements we aren't all building industrial IOT applications and so I can't really answer this question if you need in G or X or not there's no blanket yes or no statement to this question or so I thought you see if I kind of just use this as my scapegoat each time I come to a conference what I've learned is that some answers have really started a gained traction and let me tell you these answers really aren't that great either for or against n gr X and so the first one that I hear most regularly is that you should not use n gr X because of boilerplate who here has heard this complaint about n gr X boilerplate yeah yeah probably even more hands than that if you could do me a quick favor we're gonna take a quick pause so that you can tweet at Maya co-worker Brandon Roberts just the word boilerplate I've crafted a sample tweet for you here so we'll take about ten seconds go ahead get that tweet firing he won't know that I'm giving this talk if you don't tweet at him and that's very important so we're going to take a pause for that no really he'll really love it so please fire off the tweet all right you see I understand and sympathize with this complaint about boilerplate injects is built on top of this Redux pattern you disconnect how state changes from the events that rise in your application these events called actions are transformed into state by reducer functions and specialer angular and special angular services called effects listen for these events trigger side effects and dispatch new actions back to the store and when you take this loop and decompose it into a feature it's a massive number of things you have to write for every feature every feature needs some combination of actions reducers selectors services effects containers presenters and it's just a tremendous number of files but if you embrace this you get some really cool benefits the first is serializability this lets you inspect download upload and dispatch as well as time travel all from the store deft unless you transmit actions over a WebSocket connection or from a web worker and lets you save and serialize state to local storage the patterns also built on top of immutable data structures and what that practically means for you is you can turn on on push change detection and your angular applications for performance boost it's also completely written in typescript and really tries to embrace type safety we write reducers and selectors and actions in a very specific way within grx to embrace and get as much type safety out of the typescript compiler as we possibly can this lets you verify the correctness of your program if you're using in jar X at the data layer it also lets testing the just a little less painful I'll touch on this in a minute but the idea is that we kind of remove this notion of dependency injection from a large part of our application and only really use it for side effects where it makes a lot of sense and so I like to say that it's explicit code it's not boilerplate all these benefits are possible because ng rx demands you be explicit about your application this does mean more code but not boilerplate so I empathize because I agree that there is a lot of it but it's kind of unavoidable if you're gonna write in jar X and if it was just boilerplate I could write abstractions on top of it for you but almost every abstraction or in jar X alternative that reduces the amount of code it's going to sacrifice or compromise some of those benefits and when we find opportunities for abstractions we kind of try to quickly bring these into ng rx that's where tools and libraries like injects schematics entity and injects data come into play and I know that probably sounded like me copping out of that answer but just keep two more things in mind I want to challenge you to think about in jar X naught in terms of boilerplate but in terms of code cost so that maintainability performance and debug ability of an index application you kind of have to pay something to get all those things really great things are rarely free so you're considering if you should use injects or not consider if you are willing to pay the code cost in directs demands for some of those benefits and again those benefits are testability type safety immutability serializability functional programming and reactive programming but of these six qualities that makes in Jurek so great of those to make an angular app you don't need any of them so you really don't need in grx unless you need one of these core qualities on the other hand at conferences like this I often hear the hallways that you should use in grx because ng rx makes your application easier to reason about now who's heard this one before okay a few hands not as popular as boilerplate and I'm not surprised but this one really really makes me sad because MGR X is an indirection framework that introduces intentional decoupling of your business logic from your view layer what is this interaction beam well ng rx embraces the single responsibility principle which states that for any given responsibility you should have one well-defined module of code that handles just that responsibility so in a typical angular service based application we tend to write components that have a number of responsibilities for instance it's not uncommon to have a component that might use a service to make an HTTP request and then using the result of that HTTP request show the results in the template but angular wants you to write applications this way in jar X wants you to try and decouple them so we take these responsibilities and we sort of separate these concerns out using ng rx individual responsibilities around presentation state transitions and HTTP requests are all separate concerns so i'ma bringing this up well if you take a typical store where component there's a big question that new developers who are going to read this component are gonna have and that question is where are the books coming from that this component is trying to show where is this data actually coming from I see no evidence of getting that data anywhere in this component well I wrote this code suddenly walk you through it and let's see if you found this to be really easy to reason about or not you see the first thing that happens to get this data is this component dispatches an action called an interaction and the actor is the books page this captures the event of entering this route using the angular router from there and a completely separate file there's a special angular service called an effect and it's using a special rx operator to listen for actions of that type it is listening to that interaction and when it sees that action it's gonna make an HTTP request to get all the books and it's gonna map the response of that HTTP request into a new action it's capturing the event of a successful response and transforming it into a new action in this case books API get all success then in another file there's a reducer that's listening for this get all success action type and it's updating the state the list of books to the result from that HTTP request and yet another file there's now a selector that's taking the entire application state and retrieving that list of books and then finally circling back around to our components it's applying that selector to state and that's what a list of books come from did you follow all of that no indirection can make tracing business logic really confusing so in Gerak's is not going to magically make your application easier to reason about in fact it might be the case that many apps where you implement in jar X is gonna make it difficult to trace business logic in your application unless you're really well trained on the pattern itself so if you're evaluating in durricks try to keep this in mind don't pass up in jar X because of the boilerplate instead frame it as a code cost to leverage the benefits of the ngr X pattern on the other hand don't rush towards using in gr X if you think it's going to give you some sense of clarity over your application so what are some good reasons to use in jar X well you might need in gr x if you have complex state problems and to talk about complex state problems on the ng rx team we've come up with a pneumonic called the sherri principle to highlight some of the most complex state problems we see in angular applications first is shared state shared state is accessed by many components and services in your application my favorite example of shared state is authentication state many components or services may want to know if you have a user authenticated successfully with your application or if they have not logged in yet the H stands for hydrated or state that is persisted and hydrated from some kind of storage mechanism two examples of this would be like local storage or angular Universal with local storage you may want to synchronize some user preferences to local storage and the next time the user that uses the application you want to rehydrate those from local storage that's an example of a hydrated state problem similarly with angular universal your application might enter a state when you're rendering your 8 application on the server and you want to take that state transmit it down to the browser and have your application resume from where it left off those are both examples of hydrated state problems the a stands for available or any state that needs to be available when entry entering routes think about some of the complex form wizards that you've had to build as angular developers when a user is going through that form wizard maybe they want to go back to the previous page or for their page and not lose any results so you want to keep that state that they're building up across multiple routes in your application the R stands for retrieved or any state that needs to be retrieved with a side-effect the easy one here is an HTTP request if you want to save the result of an HTTP request the stores a great mechanism to kind of keep that state and not have to redo placate that HTTP request again in the applications lifecycle and finally the I stands for impacted this is probably the most complex of the Shari principle but it's any state that's impacted by actions from other sources so I'll give you an example pagination sometimes in applications I've had to build a pagination component where I've taken in a list of data you to chunk it up into specific pages and then show up a generic opponent across the bottom and that component state is really based on that list of items that I've passed into it but that state could change from a variety of ways the application could go make a new HTTP request that rehydrates that list of items and now that list might be bigger or smaller similarly I might get some kind of WebSocket message that adds a new item to the stack and so I need to recalculate state as this list changes that state that's been impacted by actions from other sources another reason you might need in Gerak's is if you find yourself writing a lot of tests this is because quality is at the heart of in grx where I work at synapse if the software I write fails it could put people that are in manufacturing plants in danger so as a result I've tried really hard to make sure that quality is embedded into the core of ngr X in testing is a big reason why ng Rx is so explicit by decoupling our responsibilities into well-defined modules adhering to the single responsibility principle we can sort of build common testing strategies that are targeted to those specific modules of code and one of the principles that we're going to apply is functional purity and Gerak's emphasizes this notion of functional purity which is that a function can be called pure if it always produces the same output for a given input and has no observable side-effects and I've found that it's best to understand functional purity by looking at some functions that are not pure and seeing what it takes to purify them a function cannot be called pure if it modifies one of its arguments in this case this insert item function is taking an array of items and it is pushing an item directly into that list you can say that it is modifying that list directly we are changing that argument we can make this function pure by instead having it returned a whole new list of items with that item prepended to the end so in this case we've taken this function and we're no longer modifying any of the input arguments to the function a pure function must always return the same result for a given set of inputs this bootstrap app function doesn't do that and it's because it's reading from some global state this is at bootstrapped flag that's on window that means each time you call this application it's going to return something different you have no guarantee that it's going to return the same thing each time you call this function so how can we make this a peer function well instead of reading from global State we could just had that state passed into this function as an argument now depending on how you call this bootstrap app function it's always going to return the same result you have a guarantee about how this function is going to behave this function has an observable side effect the get menu function immediately starts an HTTP request to that API endpoint and so this get menu function is completely impure but how do we purify this one well you really can't most applications have to have side effects somewhere we can't write our applications in a completely pure way or a completely deterministic way inherently most of the applications we are building with angular are gonna have some kind of side effect and so in the Redux pattern we've extended it on the ng rx team to have these special things called effects these are long-running processes built using observables that run independently of your component tree they can listen for actions but don't necessarily have to do anything about that and trigger some kind of side effect optionally yielding new state or actions back to the store this keeps our reducers pure but can we write components in a pure way components can't be written with just functions today but still some aspects of functional purity can be applied to our component so that this component have any of those side effects we just pointed out the answer is not really it's not doing anything to change this list of items it's not reading from global State and each time you pass in a list of items it's always going to render deterministic deterministically for that same list of items well what about a store where component does this one have any of those same aspects of functional purity and again I think it does it's the same kind of component we're not modifying the list of zones that were getting from the store we're always rendering the same way for the same list of zones but it's ones store where and so I kind of like to think of store dot select as a special version of input and I bring functional purity up for both functions and components because functional purity reduces the scope of unit tests by encapsulating your logic and pure functions and components we dramatically reduce the scope of a test we don't need to mock out side effects when testing these components and reducers instead we can just provide them with some legal input and verify that they've either returned the same result for functions whether they've rendered the same way for components this is gonna save a lot of time when you go write tests for an index application and injects really emphasizes writing pure functions and components reducers and selectors are completely pure components both presentational and container components can be written in a pure way and so functional purity reduces the scope of tests and index helps you write the majority of your angular application using this pure principle then you can say that ng rx reduces the scope of testing in your application you might also need n jar X if you work in a team environment and I think in jerks has three key advantages if you're working on a team it offers a common architecture for your team has great content that helps new developers on board to the architecture and it's gonna unlock some productivity benefits so what I mean well I said at the beginning of this talk that ng Rx prescribes an architecture and I think it's worth repeating again here if you're working on a team or are a member of a larger organization you need a well-defined architecture an architecture gives you an abstract understanding of a really complex application that every engineer can use to talk about that complexity in gr X can be that common architecture for your team it would give you a playbook for implementing new features in your application and it'll give your team a common language for talking about your apps code and along the same lines in Jax is really privileged to have some of the best content creators in the community like Deborah Kurata John Papa and Sam Julian writing articles conference talks workshops online courses and tools that will help you onboard new developers that's architecture quickly I guarantee you that it's gonna be difficult to replicate the same quality of content that index has for your in-house architecture another benefit for teams is the ability to parallelize work across your team because it in grx application is composed of loosely coupled pieces you can easily parallel wise the development of features first you write the actions services and presentation components these can all be done completely independently of each other by different developers on your team then with the actions and services in place you can go ahead and start writing your effects and reducers again different team members can write these pieces they don't have any knowledge of each other thanks to that indirection finally you bring it all together with a small layer of container components you can build these as a team to solidify your team's understanding of how this feature was built and so index provides a productivity boost for your team this decoupling can allow you to parallelize the development of features just by using ng rx and this could mean for some of you the ability to deliver value to your customers more efficiently lastly you might need in gr X if you want to increase code reuse in your organization so this one I'll share a story of one of the applications that I work on at synapse we have an industrial-grade smart lighting solution and using this application users can create scenes that apply different behaviors or levels to the lights and it's just my luck that this entire application runs on this thing and I promise you this thing has less power than an Android phone from four years ago so the applications really complex the UI for this has to do a lot of the work because the backend for this application has to be very low level and primitive in order to run on this device we actually have a cloud-based version of the same lighting application and its back-end is so much nicer I'm talking about graph QL WebSockets the whole nine yards it's an absolute treat to work with but the components are exactly the same as the one that was running on this device so how can I share components between that device and the cloud well indirect makes this easy for us that indirection that injects introduces between my component layer and the business logic means that I can share those entire components between applications and implement different effects for each applications that I want to share these components with so to recap you might need in grx if you have complex state problems captured by the sherry principle you also might need it if you find yourself writing a lot of tests and want to find ways to make testing easier you may need in jarek's if you work in a team environment and are looking for an architecture that unifies your team or you want to get a little bit more productivity out of your teammates or you might need njx if you want to increase code reuse across your organization and have a need to share big component hierarchies across multiple applications and so at this point some of you might be thinking ok yes I want to start learning in jar X this might be useful for my application but before you start there are a few things to consider first behavior subjects are totally fine I often find at conferences that developers kind of feel guilty about using services and behavior subjects for their application state but really this is a fantastic pattern if you're getting mileage out of this and you don't feel any friction using them keep using behavior subjects they are really fine additionally index has some really advanced use cases that it tries to cover and we pay for that with complexity in that high code cost Akita and ng XS both offer simpler state management solutions for angular than ng rx does so make sure that one of these two libraries doesn't cover every use case that you have before you reach for the big tool that is in gr X because index is all about these trade-offs you gain testability react and performance when you use in grx but you pay for that with complexity in direction and a high code cost and I'm not trying to dissuade you about in grx I think it's an amazingly powerful framework and I'm very proud of the work that deams done but the problem is that is really overused and developers are frustrated by all that complexity that introduces so next time you're starting a new angular application just keep in mind that you might not need in grx thank you [Music]
Info
Channel: AngularConnect
Views: 20,467
Rating: 4.8726115 out of 5
Keywords: angularconnect, angular, angularconnect 2018, angularJS, angular conference, javascript
Id: omnwu_etHTY
Channel Id: undefined
Length: 27min 31sec (1651 seconds)
Published: Fri Nov 16 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.