Given some Uploader Class, I have three modules included in it.
They have each their own distinctive uses and that's why I divided them into three modules. But, as it turns out, there is one method that all three modules need.
So, it is so far obvious to me that there must be a better way than defining this method in each of these three modules. Should I make a fourth module and put this method in it, and have these original three modules include this fourth module? Or is there a better way?
Yes, it sounds like you should have a fourth module. But it sounds like you might actually need a class hierarchy rather than independent, flat modules. Apply the 'is a' test - can you say an UploaderA instance is an Uploader? If so, you should have
class Uploader
include FourthModule # with shared functionality for all uploaders
# or just go ahead and put the shared functionality right in the Uploader class here.
end
class UploaderA < Uploader
end
Related
Each of our page objects has around 80-100 PageObject elements defined. This is a byproduct of a very data centric application and I don't see that changing any time soon. We have many text fields, select lists, buttons, and menus. I want to clean up these somehow and put them somewhere, but the things I've thought about don't seem very clean.
Ideas:
Move elements for each PageObject into a corresponding module and include that module into a single PageObject only
create a YAML config file, with the mapping of element_type => element_name => element_id and then call the corresponding element methods using metaprogramming
Utilize the upcoming PageObject sections feature to create different "panels" within each page and then include those Panels into the page.
The first solution has the problem that each module can be included in other classes if somebody doesn't pay attention. It's not restricted to the single class
The second solution seems slow and not very "rubular", along with being confusing to update elements for those new to the project
The third solution seems like the best, but like the first solution, you could potentially include Sections into a class that they don't belong in.
What other way can I move the definition of these elements out of the class so that our class is cleaner, shorter, easier to read, and defined to Ruby Specifications (i.e. the Ruby Style Guide). They really just seem like config data rather than ruby code, so I feel like they don't belong in the class. Especially when we have 80+ elements in each class.
I don't see why you wouldn't keep the elements in the page object class. That's kind of the point of the class, right? If they're shared across multiple pages, then I understand putting them in a module and mixing in. But why abstract the unique elements on that page away from the page class?
But if you're absolutely going to do this, I'd think this is the best option:
Move elements for each PageObject into a corresponding module and include that module into a single PageObject only
There are ways you could ensure these modules are included only in the classes you expect. I have Module#included in mind. Something like:
module MyPageElements
def self.included cls
raise "Expected to be included on MyPage, got: #{cls}" unless cls == MyPage
end
# ... elements ...
end
create a YAML config file, with the mapping of element_type => element_name => element_id and then call the corresponding element methods using metaprogramming
Seems like this would be a headache to bring new, unfamiliar people up to speed on the code. Ultimately, I agree that it's just too un-Ruby like.
Utilize the upcoming PageObject sections feature to create different "panels" within each page and then include those Panels into the page.
Since I've just barely looked at this (thanks for linking me to the PR), I don't feel like I can speak to its efficacy.
Is it conventional to define a subclass under it's parent class like below?
class Element
class Div < Element
end
class Paragraph < Element
end
end
Or is it more appropriate to make a module to contain the subclasses?
class Element
end
module Elements
class Div < Element
end
class Paragraph < Element
end
end
Or to create a "base" class in a module and define the subclasses within the same module?
module Element
class Base
end
class Div < Base
end
class Paragraph < Base
end
end
Or is it better to force a naming convention?
class Element
end
class DivElement < Element
end
class ParagraphElement < Element
end
It seems every library chooses a different namespacing/naming convention.
Which is the best to use?
What are the pros and cons of each?
TL;DR: The most conventional and best way to do this is with a module containing a base class and its subclasses. But let's go over everything.
There aren't many official sources on this; however, it is the style to use modules to contain libraries, code, and groups of classes.
Subclasses in Superclass
Pros:
Self-contained: The entire class system is contained under one name
Cons:
Unnatural: Who would think to look inside a superclass for a subclass?
Having the subclasses in a superclass really depends on situation. However, any benefits of this method are also achieved by the module method. But in practice, this just isn't done. Classes are here to contain methods, instance variables, class methods, etc. But classes can be thought of as a last level of nesting -- you don't have a class in a class unless it's a very specific circumstance.
The one case where I can think of this making sense is a case where the only way subclasses are used is through the superclass, for example a Formatter class that has internal subclassses like XML, PDF, etc. Let's say that you only use these classes by doing things like Formatter.new(:xml). But if we're doing this, the subclasses should be private and not accessible to the outside world anyway. And at that point, inheritance is a very C++y way and not Rubyish at all.
Base class outside module, subclasses within
Pros:
I can't think of any
Cons:
Implies Non-conected: If Element is not in the same namespace as its children, what, beyond the name tells me that it's even related?
This method is very unnatural. It makes it look as if Element has nothing to do with it's children, or if looked at differently, that it's children are internal implementation details that aren't to be dealt with. Either way it looks like shabby, sloppy naming and bad code structure planning. If I were reading code using this, I'd have to look at the contents of the Elements module to see that Element was subclassed at all -- and this isn't the most natural thing to do.
Class and subclasses in module (best solution)
Pros:
Contained: The superclass and all the Element classes are contained in one namespace, allowing them to be easily imported, required, iterated, etc. Also assists metaprogramming.
Includable: The classes can be easily includeed into any code.
Clear: There is an obvious association between Element and the subclasses. They are obviously a bundle of functionality.
Cons:
Encourages lazy naming: This does encourage you to name classes things like Base that are very ambiguous.
This is the best approach. It makes the classes a neat bundle, while still showing an obvious association and an obvious "Here, use my Div class" (as opposed to the subclasses-in-class strategy). Also, this is really helpful for metaprogramming, where having everything in a module is crucial to make things work. Finally, this works well with constructs like autoload, require_relative, include, etc. Those show that this is the way the language was designed to be used.
Force a naming convention
Pros:
Simple: No complexity here.
Removes ambiguity: Removes ambiguity from short names like Div or Para by turning them into DivElement and ParaElement.
Cons:
Archaic: Naming conventions to group classes or methods should only exist in languages that don't have a better way to do it, like C or Objective-C. C++ dropped it as soon as it got namespaces.
No programatic grouping: These naming conventions, while clear to humans, make the class structure very cloudy to metaprograming code, and make it impossible for the program to deal with the classes as a group
Pollutes global namespace: This creates many, many names in the global namespace, which is always a bad idea.
This is a very, VERY bad solution. It encorages writing sloppy, C-style code with little organization and little sense. These kinds of naming conventions should only be used in languages where there is no better solution, and Ruby has plenty of better solutions. Even defining all the classes in an array is better than a naming convention.
Note: However, if you really want to, you can define a naming convention on short names like Div or Para as long as you still keep them in a module, so that it's Elements::DivElement. However, this violates DRY, and I wouldn't suggest it.
Conclusion
So, you really have two options. Just put everything in a module:
module Elements
class Element; end
class Div < Element; end
#etc...
end
Or, put everything in a module with a naming convention:
module Elements
class Element; end
class DivElement < Element; end
#etc...
end
I sugest the former for clarity, use of standard methods, and metaprogramming reasons.
This is a problem I have faced many times - you have some shared functionality and a few different implementation classes that use it - it's natural for the shared functionality and the namespace for the implementation classes to have the same name.
I have never had a problem defining a subclass under its parent class as in your first example - except for the fact that it has sometimes confused other developers on my team. So depending on who you are working with and what their preferences are I don't think there's any problem with this approach.
I would still prefer the second approach, with a different name for the namespace, if there was a name that made sense. If there isn't, I'd use the first approach.
I would avoid using names like Base, as in my opinion this sort of generic name encourages you to just throw any old stuff in there, whereas a name that describes what the class does will (hopefully) make you think each time you add a method if it really belongs there.
And I'm really not a fan of compound names as in your naming convention example, which I justify to myself with a sort of vague feeling that it's like database normalisation - each field (or class name) should contain only one piece of information.
Anyway, I hope this helps you. I can't really draw from any sources other than my own experience (it's for you to decide if you think that's 'credible'), as I do think there's no absolute answer to this question. It is in a large part subjective.
Name space and inheritance are for different purposes. Use name space to encapsule a module within another. Use inheritance to define a module using the methods/variables/constants of another as a default.
It could happen in principle that you may want a module to both be within the name space of and inherit from the same single module, but that depends on your use case. Without discussing over a particular use case, it cannot be decided which way among the ones you presented is the best.
I am just starting Ruby and learning the concept of modules. I understand that one use of modules is to better organize your code and avoid name clashes. Let's say I have bunch of modules like this (I haven't included the implementation as that's not important)
:
module Dropbox
class Base
def initialize(a_user)
end
end
class Event < Base
def newFile?
end
def newImage?
end
end
class Action < Base
def saveFile(params)
end
end
end
and another module:
module CustomURL
class Base
def initialize(a_user, a_url, a_method, some_args, a_regex)
end
end
class Event < Base
def initialize(a_user, a_url, a_method, some_args, a_regex)
end
def change?
end
end
class Action < Base
def send_request(params)
end
end
end
I am going to have a bunch of these modules (10+, for gmail, hotmail, etc...). What I am trying to figure out is, is this the right way to organize my code?
Basically, I am using module to represent a "service" and all services will have a common interface class (base for initializing, action for list of actions and event for monitoring).
You are defining families of related or dependent classes here. Your usage of modules as namespaces for these families is correct.
Also with this approach it would be easy to build abstract factory for your classes if they had compatible interface. But as far as I see this is not the case for current classes design: for example Dropbox::Event and CustomURL::Event have completely different public methods.
You can reevaluate design of your classes and see if it is possible for them to have uniform interface so that you can use polymorphism and extract something like BaseEvent and BaseAction so that all Events and Actions will derive from these base classes.
Update: As far as you define services, it might be useful to define top-level module like Service and put all your classes inside this module. It will improve modularity of your system. If in the future you would refactor out some base classes for your modules services, you can put them in the top-level namespace. Then your objects will have readable names like these:
Service::Dropbox::Event
Service::Dropbox::Action
Service::CustomURL::Event
Service::CustomURL::Action
Service::BaseEvent
Service::BaseAction
I have some similar code at work, only I'm modeling networking gear.
I took the approach of defining a generic class with the common attributes and methods, including a generic comparator, and then sub-class that for the various models of hardware. The sub-classes contain the unique attributes for that hardware, plus all the support code necessary to initialize or compare an instance of that equipment with another.
As soon as I see the need to write a method similar to another I wrote I think about how I can reuse that code by promoting it to the base-class. Often this involves changing how I am passing parameters, and instead of using formal parameters, I end up using a hash, then pulling what I need from it, keeping the method interface under control.
Because you would have a lot of sub-classes to a base class, it's important to take your time and think out how that base-class should work. As you add sub-classes the task of refactoring the base will get harder because you will have to change other sub-classes. I always find I go down some blind-alleys and have to back up a bit, but as the class matures that should happen less and less.
As you will notice soon, there is no 'right way' of organizing code.
There are subtle differences in readability that are mostly subjective. The way you are organizing classes is just fine for releasing your code as a gem. It usually isn't needed in code that won't be included in other peoples projects, but it won't hurt either.
Just ask yourself "does this make sense for someone reading my code who has no idea what my intention is?".
What tools can determine which modules have methods that are calling methods from other modules in Ruby?
Background: I'm partway through breaking a 808 line module into smaller modules, having created 12-submodules. However, some of the methods in one of the modules are calling methods in another sub-module. This may or may not be ok, depending on whether the module of the called method is meant to be common functionality.
module DisplayStatistics1
def display_statistics_1_foo
calculate_statistics_foo # call a method that's in CalculateStatistics - this is ok
display_statistics_2_bar # call a method that's in DisplayStatistics2 - this is bad
end
# other methods omitted
end
# modules DisplayStatistics2 and CalculateStatistics omitted
class ExampleClass
include DisplayStatistics1
include DisplayStatistics2
include CalculateStatistics
end
Ideally the analysis tool would show that DisplayStatistics1 has dependencies on DisplayStatistics2 as well as on CalculateStatistics.
Update: Maybe I shouldn't have done it this way - maybe I should have split them up into classes instead. That way, I'd have known for sure what depended on what!
While I'm not aware of a static analysis tool for Ruby, the one that seems closest to what you want is rubyprof. This can generate a callgraph in many formats, including an HTML tree and even a GraphViz box-and-line plot.
I was reading up on Ruby, and learned about its mixins pattern, but couldn't think of many useful mixin functionality (because I'm not used to thinking that way most likely). So I was wondering what would be good examples of useful Mixin functionality?
Thanks
Edit: A bit of background. I'm Coming from C++, and other Object languages, but my doubt here is that Ruby says it's not inheriting mixins, but I keep seeing mixins as Multiple inheritance, so I fear I'm trying to categorize them too soon into my comfort zone, and not really grok what a mixin is.
They are usually used to add some form of standard functionality to a class, without having to redefine it all. You can probably think of them a bit like interfaces in Java, but instead of just defining a list of methods that need to be implemented, many of them will actually be implemented by including the module.
There are a few examples in the standard library:
Singleton - A module that can be mixed into any class to make it a singleton. The initialize method is made private, and an instance method added, which ensures that there is only ever one instance of that class in your application.
Comparable - If you include this module in a class, defining the <=> method, which compares the current instance with another object and says which is greater, is enough to provide <, <=, ==, >=, >, and between? methods.
Enumerable - By mixing in this module, and defining an each method, you get support for all the other related methods such as collect, inject, select, and reject. If it's also got the <=> method, then it will also support sort, min, and max.
DataMapper is also an interesting example of what can be done with a simple include statement, taking a standard class, and adding the ability to persist it to a data store.
Well the usual example I think is Persistence
module Persistence
def load sFileName
puts "load code to read #{sFileName} contents into my_data"
end
def save sFileName
puts "Uber code to persist #{#my_data} to #{sFileName}"
end
end
class BrandNewClass
include Persistence
attr :my_data
def data=(someData)
#my_data = someData
end
end
b = BrandNewClass.new
b.data = "My pwd"
b.save "MyFile.secret"
b.load "MyFile.secret"
Imagine the module is written by a Ruby ninja, which persists the state of your class to a file.
Now suppose I write a brand new class, I can reuse the functionality of persistence by mixing it in by saying include ModuleILike. You can even include modules at runtime. I get load and save methods for free by just mixing it in. These methods are just like the ones that you wrote yourself for your class. Code/Behavior/Functionality-reuse without inheritance!
So what you're doing is including methods to the method table for your class (not literally correct but close).
In ruby, the reason that Mixins aren't multiple-inheritance is that combining mixin methods is a one time thing. This wouldn't be such a big issue, except that Ruby's modules and classes are open to modification. This means that if you mixin a module to your class, then add a method to the module, the method will not be available to your class; where if you did it in the opposite order, it would.
It's like ordering an ice-cream cone. If you get chocolate sprinkles and toffee bits as your mixins, and walk away with your cone, what kind of ice cream cone you have won't change if someone adds multicolored sprinkles to the chocolate sprinkles bin back at the ice-cream shop. Your class, the ice cream cone, isn't modified when the mixin module, the bin of sprinkles is. The next person to use that mixin module will see the changes.
When you include a module in ruby, it calls Module#append_features on that module, which add a copy of that module's methods to the includer one time.
Multiple inheritance, as I understand it, is more like delegation. If your class doesn't know how to do something, it asks its parents. In an open-class environment, a class's parents may have been modified after the class was created.
It's like a RL parent-child relationship. Your mother might have learned how to juggle after you were born, but if someone asks you to juggle and you ask her to either: show you how (copy it when you need it) or do it for you (pure delegation), then she'll be able at that point, even though you were created before her ability to juggle was.
It's possible that you could modify a ruby module 'include' to act more like multiple inheritance by modifying Module#append_features to keep a list of includers, and then to update them using the method_added callback, but this would be a big shift from standard Ruby, and could cause major issues when working with others code. You might be better creating a Module#inherit method that called include and handled delegation as well.
As for a real world example, Enumerable is awesome. If you define #each and include Enumerable in your class, then that gives you access to a whole host of iterators, without you having to code each and every one.
It is largely used as one might use multiple inheritance in C++ or implementing interfaces in Java/C#. I'm not sure where your experience lies, but if you have done those things before, mixins are how you would do them in Ruby. It's a systemized way of injecting functionality into classes.