The talk about https://bugs.ruby-lang.org/issues/19744 Why and how we will (not) introduce namespaces in Ruby 松江Ruby会議10
Satoshi Tagomori a.k.a., @tagomorisদߐRubyձٞ10 - Sep 16, 2023Help Collisions,Isolate the WorldsNames, Modules, Versions, and NameSpaces
View Slide
Satoshi Tagomori (@tagomoris)Independent developerTechnical ConsultantOSS Maintainer• Fluentd• MessagePack / msgpack-ruby• Norikra, Woothee, …tagomoris
https://www.flickr.com/photos/takkanm/3978417669Asakusa.rb
“Namespace on read“https://bugs.ruby-lang.org/issues/19744
CollisionsDestroy Developers’ Experience
CollisionsNames, Modules, VersionsName Collisions:No one can use a name in two ways.Module Collisions:Modules can be modified, globally, from anywhere.Version Collisions:Two different versions of a module can’t be loaded.
Name CollisionsNo one can use a name in two ways.• A structured namespace:• Foo::Bar::Baz• Major scenario:• Top-level “Configuration” in gems• Typical RoR classes vs Ruby, Gems, etc (like “Guild”)• Two apps in a process (in the context of “Modular monolith”)
Module CollisionsModules can be modified, globally, from anywhere.• A single Module/Class instance• Oj.default_options
Version CollisionsTwo different versions of a library can’t be loaded.• Dependency hell• Module A depends on C ver 1.5.x• Module B depends on C ver 1.6.x• The App depends on A and B
Avoid Collisions
Isolate Worlds
NameSpacesIn other words: “Multiverse Ruby”https://rubykaigi.org/2023/presentations/shioyama.html#day2
NameSpaces in PracticeN languages, N ways• Library space• Global NameSpace (+ Version)• Local names only• Names in code• Library name• Local alias• Class loader
NameSpaces in languagesMany ways, Many hells…• JavaScript/TypeScript (npm)• Local names + Local Aliases• Java (classes w/ FQDN)• Global NameSpace + Library name• Class loaders (oops….)• Kotlin• Global NameSpace + Local Alias• Python (pip)• Global NameSpace (+ Local Alias)• Go• Local names + Local Aliases
RubyMany Libraries in a Global NameSpace
Libraries and NameSpacesLibraries can’t be re-defined• Once a library lives globally, it can’t be locally• Ruby has a huge library set - RubyGems
NameSpace RequirementsWhat is it?• One native extension libraries of two versions at a time• Same name, Different (native) code, Different access path (local name)• Isolate libraries in specified namespaces at the required time (“on read”)Ruby ProcessLibraryXversion: a.b.c“x.so”LibraryXversion: x.y.z“x.so”ns1::X ns2::X
NameSpace RequirementsWhat is it?• One native extension libraries of two versions at a time• Same name, Different (native) code, Different access path (local name)• Isolate libraries in specified namespaces at the required time (“on read”)Ruby ProcessLibraryXversion: a.b.c“x.so”LibraryXversion: x.y.z“x.so”ns1::X X
My Proposal: module NameSpace < ModuleRespects load(filename, wrap)• The wrap of load(filename, wrap):• works as a simple namespace• Introduce a sub-class of Module: NameSpace• works like the wrap of load• has instance methods #require, #load• Dependencies will be required/loaded in the namespace recursively
Let’s go!DEMO
🎉👏🍻“Namespace on read PoC”https://github.com/tagomoris/ruby/pull/1
Hard Things, TODOs, Designs, …“How This Language Should Be?”• Hard Things: Native extension MAY need to be updated, in case• Native extensions using others’ C-functions https://github.com/tagomoris/sequel_pg/pull/1• TODOs: Upgrade path SHOULD be defined• How can we mark a gem is namespace-ready?• How can we determine the namespace of a library? (RubyGems/Bundler)• Designs• What’s the namespace in Ruby?• Problems around the top-level names in namespaces
Top-level Names in NameSpacesShould it be global? Or local?• “ns1::X” - A top-level name “X” defined in a namespace “ns1”• It MUST be so, to isolate “ns1::X” from the “X”• “X” in the code isolated in “ns1”• It should be “ns1::X”, of course• But many gems add methods on “String” by “class String”…• “::X” in the code isolated in “ns1”• Should it be “ns1::X”? or the “X”?• “class ::String” should be possible
The TODOsI need discussions• To Go? Or No Go?• In this way? Or another way? Or NO WAY?• Which way to go?• How can we break codes IN NAMESPACES? (Not globally)
I NEEDDISCUSSIONSFor further developments.Thank you!