Deprecated code represents the single biggest blocker to people updating their sites from Drupal 8 to Drupal 9. I’m mentioning this (again, because I talked about it last year) because Drupal 8 is going End of Life (EOL) in November 2021. That’s not very far away. And thankfully, at this point, the update is super smooth! But, as with “any” smooth update, that doesn’t mean there won’t be problems. And I cannot stress enough that deprecated code can be a really significant problem depending on how much of it there is.
What Is Deprecated Code
deprecation is the discouragement of use of some terminology, feature, design, or practice, typically because it has been superseded or is no longer considered efficient or safe, without completely removing it or prohibiting its use
Deprecation is a way to flag something as “stop using this” without actually removing it. The Drupal community provides pretty clear guidelines on what can (and can’t) be deprecated here. The TLDR is that:
In earlier versions of Drupal there was no formal mechanism for updating dependencies or changing core functionality (which made the ecosystem super tricky to manage)
Deprecated code is only removed during major version updates (e.g. Drupal 8 => Drupal 9)
So, if you’re working on a Drupal 9 upgrade, and you are using anything that is marked @deprecated, then once you’ve completed the Drupal 9 upgrade you will likely have a fatal error on your hands (somewhere in your application) as you attempt to use code that no longer exists.
A quick example from the GovCon site (because there’s always an example from the GovCon site) can be seen in this pull request.
In this case, we are using the User::getUsername method. This code was flagged as deprecated in drupal/core 8.0.0 and removed in 9.0.0. If you look in the code where this method is defined (see https://git.drupalcode.org/project/drupal/-/blob/8.9.x/core/lib/Drupal/Core/Session/UserSession.php in core 8.x) you’ll find the following:
* @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0.
* Use \Drupal\Core\Session\AccountInterface::getAccountName() or
* \Drupal\user\UserInterface::getDisplayName() instead.
If you look in the same file for Drupal 9.0 the method is gone entirely (see https://git.drupalcode.org/project/drupal/-/blob/9.0.x/core/lib/Drupal/Core/Session/UserSession.php).
The deprecation notice:
tells you that you shouldn’t use this method
warns you (via your IDE) if you try to use the method
gives you a couple of alternative methods
And in this case, it’s actually a super easy replacement (as you can see in the GovCon PR). Just call another method instead. This is not always the case with deprecated code. But frequently it’s a pretty straight. forward replacement. The difference is, getUsername will fatal error and getDisplayName (or getAccountName) won’t.
How to Find Deprecated Code
Deprecated code is super easy to spot when you’re looking at it, but on projects with a lot of code (custom or contributed) it can be challenging to find. Why? Well, you don’t necessarily want to skim through every file and look for the telltale strikethrough that warns you that you’ve used something that’s deprecated.
Ideally then, you’ll use a tool to help you find deprecated code and the Upgrade Status module is the best option for that. It will tell you if your code contains anything deprecated or not, and will also check contributed packages for compatibility with Drupal 9.
I should point out that the GovCon PR in question did not flag in Upgrade Status (so I initially missed it when we updated that site to D9). So, it’s very important that you still thoroughly test your site even after using automated testing tools like Upgrade Status to search your code!
How to Fix Deprecated Code
There are a few steps to take once you find deprecated code:
Review the core documentation on why it was deprecated. Usually you can find a @deprecated tag in the method declaration that either points at one or more new methods and/or a change node on Drupal.org.
Review the change node on Drupal.org (which may or may not be directly linked in the code). Something like this: https://www.drupal.org/project/drupal/issues/2787871. Note that you may find a couple of different types of pages that talk about it (and that’s ok).
Make your code change(s). I usually recommended targeting a particular deprecated instance or a particular deprecation (e.g. EntityManager => EntityTypeManager) and making sure that’s working before moving on to do “all of them.” Depending on your codebase, you could have hundreds or even thousands of deprecations (but frequently there will be multiple instances of the same deprecated code, so you may have a handful of fixes to make in “a lot of places.”)
Thoroughly test / regression test your application with these changes in place
Deploy as necessary.
Note: depending on the amount of custom code your team is actively writing, it may be wise to setup automated deprecation testing using Drupal Check to ensure that once you fix a deprecated instance no one accidentally puts another one back. Upgrade Status gives more complete information than Drupal Check, but is significantly slower (so challenging to utilize during a git hook or continuous integration process).
In Conclusion
Deprecated code is a really common coding convention. It’s around in many standard languages (including PHP) and has been long before the Drupal community adopted it. So for those of you that have come up in your careers heavily focused on Drupal, this may be new to you, but for anyone with experience in other frameworks or languages, this should be old news.
The big take away here is that this is all going to happen again throughout the Drupal 9 lifecycle as we prepare for Drupal 10. So while you probably don’t need to “worry” about Drupal 9 deprecated code (because Drupal 10 is still over a year away) this is definitely a topic that is going to come up again and again. Deprecation is part of the Drupal life cycle now. Don’t let it stop you from getting on Drupal 9 and make sure you embrace it as you’ll see it again very soon!
Dependency trees can be massive, and with the upcoming Drupal 10 release PHP 8.1 could have a significant impact on your project.