WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
9.87k stars 3.91k forks source link

Components: Document our deprecation procedures #61099

Open mirka opened 1 week ago

mirka commented 1 week ago

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:

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:

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

Soft deprecation

Hard deprecation

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 commented 1 week ago

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 commented 1 week ago

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

youknowriad commented 1 week ago

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 commented 1 week ago

+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 commented 1 week ago

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 commented 1 week ago

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 commented 1 week ago

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 commented 5 days ago

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 commented 2 hours ago

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.