Computed Properties and cache invalidation - When to add cache invalidation key


#1

Let’s say you have a simple computed property (for example && discussion purposes, not for refactor :slight_smile: or discussion on how to make it better) -

showBio: computed('hasArtwork', 'jobTitle', function() {
  if (this.hasArtwork) {
    return true;
  }
  return this.jobTitle ? true : false;
});

vs

showBio: computed(function() {
  if (this.hasArtwork) {
    return true;
  }
  return this.jobTitle ? true : false;
});

I’ve been a part of the camp where I only add the cache invalidation keys when I can test and prove that it is needed to add cache invalidation keys. However, I’ve also seen where ppl prefer to add any property inside the computed to the cache invalidation keys with or without understanding if it is actually needed.

I’m curious as to what other people’s views on this are - scalpel approach vs splat approach to adding cache invalidation keys.


#2

I’m not sure how your example exactly refers to your question, because you need both keys all the time to calc showBio (so can’t understand the question by 100%). Could you be more clear pls? Everything depends on a case.

There may be situations when people probably only add keys A, C to a computed property that returns A + B + C, but just because C is calculated with B above, and it doesn’t look very explicit + only depends on some other logic that may be unknown.

P.S.

showBio: computed.or('hasArtwork', 'jobTitle');

#3

I would ignore the code example. That just provides some context. I’m just referring to a general case of always adding any key found inside the computed to the cache invalidation keys and was curious as to people’s opinions on it.

Moreover, you may not necessarily need both hasArtwork && jobTitle as the cache invalidation keys. For example somewhere you get showBio, which requires no cache invalidation keys. However, to recalculate showBio you can add one or both keys to the cache invalidation keys. Depending on how your data flows through your application, it may be safest to just add both hasArtwork && jobTitle as cache invalidation keys; however, that may not always be the case. I’ll have to dig up an example.


#4

Then, as I said, it’s abt explicit/implicit approach to your properties. I used to have sometimes cases without using 100% of dependant keys (as I explained above in the comment) for some complicated logic of computed props.

I think if you provide a more precise example, it might help with better advice.


#5

Explicit vs implicit is a good way to think about it.

I’m not sure a better example here is needed as it is even simpler than that. I just may not have explained it well. :slight_smile:

Say this computed is in a Component.

showBio: computed('hasArtwork', 'jobTitle', function() {

vs

showBio: computed(function() {

If you only ask for showBio once, there is no need to add any cache invalidation keys. I have been of the camp where only if I can prove that I need to recalculate should I add cache invalidation keys. Other people say, to be safe, the keys should be added.

My general question was what people preferred - 1. Take a scapel approach to adding cache invalidation keys or 2. Take a splat approach to adding cache invalidation keys.

Since I’m apart of camp 1, it would be great to hear specific reasons as to why taking the approach of simply adding them for the sake of adding them is a good idea.


#6

I guess the core part of all that is to be safe :slight_smile: You never know when someone will change any of that values, e.g. extending your component by changes any of the keys. So… In simple cases: always add keys — less bugs, save time fixing them.


#7

I’m a big fan of being able to verify the correctness of code without having to understand the whole context/logic around it to whatever degree possible. I think there’s a term for this, but I can’t remember it. Anyway, most of the time it’s impossible, but this is a good example where I think it is possible.

If I’m looking at a computed property because I’m worried there might be a cache invalidation problem or something, I’d much much rather just be able to match up each property access with a dependent key and say “welp, that’s all correct” than have to spend time thinking and investigating each of the properties that aren’t listed as dependencies to figure out why they aren’t listed. Like, a mechanical verification instead of an intellectual/logical one.

Slightly less preferable is to leave some out and comment clearly why they are gone (but as previously mentioned, comments can easily get out of sync with code/logic/architecture).


#8

Say this computed is in a Component.

This is a perfect way to start. We’re fortunate to know that the model would never change and that we’d have to compute this property exactly once & that it won’t have to be recomputed in that component’s lifecycle.

Knowing this, I’d suggest we rewrite it in the form below which can express the intention behind it by reading the component code in isolation.

init() {
  this._super(...arguments);
  let shouldShowBio = this.hasArtwork ? this.hasArtwork : this.jobTitle;
  this.set('showBio',  shouldShowBio);
}

It can be made a computed property with dependent keys when we actually know that it’ll be changed during the component’s lifecycle.


#9

The example could be with just one key. The question was a bit more general and centered about the cache invalidation keys and not the specific code (and how it could be made better and what not).

showBio: computed('hasArtwork', function() {
  if (this.hasArtwork) {
    return true;
  }
  return this.jobTitle ? true : false;
});

#10

Ah my bad, I wanted to show how we didn’t have to create a computed property if it was a one time operation.

I’d personally opt for adding all properties used in the computed, i.e., in this case hasArtwork and jobTitle so that consumers of this component aren’t surprised by the fact that it doesn’t update when they start updating the models that get passed down to the component during its lifespan.