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

Components: Document our deprecation procedures #61099

Open
mirka opened this issue Apr 25, 2024 · 12 comments
Open

Components: Document our deprecation procedures #61099

mirka opened this issue Apr 25, 2024 · 12 comments
Labels
[Package] Components /packages/components [Type] Discussion For issues that are high-level and not yet ready to implement.

Comments

@mirka
Copy link
Member

mirka commented Apr 25, 2024

What problem does this address?

In the past, there has been a lot of ambiguity in our back compat policy. We've been working to bring more clarity around these issues, through efforts like Private APIs and removing __experimental prefixes (#59418).

Here, I'd like to increase clarity around component deprecations. The goal of this is twofold:

  • Minimize uncertainty and disruption for extenders, by setting clearer expectations.
  • Simplify the decision-making process for maintainers, by having unambiguous guidelines.

What is your proposed solution?

A "deprecation", at the very basic level, means that we don't encourage new usages of the component.

There are two reasons we may feel this way:

  • Reduce maintenance cost. Some components are not used enough to justify their continued maintenance. In general, anything that is marked as deprecated will no longer receive enhancements or bug fixes.
  • Encourage use of a better alternative. There may be a new, improved version in the component library. Or, it's now easier to use standard HTML elements and CSS, rather than a component that abstracted or polyfilled it.

If there is no big harm in keeping existing usages, we will be as unobtrusive as possible about the deprecation ("passive deprecation"). On the other hand, if there are strong enough reasons to discourage continued usage, we will also log a deprecation warning in the console and write a Dev Note ("soft deprecation"). Additionally, if the bundle size cost justifies the eventual removal of the code, the deprecation warning will include an end version ("hard deprecation").

If circumstances change, a component may later progress into a stronger level of deprecation.

Deprecation levels

Passive deprecation

  • Mark with TypeScript @deprecate
  • Update docs (readme, JSDoc, Storybook)

Soft deprecation

  • Mark with TypeScript @deprecate
  • Update docs (readme, JSDoc, Storybook)
  • Dev note
  • deprecated() warning with no end version

Hard deprecation

  • Mark with TypeScript @deprecate
  • Update docs (readme, JSDoc, Storybook)
  • Dev note
  • deprecated() warning with end version
  • Delete from package when end version arrives
flowchart TD
  1{{"`Do we encourage _new_ usages of this component?`"}}
  1 -- Yes --> 2[Yay!]
  1 -- No --> 3{{"`Are there strong reasons to discontinue _existing_ usage?`"}}
  3 -- Yes --> 4{{"`Is the bundle size cost big enough to justify completely deleting the component?`"}}
  3 -- No --> pdep
  4 -- Yes --> hdep
  4 -- No --> sdep

  subgraph pdep ["Passive Deprecation"]
    pdep1[TypeScript @deprecate]
    -.- pdep2[Update docs]
  end

  subgraph sdep ["Soft Deprecation"]
    sdep1[TypeScript @deprecate]
    -.- sdep2[Update docs]
    -.- sdep3[Dev note]
    -.- sdep4["deprecated() with no end version"]
  end

  subgraph hdep ["Hard Deprecation"]
    hdep1[TypeScript @deprecate]
    -.- hdep2[Update docs]
    -.- hdep3[Dev note]
    -.- hdep4["deprecated() with end version"]
    -.- hdep5[Delete from package when end version arrives]
  end
@mirka mirka added [Package] Components /packages/components [Type] Discussion For issues that are high-level and not yet ready to implement. labels Apr 25, 2024
@mirka
Copy link
Member Author

mirka commented Apr 25, 2024

It is not easy to strike a balance between all the concerns involved (consumer disruption, discoverability, maintenance cost, bundle size, etc).

With that in mind though, please chime in with any feedback that might be relevant. (Including but not limited to: @WordPress/outreach @WordPress/gutenberg-components)

@youknowriad
Copy link
Contributor

Great initiative, I think we should not limit this to components. I think the same constraints apply to any API.

@youknowriad
Copy link
Contributor

Delete from package when end version arrives

The only change I'd make the flow chart above, is that before actually doing this. I'd check existing usage using wp-directory.net. If the impact of removing an API is still big, I'd do make an outreach campaign (post, contact plugin authors) and potentially delay the removal by one or two versions.

@annezazu
Copy link
Contributor

+1 to what Riad said! I've been a part of those efforts more than a few times and I think it goes a long way.

@t-hamano
Copy link
Contributor

I found out that there is already documentation regarding backwards compatibility policy:

Backward Compatibility – Block Editor Handbook | Developer.WordPress.org

We may also find the discussion in the core ticket below helpful.

#49957 (Adopt a policy to remove deprecated functions) – WordPress Trac

@mirka
Copy link
Member Author

mirka commented Apr 26, 2024

I think we should not limit this to components. I think the same constraints apply to any API.

Probably. If this works out for the components case, I think it can be adapted into the general API case, with some tweaks in procedure and language.

I found out that there is already documentation regarding backwards compatibility policy

Yes, the intention is not to replace that, but to supplement a missing part of it. We were frequently running into repetitive discussions about the deprecation procedures, because we didn't have a common framework that acknowledged how not all deprecations are equal.

@peterwilsoncc
Copy link
Contributor

I think WordPress needs a consistent deprecation policy that covers both JavaScript and PHP. It's too confusing for implementers if one part of the code base has one policy, another part of the code base a different policy. From an implementation perspective, it's all the same.

To that end, I suggest a proposal be written up on make/core so all participants can be aware of it.

@mcsf
Copy link
Contributor

mcsf commented May 2, 2024

This makes sense, with the provisions already mentioned by Riad, Peter, etc.

My only note is that the messaging seems to stress "bundle size cost" as the only meaningful reason for a hard deprecation. In the narrow context of the Components package, I understand why (a deprecated component or prop is relatively easy to isolate, thereby mitigating the cost in code complexity), but I think it's sensible to explain that there may be other costs to be weighed empirically and not a priori.

@mirka
Copy link
Member Author

mirka commented May 7, 2024

I think WordPress needs a consistent deprecation policy that covers both JavaScript and PHP. It's too confusing for implementers if one part of the code base has one policy, another part of the code base a different policy. 

The only concern I have with making a universal policy covering both JS and PHP is that, I personally have no practical experience maintaining the non-components JS packages, much less the PHP APIs. This proposal is based on an intimate understanding of the components package, and all the specific aspects (including TypeScript and Storybook documentation) that need to be balanced there.

If someone with more familiarity with the non-components APIs would like to extract a more generalized deprecation policy out of this draft, that would be great. (I think we would still want to keep this level of specificity when making decisions for the components package, though.)

the messaging seems to stress "bundle size cost" as the only meaningful reason for a hard deprecation. In the narrow context of the Components package, I understand why (a deprecated component or prop is relatively easy to isolate, thereby mitigating the cost in code complexity), but I think it's sensible to explain that there may be other costs to be weighed empirically and not a priori.

I completely agree. This is one of the things that should be re-written in a more generalized way if we want to extract a universal deprecation policy out of this.

@youknowriad
Copy link
Contributor

I think we would still want to keep this level of specificity when making decisions for the components package, though.

Personally, while I can see some differences between PHP and JS when it comes to decision making (mainly because the impact is not similar), I have a hard time seeing anything specific to the components package compared to any other JS API. So I'd love to understand why you think there are specificities here?

@tyxla
Copy link
Member

tyxla commented May 8, 2024

Thanks for opening it up @mirka and for the discussion so far everyone!

The cost of shipping deprecated code in PHP has historically been cheaper than doing it in JS since in JS it may impact bundle size. But that doesn't mean that the sole reason for hard deprecation is bundle size impact - there might be other reasons, like abandoning a poorly designed API in favor of a better one, or just the fact that we have a better alternative that everyone should be using in order to get a better user experience and optimal performance.

That being said, I agree with the gist of @mirka's proposal and I also agree with @youknowriad that it might be a good idea to generalize the suggested deprecation procedures for any other JS API in Gutenberg. For many components and APIs, it might actually be simpler, because of fewer usages across the plugin directory, and because they're not so thoroughly covered by storybook stories and tests.

However, I think that there might be parts of the policy that don't necessarily make sense for PHP APIs - historically, we've kept close to full backward compatibility on the backend side - if a PHP API worked in 2005, it's likely to be still working. If we keep that, we might never hard-deprecate anything in our JS packages, and with their experimental and swift-moving nature, I think that would be a downside.

If we agree that we're looking at crafting a universal deprecation procedure for JS APIs, in addition to thoroughly documenting it and publicizing it, there are three things I'd propose as corrections to the existing plan:

  1. Considering that the policy applies not only to components but any JS APIs in general (props, hooks, utils, etc.).
  2. Stressing on the fact that it applies to JS APIs and components only, and doesn't necessarily affect PHP APIs.
  3. Reconsidering the hard vs soft deprecation decision flow to account for other important factors, like known existing usage being low or none, better alternatives being available, and existing good reasons not to use (like perf implications, etc).

@peterwilsoncc
Copy link
Contributor

peterwilsoncc commented May 9, 2024

There's a few reasons I think WordPress needs a universal policy for PHP and JS proposed on make/core:

  1. It's the only way you'll get buy in from all contributors.
  2. The affect on end users is near identical: a white screen of death at worst, an error message at best. A users doesn't know or care if it's caused client or server side.
  3. The performance impact of deprecated APIs in PHP can be equally terrible, for example get_usermeta() has much poorer performance than get_user_meta().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Discussion For issues that are high-level and not yet ready to implement.
Projects
None yet
Development

No branches or pull requests

7 participants