Ruby Not observing DRY principle

F

flebber

HI I am hoping you can give me some guidance. I feel I really am
getting Ruby, far more than I got python I am doing more now in a
couple of weeks than I did with python.

However I just need to get my head around the flow of transactions to
ensure I am not breaking the DRY principle and defeating the purpose
of object orientation.

If this is my proposed flow how can I do it better to be more ruby? I
am happy to do more reading but not always sure what I should
belooking up. I have tried to comment it to make as much sense as
possible.

This is my proposed flow. My main concern is around the option
calculations and selections.

def foo
some function
end

# get user input
user input 1
user input 2

pass user variables through foo, each option has different set
variables

??? Should I be using a foreach case statement here or am I someway
missing the
??? the point of object oriented language?
??? Should it be option1.foo, option2.foo etc
option1
foo(set of variables, user input 1)
# set of variables will be different for each option
# Sets will have same variable types but different values
option 2
foo(set of variables, user input 1)
foo(set of variables, user input 2)
option 3
foo(set of variables, user input 1)
foo(set of variables, user input 2)
option 4
foo(set of variables, user input 1)
foo(set of variables, user input 2)
# If result of both tests in an option proves true then output
options.

To_user valid options are
option 1
this is what the results are
option 3
this is what the results are

To_user please choose an option or none to start again.

# select case if I list the 5 cases here for a user to select how can
I limit the
# selection to valid input only????

If option 1
get some details
send to file dated with date user supplied
send to database

get user more calcs or end?
 
F

flebber

Any ideas appreciated. I just need to understand how to get the flow
better. I notice that if I am thinking something is to hard in Ruby
then I am probably doing it the wrong way. Each tie I do my program I
get better structure just concerned if I am missing the OO point
overall.....
 
A

Arturo Garcia

Any ideas appreciated. I just need to understand how to get the flow
better. I notice that if I am thinking something is to hard in Ruby
then I am probably doing it the wrong way. Each tie I do my program I
get better structure just concerned if I am missing the OO point
overall.....
I don't really understand what you're trying to do there, but I think you
need:

- An event handler (to intercept user input)
- Blocks to handle each of your events
- The process itself (a class representing what the program does)
** And, if the user is calling algorithms, then each algorithm belongs to it's
own class/function. How you call them is a matter of taste (I would push a
hash with algorithm parameters).

I think you need to get your ideas right, then apply ruby and its sugar.

Good luck!
 
F

flebber

I don't really understand what you're trying to do there, but I think you
need:

- An event handler (to intercept user input)
- Blocks to handle each of your events
- The process itself (a class representing what the program does)
** And, if the user is calling algorithms, then each algorithm belongs toit's
own class/function.  How you call them is a matter of taste (I would push a
hash with algorithm parameters).

I think you need to get your ideas right, then apply ruby and its sugar.

Good luck!

To me thats where I am tripping up, in my program I define a function
but don't seem to need a class or would it be simply that my function
I am calling is my class.

Really interested to now what type of case statement or for each
satement you would use with a block like below.

??? Should I be using a foreach case statement here or am I someway
missing the
??? the point of object oriented language?
??? Should it be option1.foo, option2.foo etc
option1
foo(set of variables, user input 1)
# set of variables will be different for each option
# Sets will have same variable types but different values
option 2
foo(set of variables, user input 1)
foo(set of variables, user input 2)
option 3
foo(set of variables, user input 1)
foo(set of variables, user input 2)
option 4
foo(set of variables, user input 1)
foo(set of variables, user input 2)
# If result of both tests in an option proves true then output
options.
 
A

Arturo Garcia

Really interested to now what type of case statement or for each
satement you would use with a block like below.
Sorry. I don't see where a foreach falls in there. If your options are
known, then you either a hash or a case would suffice. But again, it has
nothing to do with ruby.

event_handler = { :event => lambda { action } }

or

case event
when event
<< do something >>

I would prefer number 2 if you have 4 options, to be honest....
 
J

John Morrice

That is an example of the strategy pattern!

http://www.c2.com/cgi/wiki?StrategyPattern
option1
foo(set of variables, user input 1)
# set of variables will be different for each option
# Sets will have same variable types but different values
option 2
foo(set of variables, user input 1)
foo(set of variables, user input 2)
option 3
foo(set of variables, user input 1)
foo(set of variables, user input 2)
option 4
foo(set of variables, user input 1)
foo(set of variables, user input 2)

Is this sort of thing what you mean?

# The main loop
def main
loop do
puts "Please choose an option:"
puts " [1] Option1"
puts " [2] Option2"
puts " [3] Option3"
opt =3D nil

# A primitive event handler
case gets.to_i
when 1
opt =3D Option1.new
when 2
opt =3D Option2.new
when 3
opt =3D Option3.new
end

# Check if a valid option was entered
if opt
opt.run
else
puts "Error: please enter valid option."
end
end
end

# Run the program
main

You also need to define

# The first option. I wish I had a better name!
class Option1

# get some details
# send to file dated with date user supplied
# send to database
def run
end

end

Flebber, the benefit of using objects to represent your options, rather
than just functions, is that you may then apply the various object
oriented techniques.

E.g. TemplateMethod could remove duplicate code from
similar Options

http://www.c2.com/cgi/wiki?TemplateMethod

However, using a strict object oriented approach can be pretty
heavy-weight!

Johnny
 
S

shadowfirebird

It appears that my mail client is having trouble -- hence the blank
message bodies. Sorry about that.

Flebber, if you have a simple application and aren't coding to learn
about OOP, it may be that you simply don't need classes. In Ruby,
they are optional.

You should think of classes as a way of wrapping functionality and
data together. You've not told us anything about your data, or how
complex foo() is, so I'm not sure we can give you more concrete
suggestions. But if you start thinking about how the data needs to
be organised, and what operations the data needs to be able to perform
on itself, then either some classes will "pop out" -- or they won't,
and you'll know that this program does not need to be OOP.

With regard to your option selection block, I would personally put
that functionality into foo, and just pass foo a "mode" variable, so:

loop do
mode, data = getinput()
break if (mode == "quit")

foo(mode, data)
end

I'm not sure why your pseudocode asks for input twice and then runs
foo() twice, but presumably there is a good reason.

Likewise, we don't know whether you plan to gather input using a GUI
(which would involve an event-driven approach) or at the command line,
for instance (which would allow much simpler code).
 
F

flebber

It appears that my mail client is having trouble -- hence the blank
message bodies.  Sorry about that.

Flebber, if you have a simple application and aren't coding to learn
about OOP, it may be that you simply don't need classes.  In Ruby,
they are optional.

You should think of classes as a way of wrapping functionality and
data together.  You've not told us anything about your data, or how
complex foo() is, so I'm not sure we can give you more concrete
suggestions.   But if you start thinking about how the data needs to
be organised, and what operations the data needs to be able to perform
on itself, then either some classes will "pop out" -- or they won't,
and you'll know that this program does not need to be OOP.

With regard to your option selection block, I would personally put
that functionality into foo, and just pass foo a "mode" variable, so:

loop do
    mode, data = getinput()
    break if (mode == "quit")

    foo(mode, data)
end

I'm not sure why your pseudocode asks for input twice and then runs
foo() twice, but presumably there is a good reason.

Likewise, we don't know whether you plan to gather input using a GUI
(which would involve an event-driven approach) or at the command line,
for instance (which would allow much simpler code).
Is this sort of thing what you mean?

# The main loop
def main
loop do
puts "Please choose an option:"
puts " [1] Option1"
puts " [2] Option2"
puts " [3] Option3"
opt = nil

# A primitive event handler
case gets.to_i
when 1
opt = Option1.new
when 2
opt = Option2.new
when 3
opt = Option3.new
end

# Check if a valid option was entered
if opt
opt.run
else
puts "Error: please enter valid option."
end
end
end

Yes but this is how initially I started to write my code but then had
the thought that since my calculations weren't computer intensive. So
I thought why not calculate all options first and show what valid
options exist to the user rather than looping around the options
trying to find a valid option. Is this a good way to go.
I'm not sure why your pseudocode asks for input twice and then runs
foo() twice, but presumably there is a good reason.

