Hi,
I'm a newbee to Ruby, can any one you please suggest me ways to debug a
Ruby Program.
My major debugging techniques, in order of how useful they tend to be:
1. Read code carefully, including refactoring it to be more readable.
Applicable refactorings include renaming methods, renaming variables,
extracting methods, inlining methods, and restructuring algorithms.
Adding comments so it is more clear probably don't count as
refactoring; I find that useful, too.
2. As has already been mentioned, use of puts and inspect, for example
# Made up example
something.each do |thing_you_are_going_to_process|
puts "Processing #{thing_you_are_going_to_process.inspect}"
... processing here ...
end
to see that you're operating in a sane way. Various forms of this is,
at least for me, the number two major debugging technique
3. Add tests around parts of your program that are likely to contain
errors. For instance, I've been operating with some slightly complex
code to drive translation from one database to another lately; instead
of dealing with bugs in that code, I've added tests for each code
path.
4. Add invariant checking to your code - ie, check that things that
should not be able to fail do not, in fact, fail. Here's an example:
# Example paraphrased from some Perl code I did this with yesterday
new_args['Created'] = WebApp::Util.string_to_stamp(old['create_date''])
raise "Unable to translate #{old['create_data'].inspect} for
'Created'" unless new_args['Created']
For more complex programs, it is sometimes very useful to check that
complete data structures are the way they are supposed to be. For
example, in a tree structure where every node is supposed to point at
their parent, you can check with something like this (called as
tree_root.invariant):
class Tree
def internal_invariant
raise "Left #{@left.inspect} has wrong parent in #{self.inspect}"
if @left && @left.parent != self
raise "Right #{@right.inspect} has wrong parent in
#{self.inspect}" if @right && @right.parent != self
@left.internal_invariant if @left
@right.internal_invariant if @right
end
def invariant
raise "Root has parent?" if @parent
internal_invariant
end
end
I find the invariant adding and puts variants to flow over into each
other a bit in practice; I'll often add extra invariants when doing
debugging, and a bunch of output (puts statatements), and then I use
"cvs diff" to find and eliminate the puts statements while committing
the new invariant checks.
Bonus tip: Eliminating stuff from a diff is often most easily done by
storing the diff in a file, editing out everything you want to keep,
and then doing patch -R < file_with_diffs_to_remove
Eivind.
Eivind.