[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Stepping out on a Limb - some very ugly code

MenTaLguY

2/28/2007 7:08:00 PM

On Thu, 1 Mar 2007 02:56:25 +0900, Samantha <rubygeekgirl@gmail.com> wrote:
> I have written some horribly ugly procedural code and wanted to get some
> input as to how I can make it more Ruby like.

Hi, thanks for writing. It sounds like you have a fairly good sense of code aesthetics already, which will help you out as you progress. Just don't be too hard on yourself; while you correctly recognize that there's room for improvement, your code isn't too bad, given what it does.

That said, I guess three things stand out at the moment -- two are a matter of Ruby style, the other isn't really Ruby-specific.

First, it's probably more readable to avoid the "if cond:" syntax, particularly with an else clause. For instance, try this:

if correct.downcase == "yes"
puts("Great, let's continue!")
else
puts("Please come back when you know where you live.")
end

instead of this:

if correct.downcase == "yes": puts("Great, let's continue!")
else puts("Please come back when you know where you live.")
end

The second thing is that it's often more readable to take advantage of Ruby's string interpolation. For instance, you can write this:

puts("You have entered #{ full_name } as your name. Is this correct? (yes/no)")

instead of this:

puts("You have entered " + full_name + " as your name. Is this correct? (yes/no)")

(admittedly, in this particular case, it's almost purely a question of taste -- there's not a huge readability advantage between the two; the first is just more "idiomatic")

The third thing is about looking for recurring patterns in the code; the presence of such patterns has a lot to do with "ugly" code. The best way to deal with them is to factor them out -- in very much the same sense that you could rewrite 3x + 2x^2 as x(3 + 2x).

For instance: the main recurring pattern is a puts, followed by a gets.chomp. We can pull that out into a separate function:

def prompt(string)
puts(string)
gets.chomp
end

And rewrite the prompts accordingly:

puts("Welcome to ResumeBuilder v.1")
first_name = prompt("Please enter your first name: ").capitalize!
last_name = prompt("Please enter your last name: ").capitalize!
full_name = "#{ first_name } #{ last_name }"

(etc.)

At this point, another pattern becomes apparent: asking for a yes/no answer and checking whether it is equal to "yes". We can use the "prompt" function we've already built as part of another one just for yes/no answers:

def boolean_prompt(string)
prompt("#{ string } (yes/no)").downcase == "yes"
end

And then you can rewrite the yes/no questions like this:

correct = boolean_prompt("You have entered #{ full_name } as your name. Is this correct?")
if correct
puts("Great, let's get started, #{ first_name }!")
else
puts("Please come back when you know your name.")
exit 1
end

[ note that I've added an "exit 1" to leave the program in the case where the name was wrong, which seems to have been your intent? ]

Anyway, those are the major items which come to mind at the moment. We could probably continue refactoring the code like this a little bit further (for instance, a "prompt" function just for capitalized input), but I think that'd be passsing a point of diminishing returns -- your program is already a pretty concise expression of what it does. Also, because of that, don't worry too much that your program isn't using classes or other "special" Ruby features just yet -- as you add more functionality to your program, there will be plenty of opportunities to refactor code to use them.

-mental