From: rr.rosas@... Date: 2019-01-28T16:22:11+00:00 Subject: [ruby-core:91307] [Ruby trunk Feature#5653] "I strongly discourage the use of autoload in any standard libraries" (Re: autoload will be dead) Issue #5653 has been updated by rosenfeld (Rodrigo Rosenfeld Rosas). Hi, this is a discussion which I'm pretty much interested in and I'd like to add a few comments. It seems to me that there are basically two reasons why people rely on autoload: 1. to achieve fast boot; 2. for convenience (not having to explicitly require the dependencies); So, I'd just like to point out that there are options to achieve fast boot rather than resorting to autoload. Loading too many code upfront can be very slow not only in Ruby and there is another very well known solution for that problem that is applied to all other languages and which is available to Ruby as well: on-demand loading or lazy loading. This is not a theory only. I've been coding this way for over an year. I maintain a large application for a long time. It was written in Groovy when I joined the project about 7 years ago, and it wasn't a small application already by that time and it's only getting bigger. Some years ago I had gradually moved the source from Grails to Rails and a few years ago I moved it from Rails to Roda. While doing that, I knew already that loading all the application upfront could be pretty slow and I didn't like the autoload or constant-missing approach already by that time to load code on-demand automatically and I would prefer to do that explicitly instead. Another common requirement when developing server-based apps such as web servers is the auto-reloading feature. So, the solution I found for my use case, which would also scale to any code base size, is to split the application in multiple apps, one per route base path. With Roda an option, the one I opted for, would be to use the multi_run plugin: http://roda.jeremyevans.net/rdoc/classes/Roda/RodaPlugins/MultiRun.html Instead of loading the sub-apps upfront, I'd call it something like this: ``` ruby run 'some_app', ->(env){ require_relative 'apps/some_app'; Apps::SomeApp.call env } ``` I actually use a helper to register the apps, but this is basically what it happens behind the scenes. When some of the relevant files (source, settings) change, I'd unload all reloadable constants and run the application, using a gem I've authored a few years ago: https://github.com/rosenfeld/auto_reloader With that configuration my application boots instantly (much faster than a fresh Rails app) and with a one-line code change I could decide to load it all up-front for the production environment (I've opted for keeping it loading on-demand in production too, so that I could deploy my app as if the app was comprised by several micro-services in the case some of the requests would need more workers, so that such app wouldn't have to use too much RAM, for example). So, I'd say that there are better solutions to achieve a fast boot time than complicated frameworks such as bootsnap and similar ones and without relying on autoload or constant missing to automatically load code on demand. Now, I'd like to discuss the second reason why people want autoload: convenience. While I do have to type all my dependencies explicitly in my code base I actually like this. I mean, I prefer to type my dependencies explicitly. I'd certainly prefer an approach such as the import/export one used by ES6, for example, but I think such change would be too big for Ruby. I find it particularly annoying when I'm trying to follow what some third-party library is doing and I have to guess the dependencies based on their several lines of autoload calls distributed anywhere in the code base. I like to be able to quickly inspect the dependencies of each file separately. There was a time I'd like to use one method from Rails helpers to format a currency value and I couldn't just require the file containing the method definition because it wouldn't work unless I required the full action_view gem due to issues caused by the use of autoload, since not all dependencies were explicitly required by that file. I can't call this a best practice, so I'm not convinced that this approach actually leads to convenience. It was quite inconvenient to me when I wanted to use just a small subset of the actionview gem, for example. Since Ruby strives to make programming a joy I believe there's a conflict here. In one hand there's a bunch of people that find it convenient not to have to type their dependencies in all sources files using them because it feels too "Javay" and consider specifying the dependencies explicitly annoying, boilerplate code. Those see autoload or automatic loading through constant-missing hooks like a huge win for making application development more convenient. On the other hand there are people like me, who find annoying not to be able to require an specific file from a third-party library because it can't be required separately because it relies on autoload calls that are supposed to be registered in another file, which is not required by this particular file, by the way. That's why I find this very topic so tricky. Because it's virtually impossible to make all users happy. If you opt for keeping the autoload feature, those who want to be able to require individual files from other projects, or those who want to view all dependencies for every file explicitly available, will become disappointed (like me). And if autoload is removed, a lot of code would simply stop working since this seems to be a very common practice among gem authors. And, of course, most Ruby users would be upset as well because the gems they relied on are no longer working, which is very understandable. Also, I believe most Rails users actually like all the conventions and not having to explicitly require their dependencies, so I bet most Ruby users would prefer autoload to remain available in the language. That's why, even though I'd personally love to see autoload gone once and for all from the language, I actually sympathize with most Ruby devs who actually seem to like autoload and I think that actually removing it from the language wouldn't be the right move at this moment. The way I see this issue is like Matz was begging Rails to find an alternative because he wanted very much to get rid of autoload because he realized that it's not a good feature to have in the language but he also realizes that he can't just remove autoload while Rails keeps using it. If the Rails team stopped using it, maybe other popular gem authors would follow the move and hopefully one day we could get rid of it. Instead, the Rails core team has decided not only to disregard Matz's request, but to actually do the opposite and rely even more on autoload so that removing autoload would actually break all Rails apps because it would become impossible to replace it with another solution without requiring changes to the application. I actually feel sad about this decision because Rails is now forcing the development of Ruby in a direction that is the opposite of its creator will. I'd love to see the Rails core team reconsider their decision although I don't think this will ever happen :( Sadly it seems we'll have to live with autoload in the language, not because most Rubyists seem to agree that it's a great feature, but because the Rails core team decided it had to stay instead. This is the part that makes me feel more sad :( ---------------------------------------- Feature #5653: "I strongly discourage the use of autoload in any standard libraries" (Re: autoload will be dead) https://bugs.ruby-lang.org/issues/5653#change-76553 * Author: matz (Yukihiro Matsumoto) * Status: Assigned * Priority: Normal * Assignee: matz (Yukihiro Matsumoto) * Target version: Next Major ---------------------------------------- Hi, Today, I talked with NaHi about enhancing const_missing to enable autoload-like feature with nested modules. But autoload itself has fundamental flaw under multi-thread environment. I should have remove autoload when I added threads to the language (threads came a few months after autoload). So I hereby declare the future deprecation of autoload. Ruby will keep autoload for a while, since 2.0 should keep compatibility to 1.9. But you don't expect it will survive further future, e.g. 3.0. I strongly discourage the use of autoload in any standard libraries. matz. ---Files-------------------------------- noname (500 Bytes) 5653.pdf (38.3 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: