Design question: class methods verses initialize


#1

I have a design question for a beginner:

what is better for my case?
I want to access functionality from a library I created.
I’ve tried class methods like this:

class Calc
def Calc.velocity_head(v)
v**2/(2.0*G)
end
def Calc.pressure_head§
h = p / Gamma
end
def etc…
end

This is nice because now I can create many “velocity_head” objects or
“pressure_head” objects as needed by doing vh1 = Calc.velocity_head(4.5)
for example. But what if I have a bunch of methods in a class that all
require the same exact arguments? My first thought was using initialize
and instance variables:

Class Geom
def initialize(b, y, m)
@b, @y, @m = b, y, m
end
def area
@a = (@b + @m * @y) * @y
end
def hyd_rad
@r = (@b + @m * @y) * @y / (@b + 2.0 * @y * (1 + @m**2)0.5)
end
def wet_perim
@p = @b + 2.0 * @y * (1.0 + @m
2)**0.5
end
def etc…
end

But now I have to do area1 = Geom.new(4, 1.5, 2) and then area1.area
Is this the only other way to do this:?

Class Geom
def Geom.area(b, y, m)
a = (b + m * y) * y
end
def Geom.hyd_rad(b, y, m)
r = (b + m * y) * y / (b + 2.0 * y * (1 + m**2)0.5)
end
def Geom.wet_perim(b, y, m)
p = b + 2.0 * y * (1.0 + m
2)**0.5
end
def etc…
end

I feel like I’m re-stating the arguments more than necessary. Could
someone give me some pointers? Thank you!


#2

On Jan 22, 9:40 am, Jason L. removed_email_address@domain.invalid
wrote:

But what if I have a bunch of methods in a class that all
require the same exact arguments? My first thought was using initialize
and instance variables:

This is a classic case of the Extract Class pattern (http://
www.refactoring.com/catalog/extractClass.html). It’s a good first
thought to have, Jason. (Or on second thought, it’d be Extract Class
if this functionality were already present in a separate class. Is
there a refactoring pattern called “Use Instances of Already-Present
Class”? I purport this is a classic case of a pattern whose name I
can’t think of right now.)

o< snip example >o

def Geom.wet_perim(b, y, m)
p = b + 2.0 * y * (1.0 + m**2)**0.5
end
def etc…
end

I feel like I’m re-stating the arguments more than necessary. Could
someone give me some pointers? Thank you!

So, as you realized, there’s some trouble with only using instances of
a class. Here’s one solution:

class Geom
def initialize(b, y, m)
@b, @y, @m = b, y, m
end

def area
(@b + @m * @y) * @y
end

def hyd_rad
(@b + @m * @y) * @y / (@b + 2.0 * @y * (1 + @m**2)**0.5)
end

def wet_perim
@b + 2.0 * @y * (1.0 + @m**2)**0.5
end

class << self
def area(b, y, m)
new(b, y, m).area
end

def hyd_rad(b, y, m)
  new(b, y, m).hyd_rad
end

def wet_perim(b, y, m)
  new(b, y, m).wet_perim
end

end
end

I’m sure you see the pattern there. You have your instance methods
that can take advantage of storing away the variables upon
initialization, but you also have your class methods for convenience
if area1 = Geom.new(b, y, m).area offends you. And if the repetition
there is a concern, it’s just a SMOMP away from cleanliness.

Hope that helps. Have a nice day.

Also, as a side note not entirely relevant to the topic at hand, I’m
not quite familiar with some of these variables and calculations.
Maybe it’s been too long for me, but I can’t figure out what kind of
area equation needs to have two multiplications. And I can’t figure
out what b, y, and m stand for.


#3

Maybe it’s been too long for me, but I can’t figure out what kind of
area equation needs to have two multiplications. And I can’t figure
out what b, y, and m stand for.

I am solving for the area of flow in a trapezoidal shaped ditch
(channel). b is bottom width, y is depth of flow, and m is the side
slope as m:1.

You know, I didn’t think of area1 = Geom.new(b, y, m).area

I guess that isn’t too bad.