views:

120

answers:

3

I'm rephrasing this question because it was either too uninteresting or too incomprehensible. :)

The original question came about because I'm making the transation from Java to Groovy, but the example could apply equally when transitioning to any of the higher-level languages (Ruby, Python, Groovy).

Java is easy to debug because there is a clear relationship between lines of code, and fairly fine-grained behaviour, e.g. manipulate an array using a for loop:

for ( int i=0; i < array1.size(); i++ )
{
    if ( meetsSomeCriterion(array1.elementAt(i) )
    {
        array2.add( array1.elementAt(i) );
    }   
}

so you can set a breakpoint on the test in the loop and see what happens next. (I know there are better ways to write this; it's just to illustrate the point.)

In languages like Ruby the idiomatic style seems to favour higher-level one-liner coding, e.g. from http://rubyquiz.com/quiz113.html

quiz.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse

I'm wondering if you can suggest any effective techniques for debugging this, for example if you changed the regular expression ... would you still use the traditional debugger, and step into/over the chained methods? Or is there a better way?

Thanks!

+3  A: 

If I were to debug your example, the first thing I would do is break it down into multiple steps. I don't care if it's "pythonic" or "the ruby way" or "tclish" or whatever, code like that can be difficult to debug.

That's not to say I don't write code like that. Once it's been debugged it is sometimes OK to join it all into a single line but I find myself leaning more toward readability and maintainability and less toward writing concise code. If the one-liner approach is genuinely more readable I'll go with it, but if it's not, I don't.

Bryan Oakley
Thank you Bryan, RHSeeger and Geo for clearing this up for me. As you all seem to agree I'm making Bryan's as the accepted answer, since this appears first (chronologically?).
Andrew Whitehouse
That appears to be the case, yes, so it makes sense to mark his as the answer. Besides, Bryan is smarter than I am ;)
RHSeeger
A: 

If I have to debug such a line as the one you posted I find that nothing helps as much as breaking it into stand-alone statements. That way you can see what each method receives as a parameter , and what it returns.

Such statements make code hard to maintain.

Geo
A: 

Combining multiple actions into a single line is all well and good, when you can still look at the line in question and know that it's going to do exactly what you want it to do. The minute you get to the point where you can't look at the code and go "yeah, ok, it does xyz, there's no way it couldn't" is when you should consider breaking it into individual pieces.

I give the same advice to people with long procs/methods. If you can't look at the code and know exactly what it's doing in all situations, then break it up. You can break up each of the "non-obvious" bits of code into it's own method and write tests for that piece alone. Then, you can use that method in your original method and know it's going to work... plus your original method is now easier to understand.

Along the same lines, you can break your "scan(/(?:\d*.)?\d{1,3}-?/)" code off into another method and test that by itself. The original code can then use that method, and it should be much easier to understand and know it's working.

RHSeeger