We see these problems in this area:
- Polluting the Ruby top-level namespaces with names as generic as Installation, Packages or UI.
- Inconsistencies.
- Collisions (e.g. Storage is already a module and cannot be used as a namespace).
Let's see some examples:
::Registration::UI::Dialog
vs::UI::InstallationDialog
::Installation::FinishClient
vsYast::PkgFinishClient
You can see a complete example in PkgFinishClient.
- PkgFinishClient lives in Yast namespace (although is located in
lib/packages/clients/pkg_finish.rb
; more on that, later). - It inherits from
::Installation::FinishClient
, which live outside the YaST namespace (polluting the top-level one).
About source code layout, situation is not that bad but it can be improved. Sometimes is not straightforward to find where a class/module is defined (it's easy enough using grep or the Github search, but I'd prefer a more consistent/predictible way).
Although it's not mandatory, using a single class/module per file and naming the file as the class/module (but replacing CamelCase with snake_case) is the preferred option within the Ruby community.
Going back to PkgFinishClient
, it should live in
pkg_finish_client.rb
. And a Yast::SomeModule::Clients::SomeClient
class should be defined in
lib/yast/somemodule/clients/some_client.rb
.
Steffen pointed out that if he requires yast/storage
, he would
expect all storage code to be loaded. And he's right. If you want to
load only a class/file, you can require yast/storage/some_class
.
In an installed system, all YaST2 Ruby code lives in
/usr/share/YaST2
. That's fine for things like modules
(/usr/share/YaST2/modules
) which are quite YaST-specific. But from a
Ruby developer point of view, libraries should live in
/usr/lib64/ruby/vendor_ruby
(or something like that).
about code generators, it was there in past and result is that it become obsolete and just add to code useless stuff that are no longer valid. I prefer instead of code generator to create extension to rubocop and check if code follow yast conventions, as rubocop is easy to update. If you update code generator, you still have to cope with old code generated by old generator.
Regarding Namespaces, it is fine for me, but we still have problem that when you do something in Yast namespace, then you risk collision with Yast modules like famous Yast::String versus ::String problem. It was actually main reason for me to not use Yast namespace when possible.
changing clients dir is problem as it is used in Y2DIR and loaded by ruby-bindings, which different location it is hard to find. But it can be solvable by small wrapper that just run given client.
For me main decision is if we have Yast as whole project, that should have everything in namespace or if we want each module as own project sharing some common, so having namespace per yast module. In yast namespace there is risk of collision in Yast code, in own namespace, smaller risk of classes, but higher risk that top level namespace can collide ( but one name collision versus potential collision with a lot of libs and modules from various modules ).