Change Detection Method in Angular - AiA 359
In this all-panelist episode, Armen comes back to the show to talk about one of his articles, “Change Detection without Change Detection. Change detection functions by helping rerender the UI when data changes. In this episode, he shares the importance of using his Change Detection technique to improve performance rather than using the built-in one.
Show Notes
Armen comes back to the show to talk about one of his articles, “Change Detection without Change Detection". Change detection functions by helping rerender the UI when data changes. Armen joins Chuck and Subrat as he shares the importance of using his Change Detection technique to improve performance rather than using the built-in one.
Topics discussed
- Change detection and how it works
- How do you call or trigger a Change Detection
- Inject Function
- Proxy Object
Sponsors
- Chuck's Resume Template
- Developer Book Club starting with Clean Architecture by Robert C. Martin
- Become a Top 1% Dev with a Top End Devs Membership
Links
Picks
- Armen - House of the Dragon | Official Website for the HBO Series
- Charles - Board Game Conventions
- Charles - Clean Architecture
- Subrat - Atomic Habits
Transcript
Charles Max_Wood:
Hey everybody and welcome back to another episode of Adventures in Angular. This week on our panel we have Subra Mishra.
Subrat_Mishra:
Hello, hello.
Charles Max_Wood:
We also have Armin Vardanyan. I can't even remember if I'm saying your name right, dude, sorry.
Armen_Vardanyan:
Hi everyone.
Charles Max_Wood:
I'm Charles Max Wood from Top End Devs. A quick shout out, I'm putting together a course on how to take your career where you want it. So if you feel stuck, this is your course. Anyway, Armin, you said you wrote this article, in fact, you sent it to us about change detection without change detection. Do you want to kind of just give us the 10,000 foot view? Cause it sounds, I don't know. Change detection, turning off change detection for anyway. I'm kind of curious how this works if you...
Armen_Vardanyan:
yeah
Charles Max_Wood:
mess with
Armen_Vardanyan:
sure
Charles Max_Wood:
zone JS
Armen_Vardanyan:
let's
Charles Max_Wood:
and stuff.
Armen_Vardanyan:
yeah yeah let's dive into this so here's the general idea like in So the way that it works there is this change detector mechanism that gets invoked when we have like asynchronous events like set timeouts or promises get resolved or something like that. So in general, it works automatically we don't have the need to kind of engage with it. It's optimized heavily but it's not like ideally optimized because it runs change detection cycles a lot. like most of the time it runs change detection checkings without any changes actually happening. So one way to optimize it is of course like we use the change detection strategy, we can put the on push strategy, it optimizes a lot but you cannot have all your components having on push strategy. Some components need to have like the usual change detection strategy and only the components that are kind of like engaged only in rendering stuff. the UI, we put them into change detection strategy on push, right? But even this is still not like ideally optimized. We have situations where still there will be checkings and also if we have primitive values in the component, they also will get type checked. So this only protects against like mutations on objects and nested objects. It's still pretty good. In most of the cases, it's pretty enough. to like optimize the rendering and change detection. But yet it's not covering the entirety of the cases. So what we can do about it, so imagine if we are using like Angular 12, we don't have like the newest stuff, what we can theoretically do, no one is going to do this and I'm not recommending to do this, but what we potentially can do, we can inject the change detector ref. and call the detach method. So it has a detached method, what it essentially does, it says that starting from this component, detach this component from the change detection tree. So whenever there is a change detection cycle, when the change detector goes through the component tree and reaches this component, it will not go deeper, it will not go into this component and its children, it is not going to happen. So essentially just turns off change detection starting from a certain node on our component tree so we can detach it from the automatic change detection but every time that we perform any change to our component like change a property or an object or an input we can manually call like change detector refs dot detect changes course, it's a tedious thing. It means that like, after every method, after every callback, we need to call this function. Obviously, this isn't something that I recommend to do, don't please don't ever do this. But what if we could create some sort of function or something that will return objects that will do that for us, so we can interact with them and kind of have that functionality automatically done when we try to change this object. So this became possible after Angular version 14 when they exported the inject function. So the problem with doing what I mentioned within an object or in a function that is not inside the component is that we cannot access the change detector reference because it needs to be injected into a class. But now we have this inject function that allows us to get references to dependencies inside custom functions that we write. So if we write a function that gets to the change detector ref, we now can create objects or instances of classes that automatically call that function. But the idea is we write a function that returns an object that when its properties are changed, we'll call the change detector ref dot detect changes function. So how do we do this? We do this with the proxy objects in JavaScript starting from ES6 we have proxy objects. We can turn any object into a proxy, meaning that we can define generic getters and setters. So what we need is just return a simple getter from any object that we have, that will just return the value. And for the setter, we just need to set the value and call the detect changes method. That's it, that's like
Charles Max_Wood:
Mm.
Armen_Vardanyan:
literally very simple. One step further would be to make this function recursive. So now if we even provide objects with nested properties with other nested objects or arrays or anything, it will go all the way down recursively and make all the inside objects into proxies that will in their turn call the tech changes. And now this
Charles Max_Wood:
Okay.
Armen_Vardanyan:
object is perfectly optimized. It only calls for change detection when it is definitely changed when we have set a new value on this object, we don't even need to change the reference of the object. In my examples, I went the kind of like react route. I created a useState function. I called it useState, but it's irrelevant how it's called. It receives an object, turns it into a proxy. And now I can just modify the object any way I want. And it will automatically call the change detection. And also this function detaches the... change detection from my component. So if I call you state, I can only work with that object. If I have another property on my component and try to mutate it, it will not affect the UI. It will not be detected as changes. And that's perfectly okay, because usually we there are developers that have this practice of creating a view model object and putting everything there. We don't really need separate instances of this. We can also use this to kind of get rid of the async pipe, not really get rid of it, but we can, if we turn change detection and put an observable into a similar function that subscribes to observable and calls change detection when it receives the new value. We can also make sure that async pipe works, like we can write a separate function called use observable and it will work perfectly in the same scenario. And the cool thing is, no matter what is the object that we turn into a proxy like this, it will work all the way down. If we have an array and we do array push, it will trigger change detection. If we do an array pop, it will trigger change detection and so on and so on. So it's an approach of kind of like ditching change detection in a specific component. For example, we have a component that is so heavy and it works on lots of data. we don't even need to like convert our entire application to this we can just select one specific component and say you know detachment change detection here use this reactive kind of like object and we won't get any change detection checkings on this one starting from this one because all the layers down will be detached from the tree
Charles Max_Wood:
So.
Armen_Vardanyan:
so that's the general idea
Charles Max_Wood:
So one question that I have, and you may have explained some of this, but I mean, why go through all of this? Is it performance or is it something else? You know, rather than just use the built-in change detection that comes in Angular that, you know, quote unquote, just works.
Subrat_Mishra:
Yep.
Armen_Vardanyan:
Yeah, it's mostly performance related, of course, because in general we have no problems with just writing properties that work the same way. For most of the part, this is a sort of cool experiment, but it has value like we can entirely ditch like zone.js. We don't need zone.js if we are using this approach. We just don't need it. By the way, I have read that for example, Vue.js is making heavy use of proxies also. So they rely on their change detection using a similar approach. But the Angular has the change detector and now you can export it. sorry, import it using the inject function. It means we can just write like plugins like this. So throwing away zone.js and improving the change detection. I'm not saying this is something that's gonna, you know, revolutionize everything and we're now going to throw it away, but it is an interesting perspective. It's not ideal in any way. I'm planning on releasing this. small code base as a library so people can experiment with it. But I wanted to write unit tests and everything for it because it's kind of raw at this point. But when I'm done I'm definitely looking for feedback on this. I'm sure there are gonna be issues. One issue I discovered was that inputs weren't working properly when you use this function. So there is a workaround if we... implement ng-on changes and just call the tech changes there. Now inputs will also work perfectly. We don't need to make them into a proxy. So that's not a big work around, so not a real big deal issue. You can run into problems with third party components if they have their change detection strategy changed or in some way. But in general, as far as I've tried it, it worked. Mostly I have tested
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
it for several days, but obviously of course it's going to have issues. So. to find
Subrat_Mishra:
Yeah.
Armen_Vardanyan:
workarounds for those.
Subrat_Mishra:
Yeah, I think I just want to like what I understood from what I heard. Like when you're creating a component, we can have a separate method which will inject our chain detection, right? You can inject a chain detection and the method itself will be responsible for the chain detection rather than the zone.js or the angular default chain detection to run the chain detection. Okay, I mean...
Armen_Vardanyan:
The issue is not the change detection itself. Sometimes people commonly think that we're optimizing change detection itself.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
It's not the optimization of change detection. Change detection still works the same. It goes through some component data and compares references and values. It works the same regardless if we do an on-push strategy or if we do just This approach of mine or we just leave it by default It works the same what changes is when we call change detection So now when we don't use any strategy angular decides when to call change detection and it calls change detection on Not all but most async events like if you move your mouse You'll get at least one like change detection cycle. Yeah, they did optimization. It's pretty optimized. It's pretty good for like 95% of apps.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
But if you have like this large enterprise tool with lots of data and web sockets and everything, especially if the code is not very well written or you haven't done other optimizations, this can cause problems because if you are having interconnected components, a change in one place will mean, you know, lots of like ticks and they will start checking everything and they will go through. And also you will get like this nasty warning errors, like expression changed before it has been checked, right?
Subrat_Mishra:
Yeah,
Armen_Vardanyan:
The bane of all Angular developers. Yeah.
Subrat_Mishra:
this is a famous error for everyone like
Armen_Vardanyan:
It's that error is born out of not change detection itself, but like how it works. Like you go detecting changes. So it's a process. And meanwhile, some other process like modify something after the changes have been transferred to the view. Now Angular checks it and says, oh, you know, there's this problem that the data has changed again. Maybe the data model is not stable. And it throws this warning in the form of an error, which none of us like. But most of the time we try to deal with it. Like I have three or four instances in my work project application where I have this error and we don't have the time to deal with it. But it obviously shows that there is some issue in those. But if you, one like radical way to erase this would be, you know, detach change detection and just call it manually. Of course
Subrat_Mishra:
Yeah.
Armen_Vardanyan:
we're not going to do that, but for example, this approach solve this because you never call change detection after, without explicitly changing something. So this is like the smartest approach in that way.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
Angular approach is more efficient in really like detecting everything but it's very blunt it's like it's mostly like let's check every once in a while if there have been changes
Subrat_Mishra:
Yeah.
Armen_Vardanyan:
but instead of setting up like a set set interval for every I don't know 100
Charles Max_Wood:
Mm-hmm.
Armen_Vardanyan:
milliseconds it is a bit smarter than this very blunt approach but it's still kind of blunt it's not bad again I'm not like criticizing it it's 95% of Angular apps work very well.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
Most of apps don't need these sort of optimizations. But still, it's a cool way of thinking about how this part of Angular possibly can be changed to make it work better for even very high load front-end apps.
Subrat_Mishra:
yeah i think uh if i remember if i if i'm correct they correct me if i'm wrong like uh if we are going with on push strategy then even if someone is changing in the input then angular will run the chain detection so in this case if someone has suppose just want to implement your approach in a particular component so what will be the good approach like detach the chain use your un-pushed strategy and run the things because un-pushed strategy also like responsible for input and some event will can trigger chain detection
Armen_Vardanyan:
Actually, it is, we commonly say that when we put on push strategy, that it means that the component only reacts to input changes, but that's like not entirely true. It's on push strategy just means that it reacts to reference changes. If you have a primitive property on your component, not an input, just the usual property, but with a primitive value like a number. If the strategy is on push and you modify that number, it will still get detected. It will still trigger
Subrat_Mishra:
That's
Armen_Vardanyan:
a
Subrat_Mishra:
an
Armen_Vardanyan:
component
Subrat_Mishra:
detection.
Armen_Vardanyan:
re-render. The only thing that changes is that if you have an object and changes property without changing the reference, you won't get, if you push something in an array, if you have change detection strategy on push, it won't update the view, it won't re-render. It's a big deal because we usually work mostly with objects, like primitive value changes aren't that serious, we only can check them by comparing values, we don't compare references for numbers, right? We compare
Subrat_Mishra:
Hmm.
Armen_Vardanyan:
the values directly, so. But for objects, it's kinda... different approaches. Do we compare the value of the object? If you have this simple change detection, like the default change detection, it will go and compare everything in an object recursively. So that's a problem if you have an object with nested values, like a big list with objects and those objects have sub-objects and something like that. That's a big deal that you're gonna like traverse this entire tree of objects. So instead you can just say, you know what, I will create a new reference I will put the change detection strategy to on push. Don't go so deep and check everything there. Just change, if the reference the same, I don't care. If someone did a array push, I don't care about it. Is there a problem? I'm saying, you know, just compare references, which is obviously way faster than going through all the values inside of an object that has like nested objects and everything. So that is the optimization. I mean, So of course, on push strategy is a good optimization. It's something that we can like reuse, we can also rely on the async pipe being triggered, because it's an impure pipe. So we can just put the change detection strategy as on push, and just use observables for all of our values use an async pipe. That is also something that we can do to optimize, because now with each new object arriving, We will have new references, we won't have problems. Yeah, it's gotta be triggered a lot.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
Don't get me wrong, every time change detection is triggered, the async pipe is running. But the good thing is that it is only checking references. It's not a big deal. If you have like 10 async pipe instances in your component template, yeah, sure. It will just make a very simple comparison of two references 10 times once in a while. It's not it's not ideal like mathematically, but
Charles Max_Wood:
Thanks for
Armen_Vardanyan:
it's
Charles Max_Wood:
watching!
Armen_Vardanyan:
not a big deal, like from the time perspective, it's not a long process. So okay, let's repeat that process a lot. It's not very costly. That is one approach that people use like, you know, Eric's Angular, this small like component management or ngrx
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
I know people that in their projects, they for every component, they create the component store with only data that relates to only this component. So it's not like shared data and then just select that data as observables and put the change detection strategy to on push like it's a perfectly reasonable thing to do it even kind of makes the code clear clearer like You have these values here separately. This is the state of this component. And this is what they write one async pipe. They don't like write lots of them. They get the entire state into one object. So there's only one reference that is going to be checked. That's not a big deal. That's really a big optimization, like 90% optimization level. So this is also a good strategy. If you are having a large app,
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
That is an approach that is very attractive in that way. It's not very hard. We're still working with just observables, nothing new. It doesn't have the entire overhead that ngRxStore has. You don't have reducers and I don't know different things. You just write the simple class extend from component store. There you can write functions that transform the data and functions that get the data just injected into a component. And That's it. You have reactive state. No need to write properties directly onto your component class.
Subrat_Mishra:
yeah i think
Charles Max_Wood:
So.
Subrat_Mishra:
it will make sense yeah sorry
Charles Max_Wood:
Oh, go ahead. No, go ahead.
Subrat_Mishra:
now what I think is it will make sense like if like the now it's become independent of the component as well as as a change detection will not run for the smaller devices like which have lesser RAM like suppose older mobile phones or someone open lot of tab in the in the in the browser
Armen_Vardanyan:
yeah
Subrat_Mishra:
so eventually it will take less memory and try to run the application smoother. Like maybe the
Armen_Vardanyan:
yeah
Subrat_Mishra:
difference
Armen_Vardanyan:
that is
Subrat_Mishra:
may be small milliseconds and if that is bigger then people can go with this approach.
Armen_Vardanyan:
yeah that is sure some sort of taking like look at it because If you are developing an app, it's important to have like your sort of system requirements, like what versions of browsers do I support? What's kind of like, what is the sort of target ram that I'm looking at? Like do if it's an enterprise app and people are going to work it from their like office desktops,
Subrat_Mishra:
Yeah.
Armen_Vardanyan:
maybe it's not that big of a deal. But if
Subrat_Mishra:
Yes.
Armen_Vardanyan:
you write an application, like, I don't know, like YouTube.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
billions of requests every like second and you load lots of data and you have like sockets or you have live notifications you have I don't know videos playing there and everything so it's not in your best interest like to re-render a lot or run a process that is sort of pointless most of the time so you can open like the memory profiler tab in chrome try to compare whether this yields any difference for you. I think that frameworks like Angular React and everything, they sort of yield. tool for kind of like working with like creating a UI but how you are going to sort of serve it to your users is a different question like you have for example people will say don't write a personal website or something or landing page in angular but you can still do that and just use a static
Subrat_Mishra:
Mm-hmm.
Charles Max_Wood:
Mm-hmm.
Armen_Vardanyan:
You write what you are familiar with and export it as a static website. That is also an option. So differs on the scale, differs on the actual problem that we are trying to solve.
Subrat_Mishra:
So one more question like to be like I just want to wrap it up in my head So is this strategy also going to work? in the server side if like the with angular universal because I think that's I think it's not making sense
Armen_Vardanyan:
I haven't, to be honest, I haven't tried it but from the top of my head I don't see a problem. Like we can inject detection
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
strategy where we want. The inject function doesn't appear to have problems with server-side rendering. So essentially, yeah, initially you will get like null values, but it's kind of like whatever you expect with server-side rendering anyway. I don't think there's got to be a problem, but yeah, that's an interesting question. I think when I have time, I will try to... how it's interplaced with like Angular Universal.
Subrat_Mishra:
Mm-hmm. I will also try to go through article again and try to implement something. It's a good approach though.
Armen_Vardanyan:
I will when I publish it to github I will I will put a link in the chat
Subrat_Mishra:
Mm-hmm.
Charles Max_Wood:
Yeah, I was going to ask. Um, uh, it sounds like you can kind of pull this in and. you know, do some work on how you want to do change detection if it's, you know, different from, from how the rest of this works, you know, it sounds like mostly you're just introspecting on objects, but, um, yeah, the, the trick being, I have to go and decide where I want to inject this, where I want it. And so then the, the, the question becomes how automatic can I make it? And the other question is, how do I know that this is the right place to be injecting this instead of just letting Angular do the change detection the way it does. Because up to a certain point, I find with most performance optimizations, it doesn't make a major difference. It's just on those cases where things kind of go beyond the, you know, the reasonable responsiveness that you're going, okay, I need a performance boost here and where we're talking about Angular that generically and generally runs in the browser. It's just down to how efficient the browser is and how efficient the computer and operating system are that it's running on. So yeah, if you have a slower phone and you know that it has performance issues, you'd be putting it in place for those specific users. And then everybody else just kind of benefits it from being faster, but not so much faster than you necessarily feel it. And so yeah, I'm trying to decide, okay, this sounds cool. It sounds like something that I may need in certain spots, but yeah, how do I decide where to put it? Like, how do I decide which spots to put it in, or which components to apply it to, if that makes sense.
Armen_Vardanyan:
Yeah, I understand your point, but essentially about this over optimization, I completely agree with you. It's not like I wasn't running to like change my apps to use this, obviously,
Charles Max_Wood:
Why not?
Armen_Vardanyan:
but because it's experimental. But you know, the thing is, like from the developer, like, developer experience perspective, You also, you can realize that with this approach, you don't need pipes and you can write functions directly in the template.
Subrat_Mishra:
Mmm.
Armen_Vardanyan:
Because the problem with the templates, with functions in templates is that they gonna be invoked all the time, right? Every change detection cycle, you need to call the function to understand whether the value has changed, if you need to update or not. That is why Angular says, no, no, never call functions in the template, use pipes. Now you can just call functions in the template. You don't have change detection. Change detection is going to run only when we definitely know that the value has changed. So there is no need to like think about it. So you don't need pipes and it's like immediately a better approach. Like you don't need pipes. Pipes is some overhead. We need to explain it to. other developers like newcomers why do we need pipes and so on so not only for pipes like from the top of my head it's also it also like makes it it can potentially make it easier to work with like observables just wrap them into another function return a proxy object that will call change detection when it is subscribed from the sorry, from the function. This inject function, mainly for me, it started when I saw an interesting example when someone wrote a RxJS operator sort of, that worked like take until, but it was kind of aware of the component that it was inside of. it was the same as take until but you but he didn't create like a subject and called it on engine destroy what what they did was write a function inject the change detector and change detector also has this on destroy hook inside it works when this particular instance of change detector is destroyed and of course it coincides with the on destroy function on the component So they created the subject, they use the take until, but they called that subject inside that function. So you just can drop this operator on any streaming and angular components, say like take until destroy, and that's it, it works. So that got me thinking, if we can access change detector, that's how I started doing this. If we can access change detection in function like this, and like, why not try to call change detector manually when we know when we need it and just discard it from the component why not so I just got into trying to make this work and surprisingly for me I thought that they're gonna hit something that will be like unpassable that I can't couldn't do this but you know apparently I haven't found any like blocking thing yet maybe still out there there is some use case when this is becomes completely unusable, I don't know of that yet. But as far as I've tested, as far as some other developers I know tried it out, it worked pretty well. I like that they exported the inject function. It provides like new horizons on really reusable pieces of code. Now we can write functions that access dependency injection, that's really cool. That
Charles Max_Wood:
Mm-hmm.
Armen_Vardanyan:
really opens huge possibilities.
Subrat_Mishra:
Yeah, I think one according to me one best place to use it. All the components who are already have like on push strategy or they have detached the change detection and they are running detect change manually on every method call or on some action. They can just use that or whenever they will set some state the data itself will handle and re-render the data. So that. So they need not need to go and run detect change every time on some method. So this is like one of the good place. So from their coding point of view, the headache of running detect change is gone. They just need to set the value and it will run that change detection and it will render.
Armen_Vardanyan:
You are correct and I think that a pretty good use case for this if you are writing a UI library, UI component library and you if you are if you are writing a UI component library, usually you don't use like third party components, right? You are writing your own from scratch. So you can optimize them a lot with using like this approach. You know, you don't use third party components. So if you use this approach, you're not messing with any other library change detections. If they have something inside them that will
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
cause a bug or something, you're just writing from scratch. You are not messing with the other parts of the app because you are only detaching starting from this component. So everything upper. or its siblings are safe, you're not messing with them with detaching this part of the tree. So if you're writing like a component library or maybe some specific like a widget or something that is gonna be reused, this is an approach you can take and say, my component is completely optimized from the point of view of change detection, you can just drop it anywhere. I have seen this issue, like I was working with PrimeNG a lot, I have mentioned it. previous episodes. One issue that they got correcting a lot was that initially they just wrote lots of components without thinking about change detection. Some of the components got really huge like data tables, like really huge because it
Charles Max_Wood:
Mm-hmm.
Armen_Vardanyan:
has all sorts of features like reordering, reordering columns, reordering rows, adding dynamic columns, dynamically changing data and everything and sorting. And with all of that dynamic stuff going on, they had problems with change detection. They actually rewrote the entire thing. They wrote a new component called prime ng table. It was data table previously and enforced on push strategy there. So they really hit problems with change detections with all of that dynamic stuff going on. They just abandoned the previous component. They wrote on push. And if you go into source code there, or for example in angular material also has a table component if you go into there you will see lots of calls to like change detection manually because in some cases it made more sense if you have on push strategy you have changed some object you just call it manually you don't leave it up to like angular because it's gonna be messy it's gonna be checking lots of same properties and objects all the time so Why not just detach change detection, still write the code as you are writing, if
Subrat_Mishra:
Normally.
Armen_Vardanyan:
it was in default change detection, but have the benefit of like ideally fixing those changes for you. That's one particular like use case for this approach.
Charles Max_Wood:
Cool. One other thing that I'm wondering about is just testing, right? So. I mean, I don't, how do I put it? Like I tend to not like to test my library code. So if I pull in Angular and it's doing change detection, if I do something that triggers a change, I'm not always testing that it triggers the change, right? I'm more or less trusting the framework unless I'm doing something that's a little bit outside the norm. Do you kind of see that same approach with this or? I don't know.
Armen_Vardanyan:
Well, the main thing about this is usually we also manually call the change detector when we write tests, mostly, if we need to kind of like change check the template. The thing with this is that kind of like, if you have inputs, like if you have change detection on push, like for example, which is a pretty popular thing out there, right? Especially with libraries. If you have change detection on push and if you have like change detection cycle in your app, the third party components might not be checked at all, right? In some certain cases, if inputs have not changed, it will just not go down that component, never. But the issue is that usually we don't like unit test anything about it. We just... presume it works, right? If you are talking about the unit testing or some like that perspective. I think it would be harder to kind of like test these library itself. Because like, how do you test a function like this? Yeah, sure, it returns a proxy. It's not a big deal. You can just check that it's a proxy. You can mock the Angular change detector and be done with say, oh yeah, this function has been called. and change detector is not my problem, it's an Angular function, I just wanna call it. If I test that it calls it on all of the scenarios that I come up with, it's okay. But now there is this implicit problem, what if you have like child components, and what if you don't want that thing in your child components? Is it possible to reattach something if you want? So those are scenarios that... You really need to test this function in a Angular environment, like come up with the component and with template scenarios, because essentially you are working with templates. Who cares if a property on a class has changed just in a vacuum? We want it updated in the UI. So the real unit test that this thing needs is like, have this big template with lots of scenarios, with ng-if statements, with ng-for statements, with custom directives, with everything. and see how it works out for all this scenarios. Like you have a directive, it also relies on change detection, right? So if you write something like ngOnChanges in a directive, is it going to work? Is it going to work here? Do you now need to manually call change detector in directives, like on ngOnChanges or something? Those are all cases that need to be checked. As far as I've seen, if you trigger the change detector upwards, it's okay. But what if you have something changing inside of a directive? Like it's not notifying anyone. So maybe you need to use that same approach in the directive, for example, or in a pipe. Those are the cases that's gonna be unit tested hard. If I'm
Charles Max_Wood:
Mm-hmm.
Armen_Vardanyan:
gonna like release it to... even on an experimental level. I'm working on it. I've written like the basic tests, but
Charles Max_Wood:
Mm-hmm.
Armen_Vardanyan:
yeah, that only covers like it, like it technically covers what I want to have covered, but I'm kind of like meddling with the process that is a bit weird, like change detection. So I need to try also to think what will that change detection? What if I detach change detector from some node on the component tree how's it gonna affect like the deep parts is it usable in this scenario what are the real use cases so
Charles Max_Wood:
Right.
Armen_Vardanyan:
yeah that all needs to be covered
Subrat_Mishra:
Or you can say like my code never going to break. It's a feature.
Charles Max_Wood:
Ha ha ha ha.
Armen_Vardanyan:
I've heard it only really works if you are like writing your own products.
Subrat_Mishra:
Yes.
Armen_Vardanyan:
If you're, if you're outsourcing, you really got to perfect your like acting skills for that to work.
Subrat_Mishra:
No, it's always, I think it's nowadays mandatory to kind of write tests because it will going to help us later to make our life easier.
Armen_Vardanyan:
uh we have this project going on for four years haven't written like unit tests for it it's um it's not an issue on our part like we're okay with writing unit tests but you know this is how outsource works like
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
the client wants it and and they don't really care about unit test, okay you have like QA engineers, they are working, they have written some end to end tests, they are checking for it, it's okay, just, we just want the code delivered as fast as possible.
Subrat_Mishra:
Mm-hmm.
Armen_Vardanyan:
Obviously long term not having unit tests
Subrat_Mishra:
hate.
Armen_Vardanyan:
also gonna hinder like release plans, if you've got a bug you've got a bug. you know, if your app is mostly not changing too rapidly, if you know that in a certain large portion of the app you have this code that is very unlikely to ever change, like yeah, sure, from the perspective of a client, yeah, you know, screw unit tests, who wants them? This is done, we have tested it, it's okay, if you're not gonna change it. But yeah, I like unit tests. I always say that if you can write unit tests, you should write unit tests. Yeah.
Subrat_Mishra:
Yeah, yeah, the ideal and the real scenarios always differs on the situations.
Armen_Vardanyan:
Just for the developers, it's what I notice a lot, like especially in people that write blog posts and articles. We always kind of... I'm also guilty of this. Like... lots of time I assume like an ideal scenario where oh you know you can write this beautiful abstraction that will fix everything for you and it sounds really cool on paper maybe it worked in my project but what's like you don't realize at that moment is that you know people are going to spend time on it maybe it's not sort of financially viable for their team like they
Subrat_Mishra:
Hmm.
Armen_Vardanyan:
cannot abandon their approaches and just do this sometimes it's kind of like want for articles that explore bad code not just say, oh, you know, this is bad, don't do this, but say, you know, you have this bad situation, here are some okay workarounds or like iterative approaches on how you can fix it. Because lots of approaches are really radical, like, you know, open an article about some bad practices and say, oh, this is horrible, this is horrible. Oh, you know, I'm stuck with the code base that has all these horrible things. What are the ways that I can at least, I don't know, mitigate the problems at the very least? We shouldn't presume like ideal scenarios, that's what I say.
Charles Max_Wood:
Yep. Cool. Well, is there a place where people can go check this out? Look at the code. See what you're doing.
Armen_Vardanyan:
Probably next week or the other I will at least upload what I have to github. All the examples are in the article.
Charles Max_Wood:
Okay.
Armen_Vardanyan:
yeah
Charles Max_Wood:
Yeah.
Armen_Vardanyan:
so
Charles Max_Wood:
We'll make sure we link to the article and then yeah, if you have stuff on GitHub.
Armen_Vardanyan:
yeah I will share it
Charles Max_Wood:
All right, cool. Well, let's go ahead and do our picks since we're kind of getting toward the end of the hour. Subra, do you have some picks for us?
Subrat_Mishra:
I think I am reading a pretty famous book, it's Atomic Habit by James Clear
Charles Max_Wood:
Ah, so good.
Subrat_Mishra:
Yeah, it's a lot of people advise me I bought one But again, after a long time I started reading and it's pretty good, pretty practical and You can you can after reading one chapter you can go ahead and apply that with your life So that's this is the kind of book So I'm liking it haven't finished it yet but yeah keep on that with
Charles Max_Wood:
Cool.
Subrat_Mishra:
the pick for this week.
Charles Max_Wood:
Nice. Yeah, it's a terrific book. I need to go back through it. What I want to do, so I usually listen to the books on Audible, but what I've started doing is I've started picking up books and either getting them on Kindle or getting them in hard, like hard copy. And the reason is, is because then I can sit down and I can kind of go through it at my own pace. And like
Subrat_Mishra:
Yeah.
Charles Max_Wood:
Atomic Habits is one of those books where you kind of go through a section of the book and then there are things that you can do to do better, right? And so I've gotten to the point where I don't want to just read the book and then, you know, pick out a couple of things to do. I want to go through and like implement stuff. And so I'm digging that. Um, I have related pick to that in a minute, but Armin, do you have some picks?
Armen_Vardanyan:
I haven't been reading a lot recently but I really got hooked on the House of the Dragon series like
Charles Max_Wood:
Oh, is it good?
Armen_Vardanyan:
oh it's terrific like I hope they don't pull a Game of Thrones on us again although technically the story is finished I know how it ends because I read the book but I really like the TV variant a lot, really cool. It's not as complex as Game of Thrones, which probably makes it more appealing as a TV show, I don't know. But the first season was really, really solid, so if you liked Game of Thrones, or especially if you liked Game of Thrones in general and hated the last seasons, which pretty much everyone did. like check the house of the dragon it's really interesting
Charles Max_Wood:
Yeah. I have to say that... So I'll admit to having watched Game of Thrones. And the parts that I really loved weren't the kind of fantasy world parts, so the dragons and the, all that stuff, whatever. It really was the characters and the intrigues and the deep political machinations and all that stuff. That's the part of it that I really enjoyed, right? And yeah, so the reason I didn't care for the end of it personally is because all of this kind of comes together to not really resolve in a way that, you know, has to do with all that stuff at the end. But yeah, hopefully, you know, House of the Dragon is better.
Armen_Vardanyan:
Well, Super Dragon has all the things you mentioned, like characters are really interesting and the political intrigue. Again, not as complex as Game of Thrones,
Charles Max_Wood:
Uh huh.
Armen_Vardanyan:
but who cares about the complex integration of plots if you don't get an interesting resolution, right? Better have one significant interesting storyline that has a satisfying ending, which I know
Charles Max_Wood:
Yeah.
Armen_Vardanyan:
it has because I read the book, but... So if you have got like great actors and you have got this all cool visual effects, visually it's just stunning.
Charles Max_Wood:
Yeah.
Armen_Vardanyan:
Just the same level or even better than Game of Thrones and you get way more dragons.
Charles Max_Wood:
Yeah. Well, for me, like the dragons, the ice zombies, I can't remember what they called those things.
Armen_Vardanyan:
The White
Charles Max_Wood:
Anyway.
Armen_Vardanyan:
Walkers.
Charles Max_Wood:
Yeah. The white walkers and on all the rest of it, it just,
Armen_Vardanyan:
the
Charles Max_Wood:
it raised the table stakes for the characters, right? Because there were existential threats and there was crap that just could plain go wrong and you were done. And so, so that makes it interesting too, because you can throw a twist in there. that isn't far-fetched and then make everybody deal with it. And so that's fun to watch too, along with, ooh, we may or may not be able to take the throne or whatever. Anyway, did you have any other picks or should I go? Okay, I'm gonna toss out some picks here then real quick. So the first one is I usually pick a board game. To be perfectly honest, I've kind of been doing some insane travel and stuff lately and I just haven't quite gotten into it. So I'm gonna skip it this week. I feel bad doing that because I love picking board games. I am gonna be doing Timcon again. I guess I should pick that. So... I think I started doing the game picks when I did Timcon last year and I'm volunteering. Friend of mine owns a store, a game store. And you know, so that's a local board game convention and we teach people how to play these games, you know, over off to the side. And so I'm doing like a four hour shift and then I get free ticket to the game convention. And so yeah, so I'm
Subrat_Mishra:
Yeah,
Charles Max_Wood:
going to pick
Subrat_Mishra:
so I'm gonna
Charles Max_Wood:
that.
Subrat_Mishra:
put that.
Charles Max_Wood:
They have these game conventions all over the place. So if you're looking for one, I just do a quick board game convention or board game conference and see what you can find. The way that a lot of them work is it's not so much you go sit in a session where they talk about board games. It's mostly that they have a whole bunch of tabletop games and board games and you just pay to get in and you can bring your own games. You can use the ones there, you know, and they usually have a big pile of games that you can go, you know, check one out. play it with your friends. So you play, you figure out how to play it, and then you put it away. And you could just go all day and do it, and it's a ton of fun. And then, yeah, this particular area, we're showing people, hey, these five games are pretty popular, here's how you play them. And so you sit down and you have somebody that already knows how to play to walk you through it. So yeah, so I'm gonna pick board game conventions. And then the other picks I have. So related to the books and going through the books and implementing and understanding and going deep, I'm putting together a book club for developers. And the first book we're gonna do is Clean Architecture by Uncle Bob, by Robert C. Martin. And he's actually agreed to come to some of the book club meetings. It's all gonna be online. If you go to topendevs.com slash book club, you can sign up. And yeah, it's going to be awesome. Um, we're just going to get in and. You know, go deep on this stuff. Um, we're going to do it over zoom or something like it. Um, I don't, I don't think I'm going to use zoom. I think I'm going to use something that looks a little bit more like a conference streaming software and whatever I use, it'll allow. You know, 10 people, you know, eight, 10 people to get on the call with us. And we'll just rotate people in and out. So if you have something you want to share with the group, or you have a question you want to ask Bob, or if Bob's not there, you know, a question you want to ask the group or a discussion you want to have, then you can just raise your hand and we'll bring you on and we'll just rotate people through. And that way we can have a conversation about the book. Um, but then we'll also have some kind of forum or community where you can get on and say, Hey, I picked
Subrat_Mishra:
Okay,
Charles Max_Wood:
this up
Subrat_Mishra:
I picked
Charles Max_Wood:
out of
Subrat_Mishra:
this
Charles Max_Wood:
the book
Subrat_Mishra:
up at the door.
Charles Max_Wood:
and I'm implementing it in my code. So. I really like that. And then on the personal end, yeah, like books like Atomic Habits or The Miracle Morning or things like that. I really love those and just getting into them and kind of breaking down the strategies and, you know, making life better. So I'm going to pick that. Yeah, I've got so many other things coming. Uh, Angular remote conference, I'm moving that to April. So if you want to speak at a conference in April, that would be awesome. Or if you want to come to the conference in April, uh, you can do that. And then I'm also spinning up premium podcasts so you can get it without the, uh, sponsored, uh, messages in it. And then I'm looking at with most of the shows, finding people who want to do premium episodes for like 10 minutes and just. talk about a concept from Angular or things like that. I'm going to start out with the bigger shows I have, which are Ruby and JavaScript. And then Angular's up there, right? So if I find I have time, I'll be putting those out. But you'll get a bonus episode that gives you some insight into Angular. That's just a real quick thing. That's part of the premium setup. So anyway. I'm trying to think through what else I have to pick, but I think that's pretty much it. So yeah, well this was cool, Armin. Let us know when that GitHub's up, and we'll wrap it up here. Until next time, folks, Max out.
Subrat_Mishra:
イバイ
Armen_Vardanyan:
Okay.
Change Detection Method in Angular - AiA 359
0:00
Playback Speed: