<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">import{_ as i}from"./chunks/plugin-vue_export-helper.BCo6x5W8.js";import{c as t,s,o as a}from"./chunks/mermaid.C8unLxid.js";const n=JSON.parse('{"title":"Consistent deprecation notices in Core","description":"","frontmatter":{"title":"Consistent deprecation notices in Core","date":"2022-02-09T00:00:00.000Z","area":"core","tags":["deprecation","annotations","trigger-deprecation"]},"headers":[{"level":2,"title":"Context","slug":"context","link":"#context","children":[]},{"level":2,"title":"Decision","slug":"decision","link":"#decision","children":[{"level":3,"title":"Ensuring the correct usage during CI","slug":"ensuring-the-correct-usage-during-ci","link":"#ensuring-the-correct-usage-during-ci","children":[]},{"level":3,"title":"Common Implementation","slug":"common-implementation","link":"#common-implementation","children":[]},{"level":3,"title":"Consistent deprecation notice format","slug":"consistent-deprecation-notice-format","link":"#consistent-deprecation-notice-format","children":[]}]}],"relativePath":"docs/resources/references/adr/2022-02-28-consistent-deprecation-notices-in-core.md","filePath":"docs/resources/references/adr/2022-02-28-consistent-deprecation-notices-in-core.md"}'),o=i({name:"docs/resources/references/adr/2022-02-28-consistent-deprecation-notices-in-core.md"},[["render",function(r,e,l,h,d,c){return a(),t("div",null,e[0]||(e[0]=[s(`&lt;h1 id="consistent-deprecation-notices-in-core" tabindex="-1"&gt;Consistent deprecation notices in Core &lt;a class="header-anchor" href="#consistent-deprecation-notices-in-core" aria-label="Permalink to &amp;quot;Consistent deprecation notices in Core&amp;quot;"&gt;\u200B&lt;/a&gt;&lt;/h1&gt;&lt;div class="info custom-block"&gt;&lt;p class="custom-block-title"&gt;INFO&lt;/p&gt;&lt;p&gt;This document represents an architecture decision record (ADR) and has been mirrored from the ADR section in our Shopware 6 repository. You can find the original version &lt;a href="https://github.com/shopware/shopware/blob/trunk/adr/2022-02-28-consistent-deprecation-notices-in-core.md" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;h2 id="context" tabindex="-1"&gt;Context &lt;a class="header-anchor" href="#context" aria-label="Permalink to &amp;quot;Context&amp;quot;"&gt;\u200B&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Currently, we use &lt;code&gt;@deprecated&lt;/code&gt; annotations to warn 3rd party developers that we will introduce some breaking change in the next major version. This annotation instructs the IDE to warn the developer that the method/class is deprecated, but has no consequences at runtime.&lt;/p&gt;&lt;p&gt;PHP/Symfony has also a built-in runtime deprecation mechanism with &lt;code&gt;trigger_deprecation&lt;/code&gt;. This is only used sparsely in the core in &lt;code&gt;Feature::triggerDeprecated()&lt;/code&gt;.&lt;/p&gt;&lt;h2 id="decision" tabindex="-1"&gt;Decision &lt;a class="header-anchor" href="#decision" aria-label="Permalink to &amp;quot;Decision&amp;quot;"&gt;\u200B&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;In the future we will use both &lt;code&gt;@deprecated&lt;/code&gt; and runtime deprecation notices over &lt;code&gt;trigger_deprecation&lt;/code&gt;. This means wherever a &lt;code&gt;@deprecated&lt;/code&gt; annotation is used we will also throw a deprecation notice.&lt;/p&gt;&lt;p&gt;The deprecation notices can be thrown conditionally, e.g., when a new parameter in a method will become required, we will only throw the deprecation if the method is called in the old/deprecated way. If it is already used in the new way, there is no need to trigger the deprecation.&lt;/p&gt;&lt;p&gt;This has the benefit that 3rd party developers get deprecation notices during runtime with a concrete deprecation message and the stacktrace where the deprecation was triggered. This is useful, e.g., to run the test suite of a plugin against a new shopware version to get a list of all deprecations.&lt;/p&gt;&lt;p&gt;Additionally, we can use this to provide better feedback to 3rd party developers, e.g., if App Scripts use a deprecated method/class or if some private apps in the cloud rely on deprecated functionality.&lt;/p&gt;&lt;h3 id="ensuring-the-correct-usage-during-ci" tabindex="-1"&gt;Ensuring the correct usage during CI &lt;a class="header-anchor" href="#ensuring-the-correct-usage-during-ci" aria-label="Permalink to &amp;quot;Ensuring the correct usage during CI&amp;quot;"&gt;\u200B&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;To ensure that this guideline is followed, we add a step in the CI (e.g., a custom PHPStan rule or a special unit test) that checks that every method that has a &lt;code&gt;@deprecated&lt;/code&gt; annotation triggers also a deprecation notice, and vice versa.&lt;/p&gt;&lt;p&gt;There are some special cases where we use a &lt;code&gt;@deprecated&lt;/code&gt; annotation, but a according triggered deprecation notice makes no sense:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Classes/methods marked as deprecated, because they will be considered &lt;code&gt;internal&lt;/code&gt; starting with the next major version.&lt;/li&gt;&lt;li&gt;Methods are deprecated because the return type will change. For both cases we will add special keywords to the &lt;code&gt;@deprecated&lt;/code&gt; annotation and our CI-check will skip those annotations.&lt;/li&gt;&lt;/ul&gt;&lt;h3 id="common-implementation" tabindex="-1"&gt;Common Implementation &lt;a class="header-anchor" href="#common-implementation" aria-label="Permalink to &amp;quot;Common Implementation&amp;quot;"&gt;\u200B&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;We will add a common implementation inside the core that should be used everywhere. This makes it easier to change the deprecation handling later on in a single place and makes it possible to provide custom deprecation warnings, e.g., for app scripts inside Symfony&amp;#39;s debug toolbar.&lt;/p&gt;&lt;p&gt;The new method will accept the deprecation message as string and the feature flag of the major version, where the deprecation will be removed. The method will then trigger a deprecation notice if the major feature flag is not active. If the flag is active, it will throw an exception instead. This ensures that we inside the core don&amp;#39;t rely on deprecated functionality as we have a test-pipeline where the major feature flag is set to true.&lt;/p&gt;&lt;p&gt;A POC implementation in the &lt;code&gt;Feature&lt;/code&gt;-class can look something like this:&lt;/p&gt;&lt;div class="language-php vp-adaptive-theme"&gt;&lt;button title="Copy Code" class="copy"&gt;&lt;/button&gt;&lt;span class="lang"&gt;php&lt;/span&gt;&lt;pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;    public&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt; static&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt; function&lt;/span&gt;&lt;span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"&gt; triggerDeprecationOrThrow&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;(&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;string&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt; $message, &lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;string&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt; $majorFlag)&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;:&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt; void&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;        if&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt; (&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;self::&lt;/span&gt;&lt;span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"&gt;isActive&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;($majorFlag) &lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;||&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt; !self::&lt;/span&gt;&lt;span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"&gt;has&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;($majorFlag)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt;            throw&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt; new&lt;/span&gt;&lt;span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"&gt; \\RuntimeException&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;(&lt;/span&gt;&lt;span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"&gt;&amp;#39;Deprecated Functionality: &amp;#39;&lt;/span&gt;&lt;span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"&gt; .&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt; $message);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"&gt;        trigger_deprecation&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;(&lt;/span&gt;&lt;span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;, &lt;/span&gt;&lt;span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;, $message);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Additionally, we will deprecate the &lt;code&gt;triggerDeprecated()&lt;/code&gt; method, because it will only trigger deprecation messages if the feature flag is active, but in that case the deprecated code will already be removed and the deprecation message never thrown.&lt;/p&gt;&lt;h3 id="consistent-deprecation-notice-format" tabindex="-1"&gt;Consistent deprecation notice format &lt;a class="header-anchor" href="#consistent-deprecation-notice-format" aria-label="Permalink to &amp;quot;Consistent deprecation notice format&amp;quot;"&gt;\u200B&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;To be as useful as possible, we should use a consistent format for the deprecation messages.&lt;/p&gt;&lt;p&gt;Most importantly, we should ensure that the following information is present in the deprecation message:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The name of the method/class that is deprecated&lt;/li&gt;&lt;li&gt;The version in which the deprecation will be removed and the announced changes will be applied&lt;/li&gt;&lt;li&gt;What to do instead to get rid of the deprecation, e.g., using another method/class or provide an additional param etc.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As an example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Bad:&lt;/strong&gt; Will be removed, use NewFeature::method() instead&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Good:&lt;/strong&gt; Method OldFeature::method() will be removed in v6.5.0.0, use NewFeature::method() instead&lt;/li&gt;&lt;/ul&gt;`,26)]))}]]);export{n as __pageData,o as default};
</pre></body></html>