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

Helper Managers #625

Merged
merged 9 commits into from
May 22, 2020
Merged

Helper Managers #625

merged 9 commits into from
May 22, 2020

Conversation

pzuraq
Copy link
Contributor

@pzuraq pzuraq commented May 6, 2020

Comment on lines +286 to +289
Helper managers are a low-level construct that is generally only meant to be
used by experts and addon authors. As such, it will only be taught through API
documentation. In addition, for precision and clarity, the API docs will include
snippets of TypeScript interfaces where appropriate.
Copy link
Contributor

@chriskrycho chriskrycho May 7, 2020

Choose a reason for hiding this comment

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

This is good, but I think probably somewhat incomplete. These should certainly be covered in API docs, but API docs are insufficient for actually building the appropriate mental model for consumers. (Both the CLI and Data docs here are prime examples of this problem historically for Ember! Even when they had full coverage of the API surface, it has been difficult to learn or master.)

Effective documentation includes not only reference materials but also tutorials (introducing the ideas in the first place), how-to-guides (like “cookbooks”—solving specific problems), and explanations. This RFC itself would suffice for the explanation, and API docs will handle reference materials, but I think we should also identify what appropriate kinds of tutorial and how-to material are appropriate here—presumably in an Advanced Guides section for addon authors specifically.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue here is this is not even a "standard" advanced Ember topic. I would say the current advanced section (In-Depth Topics) is currently stuff that most intermediate and senior Ember devs will eventually need to know or learn. Ideally, most Ember apps will never include a custom manager directly, and most senior Ember devs will not have to write one.

I think a guide would be useful, and I'd be happy to write one for managers in general, but I'm not sure where that would live. Maybe "Advanced Topics" would be good to add to the guides, we've shied away from the term because we didn't want to discourage beginners who are curious (thus the name "in-depth") but this would be a time when that would make sense.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just wanted to pitch in that this is something the learning team has considered previously and recently discussed at one of the meeting. If there's interest enough interest to kick-off an RFC…

Copy link
Contributor

Choose a reason for hiding this comment

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

I’d be happy to co-author, @locks! I actually mentioned as much to @pzuraq in a DM very recently!

rwjblue
rwjblue previously requested changes May 9, 2020
text/0625-helper-managers.md Outdated Show resolved Hide resolved
text/0625-helper-managers.md Outdated Show resolved Hide resolved
text/0625-helper-managers.md Show resolved Hide resolved
text/0625-helper-managers.md Outdated Show resolved Hide resolved

### Hooks

#### `createHelper`
Copy link
Member

Choose a reason for hiding this comment

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

The prose does not define if this hook is auto-tracked. I personally think it should be (but I vaguely recall that we may disagree here?), but regardless of which way we go the design should explicitly call out if it is or is not auto-tracked.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue with autotracking the creation hook is that it would break precedent, and we don't really have a clear meaning for it. We could call getValue or runEffect the next time that dirties, but it is already effectively "dirty" because we will call those hooks anyways, and we don't want to teardown and recreate the helper because then we're taking control away from the user (they can no longer control their own tracking semantics).

Instead, users can use the cache API to wrap any code that they want to autotracking in this hook, and they can do anything they want with that information. They could return a cached value in the first getValue, they could destroy and recreate the instance of the helper, etc.

Really, createHelper just means "you exist in the template now", IMO. We shouldn't define any semantics for it beyond that.

Copy link
Member

@rwjblue rwjblue May 9, 2020

Choose a reason for hiding this comment

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

FWIW, I wasn't trying to convince you to change it (though I think we should 😉), but the fact that it is missing from being explicitly stated is my fundamental problem here.

Not saying that it is or is not expected to be auto-tracked will cause people to file bug reports when they expect one version or the other and are surprised. In an "auto tracking world", when things are intentionally not auto-tracked it should be clearly stated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a section noting that the createHelper function is not tracked, and strategies for how users can track instance creation if they want to. We can keep discussing whether or not the hook should be tracked, I think the biggest question there is if it is, what would it do when it invalidates?

Copy link
Member

Choose a reason for hiding this comment

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

I think the biggest question there is if it is, what would it do when it invalidates?

Ya, this is exactly the question.

@krisselden - I think you had thoughts here, what do you think?

create the helper manager. It will be cached, and in subsequent lookups it the
cached helper manager will be used instead.

Only one helper manager exists per helper factory, so many helpers will end up
Copy link
Member

Choose a reason for hiding this comment

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

per helper factory

I don't think the term "helper factory" is actually defined here (this is the only reference in the whole document). Would helper definition work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm, I think it was supposed to be "one helper manager per helper manager factory". The semantics are that we weakmap the function that produces the manager to the instance of the manager, so you could use the same factory function with many different definitions, and they would all use the same instance. That's the thing we need to capture here.

Copy link
Member

Choose a reason for hiding this comment

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

Ya, my concern wasn't about that coupling, but it was with the terminology used to talk about which thing the factory function is associated with. There is no conceptual thing introduced in this RFC as a "helper factory". There is a HelperDefinition (which is what this argument is actually called throughout the rest of this document), but no "helper factory".

