Hashes vs. Multiple Params? - ruby

It is very common in Ruby to see methods that receive a hash of parameters instead of just passing the parameters to the method.
My question is - when do you use parameters for your method and when do you use a parameters hash?
Is it right to say that it is a good practice to use a parameter hash when the method has more than one or two parameters?

I use parameter hashes whenever they represent a set of options that semantically belong together. Any other parameters which are direct (often required) arguments to the function, I pass one by one.

You may want to use a hash when there are many optional params, or when you want to accept arbitrary params, as you can see in many rails's methods.

if you have more than 2 arguements. you should start thinking of using hash.
This is good practise clearly explained in clean code link text

One obvious use case is when you are overriding a method in a child class, you should use hash parameters for the parent method's parameters for when you call it.

On another note, and this is not only related to Ruby but to all languages:
In APIs which are in flux, it is sometimes useful to declare some or all parameters to a function as a single parameters object (in Ruby these could be hashes, in C structs, and so on), so as to maintain API stability should the set of accepted arguments change in future versions. However, the obvious downside is that readability is drastically reduced, and I would never use this "pattern" unless I'd really really have to.

Related

How to name bools that hold the return value of IsFoo() functions?

I read that it's a good convention to name functions that return a bool like IsChecksumCorrect(Packet), but I also read that it's a good convention to name boolean variables like IsAvailable = True
But the two rules are incompatible: I can't write:
IsChecksumCorrect = IsChecksumCorrect(Packet)
So what's the best way to name vars that store boolean values returned by such functions?
PS: Extra points if you can think of a way that doesn't depend on changing the case (some languages--like Delphi--are case-insensitive).
First of all, there can be difficulties only with functions that don't require arguments, in your example instead the variable should just be called IsPacketChecksumCorrect.
Even with functions with no arguments I think you would only have problems if you were just caching the result of the function, for performance's sake, and you could safely replace all instances of the variables with calls to the function if it weren't for the performance. In all other cases I think that you could always come up with a more specific name for the variable.
If you were indeed just caching, why not just call the variable Functionname_cache? It seems quite clear to me.
If you needed to use a lot this "technique" in your project and _cache seemed too long or you did not like it you could well settle on a convention of your own; as long as you are consistent you can adopt whatever works best for you, people new to the project just need to be explained the convention once and they will easily recognize it ever after.
By the way, there are various opinions on the conventions for the naming of booleans. Personally I prefer to put the subject first, which makes the Ifs more readable, e.g. ChecksumIsCorrect, ChecksumCorrect or ChecksumCorrectness. I actually prefer not to put the Is altogether, the name usually remains clear even if you omit it.

Naming convention for syntactic sugar methods

I'm build a library for generic reporting, Excel(using Spreadsheet), and most of the time I'll be writing things out on the last created worksheet (or active as I mostly refer to it).
So I'm wondering if there's a naming convention for methods that are mostly sugar to the normal/unsugared method.
For instance I saw a blog post, scroll down to Composite, a while ago where the author used the #method for the sugared, and #method! when unsugared/manual.
Could this be said to be a normal way of doing things, or just an odd implementation?
What I'm thinking of doing now is:
add_row(data)
add_row!(sheet, data)
This feels like a good fit to me, but is there a consensus on how these kinds of methods should be named?
Edit
I'm aware that the ! is used for "dangerous" methods and ? for query/boolean responses. Which is why I got curious whether the usage in Prawn (the blog post) could be said to be normal.
I think it's fair to say that your definitions:
add_row(data)
add_row!(sheet, data)
are going to confuse Ruby users. There is a good number of naming conventions is the Ruby community that are considered like a de-facto standard for naming. For example, the bang methods are meant to modify the receiver, see map and map!. Another convention is add the ? as a suffix to methods that returns a boolean. See all? or any? for a reference.
I used to see bang-methods as more dangerous version of a regular named method:
Array#reverse! that modifies array itself instead of returning new array with reversed order of elements.
ActiveRecord::Base#save! (from Rails) validates model and save it if it's valid. But unlike regular version that return true or false depending on whether the model was saved or not raises an exception if model is invalid.
I don't remember seeing bang-methods as sugared alternatives for regular methods. May be I'd give such methods their own distinct name other then just adding a bang to regular version name.
Why have two separate methods? You could for example make the sheet an optional parameter, for example
def add_row(sheet = active_sheet, data)
...
end
default values don't have to just be static values - in this case it's calling the active_sheet method. If my memory is correct prior to ruby 1.9 you'd have to swap the parameters as optional parameters couldn't be followed by non optional ones.
I'd agree with other answers that ! has rather different connotations to me.

