From: Michael Judge Date: 2006-12-31T17:08:10+09:00 Subject: Re: Methods validating their arguments: good or bad? Hi, On Dec 30, 2006, at 2:50 PM, dblack@wobblini.net wrote: > Hi -- > > On Sat, 30 Dec 2006, Michael Judge wrote: > >> >> Code Complete* recommends that methods validate the arguments they >> receive. The author went on to say that in a 1984 study, >> researchers discovered that miscommunication between routines >> caused 39% of the programming errors observed. The idea is that, >> if we check our arguments before using them, bad data won't flow >> through undetected, causing even vaguer problems later on. Lucky >> for us, Ruby checks the number of arguments received against the >> method definition -- finding many of these problems at the time >> they're written. > > The checking doesn't happen until the method is called, though. You're right. That's an important distinction. >> Plus it would probably need a few helper methods just to remain >> readable. But it would also prevent programmers from wasting huge >> amounts of time hunting for why their browser rendered a bad select >> box. The argument for adding validation is really strong for any >> non-trivial project, but does it ruin Ruby's elegance? >> >> What do you think? Do you usually validate your arguments? > > It depends a bit on what you mean by validate. It's definitely good > for methods to handle bad data gracefully, but sometimes just letting > Ruby fail and raise an exception is more graceful than trying to > figure out in a hands-on way what's going to go wrong and then raising > the exception yourself. > > David I very much agree with you. I love when Ruby fails. The stack trace and error message are all I need to get back on track after a snafu. But what about when Ruby doesn't fail? I'm not talking about syntax problems, but just general programmer stupidity, like when I blatantly assign the wrong object to a temporary variable and then send it off somewhere. That's the part I want to trap. Actually, I want to trap it, strip it naked, and parade it up and down the street. # # Example of Argument Validation # require 'validate_arguments' def print_report(record) validate do hash_role record, :keys => [:id, :status] numeric_role record[:id], :values => [0..100] symbol_role record[:status], :values => [:failed, :passed] end puts <<-END Report #{record[:id]} Status: #{record[:status]} ----- END end # The :id key should be a number, but that would make for a crappy example. print_report :id => [1,2], :status => :passed # Let's try sending it a different key than :id too. print_report :number => 2, :status => :failed # # Finish # Without argument validation, it would print this. (Egads!) Report 12 Status: passed ------ Report Status: failed ------ But with the validate block in place, it fails: ArgumentError: Object should be a number-like object from (irb):7:in `print_report' from ./validate_arguments.rb:3:in `validate' from (irb):5:in `print_report' from (irb):18 from :0 ArgumentError: Hash-like object is missing key :id from (irb):6:in `print_report' from ./validate_arguments.rb:3:in `validate' from (irb):5:in `print_report' from (irb):19 from :0 That's better than a broken report, right? There's probably a better solution to this (like, drinking less tequila.) But I feel pretty good about putting little straightjackets on my variables. I think they feel loved. Kind regards, Michael Judge