Also, conceptually calling this a "helper factory" is misleading. There is no reason for us to infer that this value is a "factory" at all (factory usually inferring that you can do new Foo() or Foo.create() in Ember parlance). For example, it is perfectly valid for this value to be {}.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right, but again, I'm not talking about the definition, I'm talking about the function that creates the helper manager itself. That is a different thing entirely, which we need a new term for, it is not the HelperDefinition

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, why would we do a different thing here than for component managers / modifier managers? We do not cache the factory instance on the manager factory function, we call the manager factory function for each component base class we find.

See this demo repo if you'd like to fact check me 😜:

https://github.com/rwjblue/manager-invocation-demo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, this is my mistake then. This is how managers work in Glimmer.js currently, I must've forgotten where we put that optimization. It looks like it first came from ember-functional-modifiers, which makes sense because that addon needed to assign the same modifier manager to many functions and we wanted to avoid creating an instance per function: https://github.com/ember-modifier/ember-modifier/blob/master/addon/-private/functional/modifier.js

Personally I think this optimization is common enough that we should consider making it the default, but we can make it something users have to implement if they need it. I'm not sure if it would be a breaking change to update the existing managers - in theory, they shouldn't depend on instance state per-definition (they may depend on state overall, or per owner), that would somewhat defeat the purpose.

Copy link
Member

@rwjblue rwjblue May 9, 2020

Choose a reason for hiding this comment

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

Personally I think this optimization is common enough that we should consider making it the default

Ya, I think that might be fine, but adding caching for something that is super light weight (new Something() where that constructor does basically nothing) is actually going to make this slower a lot of times.

Even if we do this, the prose here is wrong. It is not one per manager factory function, it is one per manager factory function per owner. I think that is conceptually fine though, just needs tweaking in the prose to be clearer I guess.

Copy link
Member

Choose a reason for hiding this comment

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

If we do that, we should also consider doing the same for the other manager types. I'd hate to introduce another small difference while our overall goal is to reduce the differences. I think we can just do the implementation change for the others though, I don't particularly think it is a breaking change or anything.

text/0625-helper-managers.md Outdated Show resolved Hide resolved
text/0625-helper-managers.md Outdated Show resolved Hide resolved
text/0625-helper-managers.md Show resolved Hide resolved
text/0625-helper-managers.md Show resolved Hide resolved
Chris Garrett and others added 2 commits May 9, 2020 10:50
Co-authored-by: Robert Jackson <me@rwjblue.com>
Co-authored-by: Chris Krycho <hello@chriskrycho.com>
Co-authored-by: Robert Jackson <me@rwjblue.com>
**Never**
- called if the `hasValue` capability is disabled

#### `runEffect`
Copy link
Member

Choose a reason for hiding this comment

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

Can you add some prose to clarify what the behavior is in SSR / FastBoot? As you know we do not run modifiers in SSR, and in general SSR does not have the ability to run update opcodes. I could easily imagine that we say runEffect should not run in SSR (essentially saying that you shouldn't have external side effects), but we should be clear and we should consider it carefully.

Copy link
Member

Choose a reason for hiding this comment

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

I think we probably should say they don't run in SSR for now. I can absolutely imagine wanting them eventually in SSR, but I think the safe default to start with (especially while introducing this new concept) is to disallow it. In the future, we can add a capability to explicitly declare that you do or do not want to run in SSR which means this isn't really blocking future functionality.

@rwjblue rwjblue self-requested a review May 14, 2020 21:45
@rwjblue rwjblue dismissed their stale review May 14, 2020 21:45

Primary issues addressed!

@rwjblue
Copy link
Member

rwjblue commented May 15, 2020

We discussed this in todays framework meeting, and are in favor of moving forward here!

Look out! It's final comment period time!! 💬 🎭

@rwjblue
Copy link
Member

rwjblue commented May 22, 2020

ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG ZOMG

LETS DO IT!!!!!

@rwjblue rwjblue merged commit 26a9a51 into master May 22, 2020
@rwjblue rwjblue deleted the helper-managers branch May 22, 2020 19:27
@BryanCrotaz

This comment has been minimized.

@rwjblue

This comment has been minimized.

rwjblue added a commit to ember-cli/babel-plugin-ember-modules-api-polyfill that referenced this pull request Sep 29, 2020
Adds Helper Manager and `invokeHelper` APIs from emberjs/rfcs#625 and
emberjs/rfcs#626.
wagenet added a commit that referenced this pull request Mar 13, 2023
bmish added a commit to bmish/emberjs-rfcs that referenced this pull request May 21, 2023
* master: (56 commits)
  Fix code examples & add ember-cli release version in emberjs#637
  Update FCP guidance to include Discord
  Update RFC 085421 ready-for-release PR URL
  Advance RFC {{ inputs.rfc-number }} to Stage ready-for-release
  feat: EmberData Cache v2.1
  finalize lifetimes
  Update text/0860-ember-data-request-service.md
  Update RFC 496, typos, correct field name
  add note
  chore: update RequestService url with finalized design details
  Move emberjs#331 deprecate-globals-resolver to recommended
  Correct metadata for emberjs#487 custom model classes
  Move emberjs#625 helper-managers to recommended
  Add release date and version for 776
  Update RFC 0776 released PR URL
  Advance RFC {{ inputs.rfc-number }} to Stage released
  Update RFC 0739 ready-for-release PR URL
  Advance RFC {{ inputs.rfc-number }} to Stage ready-for-release
  Deprecate `ember-mocha`
  Add title of RFC to advancement PR titles
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Final Comment Period T-framework RFCs that impact the ember.js library T-templates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants