Which is better -- method option or multiple methods?

T

Trans

In the case of limited options, like the following example, which is
better?

class String

def align(direction. spacing)
case direction
when :left
...
when :right
...
when :center
...
end
end

OR

def align_left(spacing)
...
end

def align_right(spacing)
...
end

def align_center(spacing)
...
end

Thanks,
T.
 
R

Robert Klemme

2008/3/10 said:
In the case of limited options, like the following example, which is
better?

class String

def align(direction. spacing)
case direction
when :left
...
when :right
...
when :center
...
end
end

OR

def align_left(spacing)
...
end

def align_right(spacing)
...
end

def align_center(spacing)
...
end

Thanks,

The general wisdom suggests to favor multiple methods over a single
method that changes behavior based on arguments. They are easier to
implement (all the switching and conditions are not needed) but most
of all the code is more modular on the interface level. Note that you
can still use a single method to implement behavior internally if that
is more efficient / easier.

Unfortunately I do not have a pointer to a more thorough discussion handy...

Kind regards

robert
 
R

Ranieri Teixeira

I think it's a matter of modularity vs performance of the algorithm you
encapsulate in your methods.
You must balance its needs in your code.
Multiple methods let you get more modular, in fact easy to mantain code.
Multiple arguments oprions are for a method that this type of coding is
coherent.
It works for me.

The general wisdom suggests to favor multiple methods over a single
method that changes behavior based on arguments. They are easier to
implement (all the switching and conditions are not needed) but most
of all the code is more modular on the interface level. Note that you
can still use a single method to implement behavior internally if that
is more efficient / easier.

Unfortunately I do not have a pointer to a more thorough discussion
handy...

Kind regards

robert


--=20
Ranieri Barros Teixeira
Ci=EAncia da Computa=E7=E3o - Faculdade de Computa=E7=E3o - Universidade Fe=
deral do
Par=E1 (UFPA)
http://tickruby.blogspot.com
http://rubyxchart.rubyforge.org
 
P

Paul Mckibbin

Method options are better if you ever want to extend it. I personally
would have both in library code, but would be inclined to keep the
multiple method code private to keep the interface clean.

class String
private
def align(direction. spacing)
case direction
when :left
...
when :right
...
when :center
...
end
end

public
def align_left(spacing)
align:)left,spacing)
end

def align_right(spacing)
align:)right,spacing)
end

def align_center(spacing)
align:)center,spacing)
end
end
 
R

Robert Klemme

Please do not top post.

I think it's a matter of modularity vs performance of the algorithm you
encapsulate in your methods.

How can the single method approach be faster when it has to do more,
namely option checking and branching?
Multiple methods let you get more modular, in fact easy to mantain code.
Exactly.

Multiple arguments oprions are for a method that this type of coding is
coherent.

Sorry, I do not understand what this is supposed to mean. Can you
elaborate, please?
It works for me.

What exactly?

Kind regards

robert
 
R

Robert Klemme

Method options are better if you ever want to extend it.

How is that? How can a single method that switches over one or more
arguments to decide what to do be easier extended? What if you detect
that the new or one of the algorithms needs an additional argument which
is not needed by other algorithms?
I personally
would have both in library code, but would be inclined to keep the
multiple method code private to keep the interface clean.

A clean interface in my world is one where one method does exactly one
thing - and not multiple things. If all those algorithms share some
common code this should go into another method that all of them use.
Much cleaner, more maintainable and easier to understand. Just think
about a method's documentation, that can do 5 different things vs. five
methods with their own documentation.

I tried to come up with a good search string for Google, 'method "do
just one thing"' is currently the closest that reveals some hits about
the matter.

Kind regards

robert
 
P

Paul Mckibbin

Robert said:
How is that? How can a single method that switches over one or more
arguments to decide what to do be easier extended? What if you detect
that the new or one of the algorithms needs an additional argument which
is not needed by other algorithms?


A clean interface in my world is one where one method does exactly one
thing - and not multiple things. If all those algorithms share some
common code this should go into another method that all of them use.
Much cleaner, more maintainable and easier to understand. Just think
about a method's documentation, that can do 5 different things vs. five
methods with their own documentation.

You are quite right. My code showed what I intended, but I garbled the
explanation. Single method with switches should be private for
implementation, and I tend to use that to make the code DRYer. Multiple
methods for the exposed interface.
Normally I'd start with multiple (separate) methods and create the
private function when there was an obvious need to refactor and
opportunity to make the code DRYer.
 
R

Robert Klemme

You are quite right. My code showed what I intended, but I garbled the

To be honest, I just briefly looked at the code because it looked too
similar to the original. :) But even then I would have asked how your
explanation and code fit together. :)
explanation. Single method with switches should be private for
implementation, and I tend to use that to make the code DRYer. Multiple
methods for the exposed interface.
Normally I'd start with multiple (separate) methods and create the
private function when there was an obvious need to refactor and
opportunity to make the code DRYer.

Yep, same here.

Kind regards

robert
 
L

Lionel Bouton

Trans said:
In the case of limited options, like the following example, which is
better?

class String

def align(direction. spacing)
case direction
[...]
end

OR

def align_left(spacing)
...
end
[...]

If the direction is supposed to be static everywhere in the code, I'd
use the align_<direction>(*args) methods.

But if the direction is dynamic (based on a property, a preference, any
algorithm, ...) then I'd use the align(direction, *args) method.
Otherwise you will get

case direction
when :left
align_left(...)
when :right
align_right(...)
when :center
align_center(...)
end

constructs everywhere...

But I'd probably use the align_* methods to implement align(direction,
....) for readability and flexibility anyway. In this case align_* would
be private if you don't need them to simplify the API or public if you
actually need them.

Lionel
 
P

Paul Mckibbin

If the direction is supposed to be static everywhere in the code, I'd
use the align_<direction>(*args) methods.

But if the direction is dynamic (based on a property, a preference, any
algorithm, ...) then I'd use the align(direction, *args) method.
Otherwise you will get

case direction
when :left
align_left(...)
when :right
align_right(...)
when :center
align_center(...)
end

constructs everywhere...

But I'd probably use the align_* methods to implement align(direction,
...) for readability and flexibility anyway. In this case align_* would
be private if you don't need them to simplify the API or public if you
actually need them.

Lionel

Surely then there would then be a decision making process that would set
the variable <direction>, and how is that simpler than calling the
function?

In any case, you can replace your "case direction" constructs with

send("align_#{direction}",spacing)

Mac
 
L

Lionel Bouton

Paul said:
Surely then there would then be a decision making process that would set
the variable <direction>

That's what I meant by "dynamic"...
, and how is that simpler than calling the
function?

It's not. It's why it was used as an argument for the case where you'd
prefer to make this function public (assuming we speak of
align(direction, *args)): the "dynamic" one.

Was my post so confusing?
In any case, you can replace your "case direction" constructs with

send("align_#{direction}",spacing)

Of course you can. But I won't: I don't find this coding-style very
maintainable or easy to read. It's a matter of taste, I only presented
mine...

Lionel
 
P

Paul Mckibbin

It's not. It's why it was used as an argument for the case where you'd
prefer to make this function public (assuming we speak of
align(direction, *args)): the "dynamic" one.

Was my post so confusing?

Not confusing. I can see some cases where the decision making process
would be embedded and the method call deferred, but by the same token,
the decision process could be:

direction=case <some logic>
when <foo>
:left
when <bar>
:right
etc....

which was what I was referring to. I'm sure that we can come up with
example and counter example all night. :)
Of course you can. But I won't: I don't find this coding-style very
maintainable or easy to read. It's a matter of taste, I only presented
mine...

That was an artificial example, which I don't think I've ever coded
sober. If I found myself in the "real" situation where I was forced to
do this more than once, I'd consider making both mechanisms public and
calling align(direction,spacing) too. It's all a matter of working out
what you need and refactoring accordingly.

Mac
 
R

Ranieri Teixeira

How can the single method approach be faster when it has to do more,
namely option checking and branching?


I want to say that when you use one monolitic method to run a whole
algorithm, it runs faster than using separated methods, yes just because
branching. But, I'm wrong because, as you wrote, multiple options also caus=
e
branching.
Sorry, I do not understand what this is supposed to mean. Can you
elaborate, please?

Here, you must use several options when it make sense, as in the call to an
activerecor find method, like:

find:)all, :eek:rder =3D> 'name ASC', :conditions =3D> ['service_usage >=3D ?'=
, 50])

I hope this reply is more clear.


--=20
Ranieri Barros Teixeira
Ci=EAncia da Computa=E7=E3o - Faculdade de Computa=E7=E3o - Universidade Fe=
deral do
Par=E1 (UFPA)
http://rubytags.blogspot.com
http://rubyxchart.rubyforge.org
 
A

Avdi Grimm

Method options are better if you ever want to extend it. I personally
would have both in library code, but would be inclined to keep the
multiple method code private to keep the interface clean.

I would do just the opposite, for the same reason. #align_left
makes it completely obvious what the method will do on the first
glance. #align() forces me to look up the valid arguments.
 
P

Pascal J. Bourguignon

Trans said:
In the case of limited options, like the following example, which is
better?

class String

def align(direction. spacing)
case direction
when :left
...
when :right
...
when :center
...
end
end

OR

def align_left(spacing)
...
end

def align_right(spacing)
...
end

def align_center(spacing)
...
end

Thanks,
T.

OR:

def align(direction. spacing)
insertSpaces( 4 * @@mapDirectionsToOffset[direction] );
end

That is, you could choose between one form or the other depending on
whether the method is continuous or discontinuous on that argument.
If you have to write a case, then use several methods. If you can
define a single formula, then use a single method.

Becareful in spite of my formulation, this choice should be done from
an abstract point of view, is the essence of this parameter to
influence the method in a discontinuous way or a continuous way?
Because we're talking here of the interface, and this interface should
speak of the essence of things, not of their implementation details.
 
P

Paul Mckibbin

Avdi said:
I would do just the opposite, for the same reason. #align_left
makes it completely obvious what the method will do on the first
glance. #align() forces me to look up the valid arguments.

You need to read the later post, or look at the code. We're actually
agreeing that
having separate methods are better than a single method.

Mac
 
S

Sam Smoot

You are quite right. My code showed what I intended, but I garbled the
explanation. Single method with switches should be private for
implementation, and I tend to use that to make the code DRYer. Multiple
methods for the exposed interface.
Normally I'd start with multiple (separate) methods and create the
private function when there was an obvious need to refactor and
opportunity to make the code DRYer.

This topic really bothers me. ;-) The tendency to see more Ruby
(mostly Rails) code use option hashes all over the place is sloppy
(IMO). The interface is less clear. Behaviour breaks or changes
unexpectedly. It's just bad practice.

Branching isn't DRY. So maybe there's a responsibility they all share
that could be extracted. In this case maybe that's generating X
characters of padding. That could be extracted. But making a "meta-
method" is not in itself DRY. In fact, the goal of DRYness seems to
lately be trumping longer standing lessons of loose coupling, cohesive
code, composition over inheritance, seperation of concerns, etc. All
of these should be much higher priority than DRYness. In fact, to go
to an extreme, you'll end up with much nicer code if you completely
abandon attempts at DRYness outside of your business layer and instead
focus on composition, cohesion and SoC.

Just one ranter's opinion. ;-)

DRY is the new new, and like every other that came before it, the most
recent probably being Design Patterns, it's being over-used and abused
to the detriment of code quality.
 
T

Trans

This topic really bothers me. ;-) The tendency to see more Ruby
(mostly Rails) code use option hashes all over the place is sloppy
(IMO). The interface is less clear. Behaviour breaks or changes
unexpectedly. It's just bad practice.

Branching isn't DRY. So maybe there's a responsibility they all share
that could be extracted. In this case maybe that's generating X
characters of padding. That could be extracted. But making a "meta-
method" is not in itself DRY. In fact, the goal of DRYness seems to
lately be trumping longer standing lessons of loose coupling, cohesive
code, composition over inheritance, seperation of concerns, etc. All
of these should be much higher priority than DRYness. In fact, to go
to an extreme, you'll end up with much nicer code if you completely
abandon attempts at DRYness outside of your business layer and instead
focus on composition, cohesion and SoC.

Just one ranter's opinion. ;-)

DRY is the new new, and like every other that came before it, the most
recent probably being Design Patterns, it's being over-used and abused
to the detriment of code quality.

How does this translate into an answer to the original question?

Interesting analysis.

T.
 
T

Trans

Not confusing. I can see some cases where the decision making process
would be embedded and the method call deferred, but by the same token,
the decision process could be:

direction=case <some logic>
when <foo>
:left
when <bar>
:right
etc....

Curious way to share common logic.
which was what I was referring to. I'm sure that we can come up with
example and counter example all night. :)

This is how I also conceived of having the best of both options.

An advantage to dynamic form that I have not seen mentioned yet, is
the ease of using a variable setting for direction. This makes it
readily alterable based on any given preference or concern. One
conceivable usage of this variability is as a "trait" of a class.

class TextField
attr_accessor :direction

def initialize(txt)
@text = txt
end

def align
@text.align(direction)
end
end
It's all a matter of working out what you need and refactoring accordingly.

Perhaps, but the need here is completely general. I wonder if the
choice only exists because

send("align_#{direction}", spacing)

is so fugly,

T.
 

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,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top