Search code examples
ruby

Ruby namespace flattening gotchas?


I must use a ruby library that looks like it was written by a java developer because the namespaces are so looooooonngg. And I have to use a lot of the classes in the namespaces.

I would like to make my own namespace wrapper/alias. I tried this in irb and it seems to work. My question is if this is the "correct" way to do it (eg include vs extend) and/or what gotchas I have to watch out for besides class name collisions

module System

   include ::Com::Company::Project::Core::System::Core   # About 5 classes
   include ::Com::Company::Project::Core::System::Common # About 15 classes

   module SubSystem
     include ::Com::Company::Project::Core::SystemSubSystem::Core   # About 10 classes
     include ::Com::Company::Project::Core::SystemSubSystem::Common # About 15 classes
   end
end


....
facade = System::Facade.new( System::SubSystem.new(...) )

Solution

  • If you want to shorten the namespace, you could introduce a constant which refers to a module deep within the hierarchy, e.g.:

    module System
      LibCore = ::Com::Company::Project::Core
    
      include LibCore::System::Core
      include LibCore::System::Common
    
      module SubSystem
        include LibCore::SystemSubSystem::Core
        include LibCore::SystemSubSystem::Common
      end
    end
    

    Another variant, although quite uncommon, is to define your top-level module from within the library's namespace via ::, e.g.:

    module Com::Company::Project::Core
      module ::System # <- using :: defines System on the top level
        include System::Core
        include System::Common
    
        module SubSystem
          include SystemSubSystem::Core
          include SystemSubSystem::Common
        end
      end
    end
    

    Or maybe even:

    module Com::Company::Project::Core::System
      module ::System
        include Core
        include Common
      end
    end
    
    module Com::Company::Project::Core::SystemSubSystem
      module ::System::SubSystem
        include Core
        include Common
      end
    end
    

    All variants above will result in:

    System.included_modules
    #=> [Com::Company::Project::Core::System::Common,
    #    Com::Company::Project::Core::System::Core]
    System::SubSystem.included_modules
    #=> [Com::Company::Project::Core::SystemSubSystem::Common,
    #    Com::Company::Project::Core::SystemSubSystem::Core]