Skip to content

Allow the Dart team (or any dependency) to deprecate APIs without breaking the tree #143312

Closed
@matanlurey

Description

@matanlurey

I'm not going to spend too much time on this issue, but I think it should be filed for transparency before making any change.

Over the years, we've closed the Flutter tree(s) when a dependency, usually (but not always, sometimes a package) when the Dart SDK introduces a deprecation. This typically causes a cascade of reverts, filed P0s, and landings of // ignore: deprecation, of which Flutter currently has 150+ of these.

Like most style and repository decisions, there are a set of tradeoffs you get. For example, this tradeoff puts a lot of pressure on the Dart SDK team and the Dart engine team/rollers (we're often the first ones to see a failure and have to revert, stop the roller, notify the Dart team), discourages the Dart team from deprecating old or brittle APIs, etc. On the other hand, it's true that we risk an API being deprecated without any working replacement (but that's also true with the current system - see also flutter_driver).

There is not a perfect system, there is perhaps no better example than the fact we don't apply this standard to ourselves. I'm planning to work with @Piinks and @goderbauer on periodically reviewing deprecation warnings, and we'll track it similar to any other form of technical debt that doesn't turn the tree red (Gradle versions, XCode on CI, the list goes on).

For posterity, here are some use cases that become worse after this change:

It's easier to introduce new usages of existing (deprecated) code

Previously, imagine that dart:foo#bar() was deprecated.

Someone would go into all call-sites, and add the following:

import 'dart:foo';

void main() {
+ // ignore: deprecated_member_use
  bar();
}

Then, subsequent additions of bar() would break CI.

Mitigation: None. However, the only deprecated members we break on are dependencies to Flutter, which happen to be packages owned by the Dart or Flutter teams. That is, we can rely on the fact that the previous APIs (a) work and (b) will get cleaned up when the APIs are eventually removed.

We could add tooling to detect "new introductions" of deprecated members, but that is non-blocking to this issue.

It's harder to track how many deprecations exist

Previously, you could grep for deprecated_member_use.

Mitigation: Now, you'd have to change (locally) analysis_options.yaml.

We could add tooling to report the numbers to a dashboard of some sort, similar to other forms of technical debt.

IDE support becomes "all or nothing"

One option that was discussed was making deprecations a hint (non-warning/error), and making hints non-breaking.

However, team members were not excited about the idea of 10s or 100s of diagnostics existing in the IDE.

Mitigation: N/A, we didn't choose this approach.

You could filter hints out of the IDE if you're not working on a file, or we could add custom tooling.


Feedback is welcome, but of course with all forms of feedback, we can't guarantee that it will change the outcome.

I'll shortly file a follow-up issue for a request for better tooling to track deprecations.

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: annoyanceRepeatedly frustrating issues with non-experimental functionalityc: contributor-productivityTeam-specific productivity, code health, technical debt.c: proposalA detailed proposal for a change to Flutterc: tech-debtTechnical debt, code quality, testing, etc.engineflutter/engine repository. See also e: labels.frameworkflutter/packages/flutter repository. See also f: labels.packageflutter/packages repository. See also p: labels.team-engineOwned by Engine teamtriaged-engineTriaged by Engine team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions