I have a class that uses hash as its internal store. What’s a good way
to communicate the interface of my methods. It seems like the user would
only know how to use it if there’s a comment or a test case. This is the
interface that I want them to use:
book = Book.new
book.add_content(1 => some_text)
book.add_content(2 => some_text)
This is the class that I have:
class Book
def initialize()
@hash = {}
end
def add_contents(hash)
@hash.merge! hash
end
def contents
@hash
end
end
On Tue, Nov 1, 2011 at 3:14 AM, Reginald T. [email protected]
wrote:
I have a class that uses hash as its internal store. What’s a good way
to communicate the interface of my methods.
Do you need to leak this implementation detail? You could make
add_content a two argument method and changing it like this:
def add_content(k, v)
@hash.merge(Hash[k,v]) # or @hash.merge({k => v})
end
–
Michael K.
http://citizen428.net | http://twitter.com/citizen428
Michael K. wrote in post #1029550:
On Tue, Nov 1, 2011 at 3:14 AM, Reginald T. [email protected]
wrote:
I have a class that uses hash as its internal store. What’s a good way
to communicate the interface of my methods.
Do you need to leak this implementation detail? You could make
add_content a two argument method and changing it like this:
def add_content(k, v)
@hash.merge(Hash[k,v]) # or @hash.merge({k => v})
end
–
Michael K.
http://citizen428.net | http://twitter.com/citizen428
That’s a good point about hiding implementation. requiring 2 arguments
looks like a good way to go about what i’m trying to do. Thanks Michael!
On Tue, Nov 1, 2011 at 10:13, Michael K. [email protected] wrote:
def add_content(k, v)
@hash.merge(Hash[k,v]) # or @hash.merge({k => v})
end
I think perhaps you want #merge! not #merge.
However, given that this can only take two arguments, the only reason I
can
think of for doing it this way is so that you can chain multiple
add_content calls: book.add_content(a, b).add_content(c, d). Otherwise,
why
not just define
def []=(k, v)
@hash[k] = v
end
and then you can have book[1] = 2? Maybe it doesn’t make sense to have a
Book look like a Hash, though, in which case you can define some other
foo=
method, if that’s meaningful. Method name aside, the @hash.merge!
approach
would be good if you can have more than one addition in one step:
def add(h = {})
@hash.merge!(h)
end
Which also avoids having to do add_content(a, b).add_content(c, d). #add
seems like it’s a bit too generic, but perhaps in the actual code it’ll
have a more meaningful name.
On Tue, Nov 1, 2011 at 11:13 AM, Michael K. [email protected]
wrote:
On Tue, Nov 1, 2011 at 3:14 AM, Reginald T. [email protected] wrote:
I have a class that uses hash as its internal store. What’s a good way
to communicate the interface of my methods.
Document them.
Do you need to leak this implementation detail? You could make
add_content a two argument method and changing it like this:
def add_content(k, v)
@hash.merge(Hash[k,v]) # or @hash.merge({k => v})
end
I don’t see how changing the argument count of #add_content has
anything to do with “leaking implementation detail”. It’s perfectly
OK to use #add_content with a single Hash argument - regardless of
internal representation. I think you are mixing two unrelated things
here.
The only place where leaking actually comes into play is return
values: both methods leak the internal Hash. But that can be easily
avoided by returning self and using #dup.
Whether it is wise to use a single Hash argument when the intention is
actually to just add a pair (of what btw?) is another question. So,
to remedy this one could do
class Book
def initialize
@structure = {}
end
Add another chapter with title.
def add_content(chapter, title)
raise “Wrong arguments” unless Integer === chapter && String ===
title
@structure[chapter] = title.dup.freeze
self
end
Get the (ordered) list of chapter numbers and titles.
def contents
@structure.dup
# or: @structure.sort_by {|chapter, title| chapter}
end
end
Kind regards
robert