Likewise, we don't know whether you plan to gather input using a GUI
(which would involve an event-driven approach) or at the command line,
for instance (which would allow much simpler code).

I ask after the program has identified there is a valid option and the
user wants to select it, it is valid data but only names and
identifiers that will be recorded in a database not relevant to
whether the calculation is valid.

i will be using a command line solution. My calculations aren't
complex they simply pass through a small formula and check whether a
ratio resolves to true. If both true then its a valid option the user
can choose.
 
J

John Morrice

Yes but this is how initially I started to write my code but then had
the thought that since my calculations weren't computer intensive. So
I thought why not calculate all options first and show what valid
options exist to the user rather than looping around the options
trying to find a valid option. Is this a good way to go.

That's entirely up to you.

However, I think most mail clients have a send button - even when you
haven't entered yet an email address!

John
 
F

flebber

That's entirely up to you.

However, I think most mail clients have a send button - even when you
haven't entered yet an email address!

John

Can a case statement return multiple correct cases?
 
S

Shadowfirebird

[Note: parts of this message were removed to make it a legal post.]
Can a case statement return multiple correct cases?

But this will, and it's no less compact than a case statement IMO:

wins = []
wins << 1 if (a > 3)
wnis << 2 if (a > 5)
wins << 3 if (a < 7)
wins << 4 if (a < 3)

For a = 4, wins should be [1,3]. Hopefully you get the idea.
 
F

flebber

[Note:  parts of this message were removed to make it a legal post.]
Can a case statement return multiple correct cases?

But this will, and it's no less compact than a case statement IMO:

wins = []
wins << 1 if (a > 3)
wnis << 2 if (a > 5)
wins << 3 if (a < 7)
wins << 4 if (a < 3)

For a = 4, wins should be [1,3].   Hopefully you get the idea.

I like your example so I started reading.

if for each wins in your example their was two conditions I could then
chain them together with an and. Awesome thanks.

So following your example where wins = [1,3] ( still not sure why ruby
doesn't have a multiple case select) can I use "and" "or"

If wins = 1 puts "for option 1 x = A_value and y = B_value"
and or
If wins = 2 puts "for option 2 x = A_value and y = B_value"
and or
If wins = 3 puts "for option 3 x = A_value and y = B_value"
and or
If wins = 4 puts "for option 2 x = A_value and y = B_value"
else puts " There were no valid options"
 
F

flebber

[Note:  parts of this message were removed to make it a legal post.]
Can a case statement return multiple correct cases?
nope.
But this will, and it's no less compact than a case statement IMO:
wins = []
wins << 1 if (a > 3)
wnis << 2 if (a > 5)
wins << 3 if (a < 7)
wins << 4 if (a < 3)
For a = 4, wins should be [1,3].   Hopefully you get the idea.

I like your example so I started reading.

if for each wins in your example their was two conditions I could then
chain them together with an and. Awesome thanks.

So following your example where wins = [1,3] ( still not sure why ruby
doesn't have a multiple case select) can I use "and" "or"

If wins = 1 puts "for option 1 x = A_value and y = B_value"
    and or
If wins = 2 puts "for option 2 x = A_value and y = B_value"
    and or
If wins = 3 puts "for option 3 x = A_value and y = B_value"
    and or
If wins = 4 puts "for option 2 x = A_value and y = B_value"
else puts " There were no valid options"

I apologise. Combination of learning and tired. I woke up in the
middle of the night and went while statement or case statement. Silly
me found this this morning.
http://www.skorks.com/2009/08/how-a-ruby-case-statement-works-and-what-you-can-do-with-it/
 
M

Mike Stephens

def foo
some function
end

# get user input
user input 1
user input 2

foo(user input, option number)

As you are (so far) writing in a procedural style, I think foo looks
more natural than user_input.foo. Your first procedure (which might be
foo in this case) needs to route according to the selected option.

The basic rule of all programming, not just OO, is to create a set of
methods - some clearly acting as controllers , and others carrying out
tasks - that divide the problem up into discrete encapsulated 'black
box' units. So just avoid jumbling up too much functionality in any
given
method.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,010
Latest member
MerrillEic

Latest Threads

Top