Ember 2.x Internal Mechanism & Macros
This course has been updated! We now recommend you take the Ember Octane Fundamentals course.
Transcript from the "Internal Mechanism & Macros" Lesson
>> Mike: Here's the TLDR of how computer properties work. So when you get, if you have a cashed value you proceed directly to the cash and return it. Fantastic. If you don't have a cached value, you rerun your calculation, you get your value. If you allow caching, right, and that is almost always, right, unless you say I'm a volatile computer property, you allow caching.
[00:00:36] That will be spit up into the cache and then you will return the value. So there are just these two paths, you have the fast path if the cached value is there. You have the slow path if the cache value is not there. And, sorry let me go back here for a moment.
[00:00:53] So when a dependency changes all that happens is we just wipe out the cache, that's it. So that is how this laziness works. It's very cheap to invalidate a computer property. You're just clearing out the cached value and then the next time you ask for it, you will do the recalculation.
[00:01:16] This is very efficient, because you can wipe it out 30 times throughout a process by changing a whole bunch of different properties. And then only recalculate it once compared to something like an observer which would potentially be firing 30 times. And that is why we discourage observer use except when binding to something foreign to Ember like D3 or something like that.
>> Speaker 2: If the computer property returns an array and a value in the array changes, an entire new property is, cache is invalid in the entire thing?
>> Mike: Sorry, can you ask that again?
>> Speaker 2: If a computed property returns an array, and a value inside of the array changes, only part of that array changes.
[00:02:01] The entire computed property is.
>> Mike: Good question. And thank you for teeing me up for something interesting here. In older versions of Ember, we were actually very careful to return the exact same array. So that we could be very efficient of, in each for example, only updating the fifth item.
[00:02:25] And that's cuz it was very expensive to update the DOM, still is, but much less so. Now with Glimmer because we have this item potent rendering engine. And item potent simply means that multiple passes over the data will just it will be the exact same results. The same operation performed multiple times will not change things multiple times.
[00:02:52] It will just ensure it's in the same exact state. So now its totally fine to return a new array. And this is why if you look at some of the stuff that's been de-emphasized and in many cases gutted from the framework itself, all of these reduce computer properties, like the sum of the items in an array.
[00:03:16] That's no longer special in a whole bunch of code to try to be careful that we hold this thing internally and only return this same thing and manipulate it. And now dealing with array values returned from computer properties falls down exactly the same code paths as everything else.
[00:03:36] Make sense?
>> Speaker 2: Awesome.
>> Mike: I am very happy to hear that. So, I talked about abstracting computer properties a little bit. There is a concept of computed property macros. This is a fancy name for a function that returns a computed property. And so, here, we're finding, in our app, that often, we need to calculate the sum of two values.
[00:04:06] We can wrap that all in a function make it generic and then just sort of use it throughout our app wherever we need it. I very strongly encourage this pattern because this function sum lends itself extremely well to unit testing. So you've taken a lot of the logic that's necessary to perform some calculation, isolated it into a single function and so you can sort of do a lot of value in value out analysis of different scenarios.
[00:05:04] You should not have computer properties in your routes usually but your code ends up being much cleaner and much more expressive. Now we don't have a function in our component so much as we have the word sum which is very easy to read, it's very easy to understand what is c.
[00:05:20] Well, it's the sum of properties a and b. Does that make sense?
>> Speaker 2: I notice you're leaving off the namespace for Ember.computed and here Ember.computed sum. Ending up Ember in some cases and Ember computed. And that ES6 was always there for you?
>> Mike: So, you're saying that here?
>> Speaker 2: I would write Ember.computed.sum.
>> Mike: I'm defining a function called sum, I'm not using Ember computed sum.
>> Speaker 2: Okay.
>> Mike: And the value of that function, up there, down in the bottom half of the slide. I can go back here. So, you may see me use destructuring assignment on the first line, here.
>> Speaker 2: I missed the first line.
>> Mike: I'm terribly sorry. And that's a way of just grabbing computed off Ember. That is more personal style, you know. I just you put the first line of code.
>> Mike: All right. So.
>> Speaker 2: That's explains what. Little cushion on that.
>> Mike: Yeah, they're just asking where would you define this?
>> Speaker 3: Would you put it on a component or a service?
>> Mike: Where would I define the computed property?
>> Speaker 3: Yeah.
>> Mike: I would define it in the Utils folder. We haven't gone over this but the Utils, app/utils is a place where you'll typically put simple functions that are usually, highly unit-testable, it's sort of, I wanna say dumping ground, but I don't mean that in a bad sense.
[00:06:48] It's where you put your generally useful, simple utility functions and then these case computer properties are perfect thing to put there. So you can generate a util with ember-cli which would just give you a function to fill in the blank and then write a unit test for that function.
[00:07:09] But that is the perfect place for this kinda thing.