Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate computed().volatile() #370

Merged
merged 1 commit into from
Oct 5, 2018

Conversation

pzuraq
Copy link
Contributor

@pzuraq pzuraq commented Aug 31, 2018

@mike-north
Copy link
Contributor

mike-north commented Aug 31, 2018

Because the only path forward involves using native classes, does the deprecation of .volatile() need to be tied to the deprecation of Ember.Object.extend({}) style syntax? As long as we support ES5-style syntax (I've heard nothing about this going away) we should also support a deprecation-free way to get a volatile-ish thing.

That being said, I'm a fan of moving in this direction for most apps. Maybe all this needs is a plan for an addon to opt back in to the old behavior, with no deprecation warnings.

looks like there's an ES5 path forward: #370 (comment) Thanks for pointing this out @rwjblue

@pzuraq
Copy link
Contributor Author

pzuraq commented Aug 31, 2018

If we do not provide some other way to declare volatile properties, then yes it would have to be available until ES5 classes are deprecated and removed. I have proposed a timeline for discussion in #338, but it really only sets a lower bound on removal - the earliest we could completely remove them is by Ember 5.

@rwjblue pointed out a way we could support getters/setters in ES5 syntax without modification below, so we won't need to tie them together.

@rwjblue
Copy link
Member

rwjblue commented Aug 31, 2018

Because the only path forward involves using native classes, does the deprecation of .volatile() need to be tied to the deprecation of Ember.Object.extend({}) style syntax?

No 😸, and native classes aren't the only way forward (though the alternatives are less ergonomic than ES classes).

For example, you can migrate from:

export default Component.extend({
  init() {
    this._super(...arguments);
    this._foo = 0;
  },

  foo: computed(function() {
    return this._foo++;
  }).volatile()
});

To:

const FooBar = Component.extend({
  init() {
    this._super(...arguments);
    this._foo = 0;
  }
});

Object.defineProperty(FooBar.prototype, 'foo', {
  get() {
    return ++this._foo;
  }
});

export default FooBar;


# Transition Path

Native getters and setters will _only_ work on native classes, due to how the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: update this to clarify that getter/setter based properties with Object.defineProperty still work with older versions of Ember.Object

@simonihmig

This comment has been minimized.

@rwjblue

This comment has been minimized.

@tomdale
Copy link
Member

tomdale commented Sep 12, 2018

I'm 👍 on moving away from volatile semantics, but my only concern is about the timing of this deprecation. If there are use cases where people are legitimately using .volatile(), I think they will feel (correctly) like they are being pushed towards native class syntax. The proposed workaround of Object.defineProperty feels pretty bad in comparison. Are we confident that the majority of classes can be moved to native syntax if need be?

Ultimately, this functionality is so rarely used I don't think it really matters either way. We should just make sure that the O.dP workaround is not going to cause people to flip tables. FWIW, I only found three uses of it in the entire linkedin.com Ember app, although I may have missed some usage in our dependency graph.

@tomdale
Copy link
Member

tomdale commented Sep 14, 2018

We discussed this at the core team meeting today and are in favor of moving this deprecation to FCP.

One of the concerns raised was whether the migration path away from volatile was "ready" yet, or if we should wait until things like native JS classes are more fully adopted so it's easier to migrate this behavior to native getters.

Ultimately, we believe that this feature is very rarely used, and when it is used, it is often used incorrectly. The specific semantics of volatile() are confusing, and usually misunderstood by people who pick it up as a tool. We also believe that almost all cases using .volatile() can be better modeled with other API.

For example, one use case people sometimes use volatile() to solve is time-based computed properties. For example, there might be a CP like this:

now: computed(function() {
  return Date.now();
}).volatile()

However, this modeling is not ideal because if this value is used in a template, the template will render once and never update again. A better way to model this is to use a timer to set a static property on a regular basis:

init() {
  setInterval(() => {
    this.set('now', Date.now());
  });
}

Now other CPs can depend on this now property and still be invalidated and updated correctly if they're used in a template.

For cases that are truly volatile but pull-based (i.e. they are never going to be used in a template or as a dependent key for a CP that will be used in a template, but called directly only when needed), they should be turned into either a method or a native getter. Because CPs invalidate and update automatically in 99% of cases, using a CP for something that is actually volatile gives downstream consumers of that property a false intuition about its behavior.

One annoying limitation in the current EmberObject.extend() implementation is that it's not ergonomic to define native getters. To add a native getter to one of these classes, developers can use Object.defineProperty (as noted in the discussion above). An alternative workaround is to create a second subclass via native syntax, e.g.:

const _MyClass = Ember.Object.extend({
  // ...
});

class MyClass extends _MyClass {
  get now() {
    return Date.now();
  }
}

Because of how rare real world use of volatile() is, we are comfortable with these less-than-ergonomic workarounds. If anyone objects to the verbosity, they can always disable the deprecation and wait until they move the class to native class syntax. But, to reiterate, we believe the problem can usually be modeled in a better way anyway. Let's just make sure we have a good deprecation guide that outlines the alternatives.

@tomdale tomdale assigned tomdale and unassigned tomdale Sep 14, 2018
@dgeb dgeb merged commit c4c0879 into emberjs:master Oct 5, 2018
@dgeb
Copy link
Member

dgeb commented Oct 5, 2018

With no further comments, we decided to merge this in the core team meeting today.

Thanks @pzuraq! 🎉

@rwjblue rwjblue self-assigned this Feb 12, 2019
buschtoens pushed a commit to ClarkSource/ember-css-modules-config that referenced this pull request Apr 3, 2019
Bumps [ember-source](https://github.com/emberjs/ember.js) from 3.8.0 to 3.9.0.
<details>
<summary>Release notes</summary>

*Sourced from [ember-source's releases](https://github.com/emberjs/ember.js/releases).*

> ## v3.9.0-beta.5
> ### CHANGELOG
> 
> - [#17733](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17733) [BUGFIX] Assert on use of reserved component names (`input` and `textarea`)
> 
> ## v3.9.0-beta.4
> ### CHANGELOG
> 
> - [#17710](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17710) [BUGFIX] Allow accessors in mixins
> 
> ## v3.9.0-beta.3
> ### CHANGELOG
> 
> - [#17684](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17684) [BUGFIX] Enable maximum rerendering limit to be customized.
> - [#17691](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17691) [BUGFIX] Ensure tagForProperty works on class constructors
> 
> ## v3.9.0-beta.2
> ### CHANGELOG
> 
> - [#17618](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17618) [BUGFIX] Migrate autorun microtask queue to Promise.then
> - [#17649](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17649) [BUGFIX] Revert decorator refactors
> 
> ## v3.9.0-beta.1
> ### CHANGELOG
> 
> 
> - [#17470](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17470) [DEPRECATION] Implements the Computed Property Modifier deprecation RFCs
>   * Deprecates `.property()` (see [emberjs/rfcs#375](https://github.com/emberjs/rfcs/blob/master/text/0375-deprecate-computed-property-modifier.md)
>   * Deprecates `.volatile()` (see [emberjs/rfcs#370](https://github.com/emberjs/rfcs/blob/master/text/0370-deprecate-computed-volatile.md)
>   * Deprecates computed overridability (see [emberjs/rfcs#369](https://github.com/emberjs/rfcs/blob/master/text/0369-deprecate-computed-clobberability.md) 
> - [#17488](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17488) [DEPRECATION] Deprecate this.$() in curly components (see [emberjs/rfcs#386](https://github.com/emberjs/rfcs/blob/master/text/0386-remove-jquery.md))
> - [#17489](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17489) [DEPRECATION] Deprecate Ember.$() (see [emberjs/rfcs#386](https://github.com/emberjs/rfcs/blob/master/text/0386-remove-jquery.md))
> - [#17540](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17540) [DEPRECATION] Deprecate aliasMethod
> - [#17487](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17487) [BUGFIX] Fix scenario where aliased properties did not update in production mode
</details>
<details>
<summary>Changelog</summary>

*Sourced from [ember-source's changelog](https://github.com/emberjs/ember.js/blob/master/CHANGELOG.md).*

> # Ember Changelog
> 
> ### v3.9.0-beta.5 (March 25, 2019)
> 
> - [#17733](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17733) [BUGFIX] Assert on use of reserved component names (`input` and `textarea`)
> 
> ### v3.9.0-beta.4 (March 11, 2019)
> 
> - [#17710](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17710) [BUGFIX] Allow accessors in mixins
> 
> ### v3.9.0-beta.3 (March 4, 2019)
> 
> - [#17684](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17684) [BUGFIX] Enable maximum rerendering limit to be customized.
> - [#17691](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17691) [BUGFIX] Ensure tagForProperty works on class constructors
> 
> ### v3.9.0-beta.2 (February 26, 2019)
> 
> - [#17618](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17618) [BUGFIX] Migrate autorun microtask queue to Promise.then
> - [#17649](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17649) [BUGFIX] Revert decorator refactors
> 
> ### v3.9.0-beta.1 (February 18, 2019)
> 
> - [#17470](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17470) [DEPRECATION] Implements the Computed Property Modifier deprecation RFCs
>   * Deprecates `.property()` (see [emberjs/rfcs#375](https://github.com/emberjs/rfcs/blob/master/text/0375-deprecate-computed-property-modifier.md)
>   * Deprecates `.volatile()` (see [emberjs/rfcs#370](https://github.com/emberjs/rfcs/blob/master/text/0370-deprecate-computed-volatile.md)
>   * Deprecates computed overridability (see [emberjs/rfcs#369](https://github.com/emberjs/rfcs/blob/master/text/0369-deprecate-computed-clobberability.md) 
> - [#17488](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17488) [DEPRECATION] Deprecate this.$() in curly components (see [emberjs/rfcs#386](https://github.com/emberjs/rfcs/blob/master/text/0386-remove-jquery.md))
> - [#17489](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17489) [DEPRECATION] Deprecate Ember.$() (see [emberjs/rfcs#386](https://github.com/emberjs/rfcs/blob/master/text/0386-remove-jquery.md))
> - [#17540](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17540) [DEPRECATION] Deprecate aliasMethod
> - [#17487](https://github-redirect.dependabot.com/emberjs/ember.js/pull/17487) [BUGFIX] Fix scenario where aliased properties did not update in production mode
</details>
<details>
<summary>Commits</summary>

- [`8df20e9`](emberjs/ember.js@8df20e9) Release v3.9.0
- [`2b9ee17`](emberjs/ember.js@2b9ee17) Add v3.9.0 to CHANGELOG
- [`bfe670c`](emberjs/ember.js@bfe670c) Bump router_js
- [`2f8b8ba`](emberjs/ember.js@2f8b8ba) [DOCS beta] remove component nesting docs
- [`0270001`](emberjs/ember.js@0270001) Release v3.9.0-beta.5
- [`1e2672c`](emberjs/ember.js@1e2672c) Add v3.9.0-beta.5 to CHANGELOG
- [`37d0a11`](emberjs/ember.js@37d0a11) Fix docs test
- [`86999a7`](emberjs/ember.js@86999a7) Post-cherry-pick lint fixup
- [`fff729a`](emberjs/ember.js@fff729a) [DOC RouteInfo] Fix grammar, spelling, and formatting
- [`b179dfd`](emberjs/ember.js@b179dfd) added param "name of the block" for the API document of has-block and has-blo...
- Additional commits viewable in [compare view](emberjs/ember.js@v3.8.0...v3.9.0)
</details>
<br />

[![Dependabot compatibility score](https://api.dependabot.com/badges/compatibility_score?dependency-name=ember-source&package-manager=npm_and_yarn&previous-version=3.8.0&new-version=3.9.0)](https://dependabot.com/compatibility-score.html?dependency-name=ember-source&package-manager=npm_and_yarn&previous-version=3.8.0&new-version=3.9.0)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
If all status checks pass Dependabot will automatically merge this pull request during working hours.

[//]: # (dependabot-automerge-end)

---

**Note:** This repo was added to Dependabot recently, so you'll receive a maximum of 5 PRs for your first few update runs. Once an update run creates fewer than 5 PRs we'll remove that limit.

You can always request more updates by clicking `Bump now` in your [Dependabot dashboard](https://app.dependabot.com).

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot ignore this [patch|minor|major] version` will close this PR and stop Dependabot creating any more for this minor/major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
- `@dependabot badge me` will comment on this PR with code to add a "Dependabot enabled" badge to your readme

Additionally, you can set the following in the `.dependabot/config.yml` file in this repo:
- Update frequency (including time of day and day of week)
- Automerge options (never/patch/minor, and dev/runtime dependencies)
- Pull request limits (per update run and/or open at any time)
- Out-of-range updates (receive only lockfile updates, if desired)
- Security updates (receive only security updates, if desired)

Finally, you can contact us by mentioning @dependabot.

</details>

[//]: # (dependabot-no-ci-start)

---
⚠️ **Dependabot won't automerge this PR as it didn't detect CI on it** ⚠️ 

You have automerging enabled for this repo but Dependabot didn't detect any CI statuses or checks. You can disable automerging on this repo by editing the `.dependabot/config.yml` file in this repo.

[//]: # (dependabot-no-ci-end)
@ghost ghost mentioned this pull request Jun 21, 2019
24 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants