drupal_static() was committed for two reasons:
1. To remove $reset parameters from functions, however Dries has overturned various efforts to do this, leading to #581626: Use a consistent/clean pattern for using $reset or drupal_static(), so we now no longer have a $reset pattern, we have a confusing mix of no pattern at all.
2. To allow simpletest to run with a clean environment, but discussion with boombatower in irc suggests this isn't being used, won't be necessary with simpletest-2.x refactoring, and #601584: setUp() function for unit and web test cases should reset all resettable statics is very far off working.
Meanwhile, we have to work around the performance implications of drupal_static() in issues like #619666: Make performance-critical usage of drupal_static() grokkable - since it's precisely functions which need to be fast, which often also want to use static variables. There are also several issues like #572452: drupal_get_filename() and drupal_load() should not use drupal_static() where it's been used completely inappropriately.
So given it's not been consistently applied, isn't doing what it was committed for in the first place, and is one of the 'thousand cuts' slowing down Drupal 7 performance, I can't really see much reason to keep it in at all.
While it would be an API change to remove it, in nearly all cases this would simply be putting back a final optional argument to functions which was taken out, so not much of one.
The only place where it's turned out to be really useful, is in places like http://api.drupal.org/api/function/drupal_cache_system_paths/7 - where you want to use information from one module's static variable in another - but there's other ways to do that.
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | reset_listeners.inc_.txt | 1.1 KB | donquixote |
Comments
Comment #1
effulgentsia commentedIt would be a shame. I like the ability to reset statics, both for writing better tests (even if we're not doing so yet, we still have a couple months to improve the tests we have), and for opening the door to contrib modules doing more sophisticated stuff within a single page request (automation that doesn't require new page subrequests). I would much prefer to see #619666: Make performance-critical usage of drupal_static() grokkable land, and the other issues catch mentions resolved. However, I agree that it's unacceptable to compromise performance, so if #619666: Make performance-critical usage of drupal_static() grokkable is rejected, I would support rolling back drupal_static() entirely, or at least in performance-critical functions.
Comment #2
effulgentsia commentedActually, I think it's pretty close.
Comment #3
David_Rothstein commentedI think @catch's summary is very good, but then again I'm biased because I never really liked drupal_static() originally...
The only direct advantage that drupal_static() ever provided was that it freed module developers from having to write extra lines of code for maintaining a bunch of $reset parameters. So if we aren't going to get rid of $reset parameters (and there are at least some good arguments for not getting rid of them), it is indeed unclear what purpose drupal_static() serves.
Maybe you could say that there is a remaining advantage in that it allows modules to easily work around other modules' bugs and limitations -- but as nicely put by bjaspan, even that is a double-edged sword because it essentially encourages them to create more of those bugs in the first place :)
In terms of the other issues, there are indeed solutions and they have been discussed before: If edge cases like SimpleTest need to clear all static caches, we could have module_invoke_all('reset_static_caches'), just like we currently have module_invoke_all('flush_caches') to clear database caches. And functions which need to access each others' static variables can do that via internal helper functions -- or, if they have something that they explicitly want to make globally accessible, we could provide variable_set_temporary() and variable_get_temporary() as wrapper functions around the existing global $conf array. It sounds like doing either of these things might not even be necessary, but could be done if we needed to because we'd be changing the API anyway.
So I'd tentatively vote for killing it (assuming that $reset parameters are here to stay).
Killing it during the API freeze might actually even have an advantage in that the change would be widely advertised to module developers and would be a good opportunity to remind people of how static variables should and should not actually be used :)
Comment #4
effulgentsia commentedWhat are the good arguments for retaining $reset parameters? I somehow missed those discussions. Please share links if you have them. I understand wanting another API layer between client code and a direct call to drupal_static_reset(), as suggested by #581626: Use a consistent/clean pattern for using $reset or drupal_static(), and I would even support a hook_reset_static_caches(), but it seems crazy to me to have every single function that uses a static to have to have a $reset parameter.
Comment #5
boombatower commentedJust heads up, #601584: setUp() function for unit and web test cases should reset all resettable statics is quite close to working.
Comment #6
donquixote commentedI have a different idea for a more automated reset of static variables in specific situations:
Let functions subscribe with their static variables to a reset service. The reset service is called with a "situation key" (or better: "event key" ?), which can be a table name or other things. More than one function can subscribe to one situation key / event - so the caller can be agnostic about the subscribers.
See the attachment.
It's quite verbose, but I think it will not have performance issues.
Maybe there is a nicer way, but I don't see it at the moment.
--- [side note] ---
Another problem with static variables is if they contain objects, or arrays of objects, and then return these objects - we get a lot of nasty side effects by functions modifying these objects. See #305653: Themes disabled during update and #632080: _system_theme_data() should clone the returned objects..
Comment #7
donquixote commentedIf you are interested in the patch above, please visit
#632434: Allow static variables to "subscribe" to global events for reset
instead, which has better code and is the more appropriate place to discuss this.
Comment #8
alexanderpas commentedaww.... that means i need to start thinking about another way to fix #516150: Add fallback for main content block rendering
Comment #9
catchIt seems like we may have got around the ugliness in #619666: Make performance-critical usage of drupal_static() grokkable with some very nice documentation and there's a decent chance that'll get committed, so downgrading this one, since #581626: Use a consistent/clean pattern for using $reset or drupal_static() is still critical and deals with most of my other complaints.
Comment #10
effulgentsia commentedAnd I'd like to add that #601584: setUp() function for unit and web test cases should reset all resettable statics passes all tests, and is awaiting someone to RTBC it.
Comment #11
David_Rothstein commented@effulgentsia in #4:
The list Dries came up with is here: http://drupal.org/node/422370#comment-1438846
Comment #12
effulgentsia commentedPretty sure we won't be removing drupal_static() in D7. If someone thinks we should in D8, change the version and status attributes accordingly.
Comment #13
moshe weitzman commentedI was looking at PHPUnit yesterday and at the start of each test they snapshot all superglobals ($GLOBALS, $_GET, etc.) and all static attributes of user defined classes. At the end of each test, they revert those to virgin state. See http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html.
So there are ways to deal with the testing problem other than drupal_static(). Perhaps this method is feasible once we move more code to classes. Just a thought.
It would be a gigantic task, but I still hold out hope we can replace simpletest. Its notion of having two drupal sites running at once (tester and tested) is hopelessly confusing for most people. Perhaps more achievable would be to make our simpletest its own app that does not depend on drupal (perhaps the app will ship with parts of drupal like DB layer).