In short: keep it simple.
I'm not sure if I'm supposed to review code that was not pasted here, but I took a look, since you linked it, and your sample is very brief. I really think that you are over-designing it (and even than your design has flaws):
- I see no reason for a factory here. Why do you want to use it (we do use them in Ruby, although we often have simpler choice that don't work that well in Java)?
Requester hold no state, why would they be objects at all (and not modules) and require instantiating?
Factory can't even be instantiated, so (assuming you keep it) it definitely has no reason to be a class.
Factory all have single method each.
Translator also has initialize, but
#translate basically only calls methods of
Requester. Don't take single responsibility literally, request and extraction could reasonably be methods in the same module (or in a class, this could be justified even with no instantiating here, because Ruby doesn't really allow private module methods and
#request rather should be private) which responsibility is 'translation'. Lazy class is a code smell, 4 lazy classes 4 times more so.
- Assuming you keep your responsibilities that much divided, forming a request URL is definitely responsibility of
Requester (one more reason to get rid of some classes, as
Translator would basically do nothing than).
The trick with patterns is not to apply them blindly. You wanted to gain better readability, testability and decoupling - did you?
- Your coude certainly is hard to read, you literally need to switch files every second line to understand it
- You didn't realy make it any more testable, those methods would be perfectly testable if they were put together. Your gem would need to get much, much more complicated before having this 4 classes would provide a gain in testability. There is no point to care about it now, it is more than likely that would your gem grow, you would need to refactor it anyways.
- You didn't really decouple anything - factory decouples instantiation, but there shouldn't even be any, as your objects hold no state. Request and extraction are coupled anyways, because if you changed your request(as in: used different translation engine) your extraction logic likely would need to change as well.
Code structure that I'd advise: one mixin to extract common logic from translators, and modules with engine-specific logic (that is request's and extraction), you have only google now, but it seems reasonable to assume more might be added in future.
# something like:
data = request text
# you might, or might not add ::url helper method, but this is
# somewhat complex so you should I guess, if only for testing it
Of course you should separate them in different files and use other module as a namespace, like all other gems do. This is simple, but flexible, maintanable and idiomatic("Ruby-ish"). To test
Translator mixin properly you would need a simple mock, but that's no biggie. Classes could be considered to make some methods private, but again, this is not that important, if someone calls
FreeGoogle::url nothing bad can happen, and Ruby has easy ways to call private methods anyways.