Reputation: 2819
I'm creating an API wrapper so I've been looking at other libraries to get some ideas on how to structure it. I found that a lot of libraries mix in all their methods in a Client
class instead of using inheritance.
Why?
Examples:
Octokit: https://github.com/octokit/octokit.rb/blob/master/lib/octokit/client.rb
Instagram: https://github.com/Instagram/instagram-ruby-gem/blob/master/lib/instagram/client.rb
Twitter (sort of): https://github.com/sferik/twitter/blob/master/lib/twitter/rest/api.rb
Why not use separate classes?
In Octokit you fetch commits by doing something like
client = Octokit::Client.new
client.commits
Why not use something like Octokit::Commit.all
? (Perhaps I'm damaged by Rails and the AR API)
If you mix everything into one big class it seems like you would have issues with accidentally overriding methods all the time.
What do I not understand here? :)
UPDATE: Here is an example of another library that uses more of an inheritance approach https://github.com/jeremyw/swish/tree/master/lib/dribbble
Upvotes: 0
Views: 81
Reputation: 1000
I think you asked this on IRC too.
The answer provided on IRC was that you get more flexibility with an include-approach, due to the subclass linear cascading inheritance effect - they all need to have a parent.
This shapes the design, as you may recall from IRC - in the case of the subclassing, I gave the example of Sinatra:
class MyApp < Sinatra::Base
Another reason also is that it is convenient to put things into modules, and then re-use it.
Months ago I gave an example of storing my constants in a module called Constants (when I have like more than 50 of these constants) - I simply like to be able to have "iteration points" in my projects that can help identify where I put things. And when I need these constants available in other classes or modules of my code, I simply include that. I can not do the same as easily with subclassing, because subclassing forces me into a more rigid model. And I can only subclass from a class, not a module - but I can include code into a module or a class freely. (This is not a great design point in ruby IMHO - I think extending behaviour should work differently, but I did not design ruby.)
Also the example you gave of Octokit seems hugely bad.
Why not give saner examples like Rack?
Rack does not use many includes at all:
lib/rack/response.rb: include Helpers
lib/rack/content_type.rb: include Rack::Utils
lib/rack/chunked.rb: include Rack::Utils
But you see the examples above are significantly better for an include-based approach.
Upvotes: 1