ruby 1.9.2 uniq method not working against array of custom classes

I have an array of custom classes. I've defined <=> on them, and have tested to make sure that my custom definition behaves as it should. I assumed that I could then call [].uniq and have it filter out my duplicates, but that isn't happening. Is there another operator I need to overload?
Array#uniq is based on equality, not on ordering, so your objects need to respond to eql?. Also, it uses hashing to speed up performance, so you need to implement hash as well.
Unfortunately, this contract isn't specified in the documentation, but it usually is specified in pretty much every Ruby book or course.
What I needed to implement, was .hash

Validate arguments in Ruby?

I wonder if one should validate that the arguments passed to a method is of a certain class.
eg.
def type(hash = {}, array = [])
# validate before
raise "first argument needs to be a hash" unless hash.class == Hash
raise "second argument needs to be an array" unless array.class == Array
# actual code
end
Is it smart to do this or is it just cumbersome and waste of time to validate all passed in arguments?
Are there circumstances when you would like to have this extra security and circumstances when you won't bother?
Share your experiences!
I wouldn't recommend this specific approach, as you fail to accommodate classes that provide hash or array semantics but are not that class. If you need this kind of validation, you're better off using respond_to? with a method name. Arrays implement the method :[], for what it's worth.
OpenStruct has hash semantics and attribute-accessor method semantics, but won't return true for the condition hash.class==Hash. It'll work just like a hash in practice, though.
To put it in perspective, even in a non-dynamic language you wouldn't want to do it this way; you'd prefer to verify that an object implements IDictionary<T>. Ruby would idiomatically prefer that, when necessary, you verify that the method exists, because if it does, the developer is probably intending their object to act alike. You can provide additional sanity with unit tests around the client code as an alternative to forcing things to be non-dynamic.
There's usually no need to validate that arguments are of a certain class. In Ruby, you're encouraged to use Duck Typing.
I have found that validating that the input parameters meet your preconditions is a very valuable practice. The stupid person that its saves you from is you. This is especially true for Ruby as it has no compile time checks. If there are some characteristics of the input of your method that you know must be true it makes senes to check them at run time and raise errors with meaningful error messages. Otherwise, the code just starts producing garbage out for garbage in and you either get a wrong answer or an exception down the line.
I think that it is unnecessary. I once read on a blog something like "If you need to protect your code from stupid people, ruby isn't the language for you."
If you want compiler/runtime-enforced code contracts, then Ruby isn't for you. If you want a malleable language and easy testability, then Ruby is.

Using Hash Tables as function inputs

I am working in a group that is writing some APIs for tools that we are using in Ruby. When writing API methods, many of my team mates use hash tables as the method's only parameter while I write my methods with each value specified.
For example, a class Apple defined as:
class Apple
#commonName
#volume
#color
end
I would instantiate the class with method:
Apple.new( commonName, volume, color )
My team mates would write it so the method looked like:
Apple.new( {"commonName"=>commonName, "volume"=>volume, "color"=>color )
I don't like using a hash table as the input. To me is seems unnecessarily bulky and doesn't add any clarity to the code. While it doesn't appear to be a big deal in this example, some of our methods have greater than 10 parameters and there will often be hash tables nested in inside other hash tables. I also noticed that using hash tables in this way is extremely uncommon in public APIs(net/telnet is the only exception that I can think of right now).
Question: What arguments could I make to my team members to not use hash tables as input parameters. The bulkiness of the code isn't a sufficient justification(they are not afraid of writing 200-400 character lines) and excessive memory/processing overhead won't work because it won't become an issue with the way our tools will be used.
Actually if your method takes more than 10 arguments, you should either redesign your class or eat dirt and use hashes. For any method that takes more than 4 arguments, using typical arguments can be counter-intuitive while calling the method, because you got to remember the order correctly.
I think best solution would be to simply redesign such methods and use something like builder or fluent patterns.
First of all, you should chide them for using strings instead of symbols for hash keys.
One issue with using a hash is that you then have to check that all the appropriate keys are in it. This makes it useful for optional parameters, but for mandatory one, why not use the built-in functionality of the language? For example, with their method, what happens if I do this:
Apple.new( {"commonName"=>commonName, "volume"=>volume} )
Whereas, with Apple.new(commonName, volume), you know you'll get an ArgumentError.
Named parameters make for more self-documenting code which is nice. But other than that there's not a lot of difference. The Hash allows for more flexibility, especially if you start doing any method aliasing. Also, the various Hash methods in ActiveSupport make setting defaults and verifying inputs pretty painless. I guess this probably wasn't the answer you were looking for.

Resources