-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Add "extension types" section to style guide #158466
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
Add "extension types" section to style guide #158466
Conversation
| Optimize for readability. Write detailed documentation. | ||
| Make error messages useful. | ||
| Never use timeouts or timers. | ||
| Avoid `is`, `print`, `part of`, `extension` and `_`. | ||
| Avoid hidden dependencies: powerful systems are composed of simple, reusable parts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have strong feelings about the line I added here, but I do feel that the previous version is outdated.
Avoid
is
This advice applies to widgets, but IMO it's a blanket statement that ignores the overall advantages of type promotion.
Avoid
This is covered by a linter rule.
Avoid
part of
I agree that this is good advice, but I seldom ever see a non-Googler creating a new file; IMO we are better off keeping the below section but removing it from the summary.
Avoid
extension
That's what this PR is about!
Avoid
_
Prior to Dart 3.0, _ was exclusively used for anonymous parameter names, but now it's also meant to designate a wildcard pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This top section is intended to be just a brief tl;dr of whatever the most common mistakes are. For example, there was a time where people were frequently uploading PRs that used is instead of carefully designed polymorphism, so the is advice got promoted to the top here, and that helped. We should feel free to keep updating this section to reflect whatever is the most useful advice to give at the moment.
| [cannot be safely accessed](https://github.com/dart-lang/sdk/issues/51641) | ||
| if the receiver is a subtype that implements the interface.\ | ||
| In these cases, it's better to house these fields in an `extension` | ||
| or to restructure them into private top-level functions if possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a really weird case. Maybe I'm not understanding it correctly? Do you have an example of this?
Accessing privates in other objects is generally dubious design in the first place...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have an example of this?
Yes indeed! Went ahead and filed an issue:
(Fortunately in this case, it can be resolved without using an extension.)
|
|
||
| Prefer specifying a non-nullable supertype (e.g. `implements Object`) when | ||
| the representation type is non-nullable: this improves static analysis for | ||
| null-checks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reads more like a description of what extension types are, than advice for when it's appropriate to use them. (The heading, "Use extension types to improve an API surface", taken literally, suggests using them all the time, which is probably not what is intended.)
I would probably replace this whole section with a parenthetical sentence in the previous section that just says something like "(Unlike extension methods, the use of extension types is fine.)", maybe with a link to the Dart documentation on what extension types are, what they're useful for, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for bringing up that the heading should be changed.
As far as including a description, it seems that the dart.dev pages for extension methods and extension types are geared toward describing rather than differentiating.
I believe including a distinction in the style guide would likely help contributors better understand how they should apply to the Flutter framework, though perhaps there would be a better place for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The style guide is meant to teach people what we've learned are best practices, it's not meant to teach people Dart. We should assume people know what extension methods and extension types are, and if we feel we need to say something about extension types at all, it should be about when they're appropriate with concrete examples. But we don't need to mention every Dart feature, only those where the choice of using it or not using it, or how to use it, is not necessarily obvious (especially as shown by people submitting PRs that misuse them).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the late response here—you bring up some good points but overall I'm not completely on board.
I 100% agree that the information we choose to put in the style guide should reflect what problems or confusion we notice in PRs. I also agree with the style guide's advice regarding extension methods:
Prefer instead adding methods directly to relevant classes.
Since the dart.dev docs don't discourage either extension or extension type, there isn't much of a reason to make an explicit effort to differentiate between them, but based on interactions I've had within PR discussions, I do feel that it'd be helpful to draw this distinction here.
I'm interested to hear further thoughts you have (along with others' perspectives), whether it's through this comment thread or the tentative upcoming Dash Forum :)
43eab11 to
d7b9c4b
Compare
d7b9c4b to
0256d79
Compare
chunhtai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general changing style guide like this should probably go through a dash forum. It required a more wider audience for this kind of change
| * `SimpleAPI` is an _extension type_. | ||
| * `SomeAPI` is the _representation type_ (and `_someAPI` is the "representation field"). | ||
| * `Object` is the _supertype_. | ||
| * `run()` is "a `SimpleAPI` method". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These bullet points were inspired by the canoncial terminology section, though the goal here is to help establish the distinction between extension & extension type so contributors have a better understanding of how each is used appropriately.
| It's the job of the reviewer to check that all these are present when reviewing a PR. | ||
|
|
||
|
|
||
| ### Effect of `extension` on API usability. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I currently feel that the best spot for this is under Conventions.)
|
Marking as draft for now, will reopen after a forum! |
|
This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
|
(triage): This is waiting on the dash forum. |
|
No longer waiting on a dash forum! |
View change (in markdown format)
Extension types can't add instance variables or override
Objectfields (==,hashCode, ortoString()), but the "static-only interface" gives complete control over the API surface.An
extension typecan implement a supertype and redeclare existing fields, even when it normally wouldn't be a valid override:Examples
Material.of(context)in the test framework #156341 (comment)TappableLabelextension type #158465