# Design question: class methods verses initialize

**URL:** <https://www.ruby-forum.com/t/design-question-class-methods-verses-initialize/158372>\
**Category:** Ruby\
**Created:** [January 22, 2009, 4:42pm UTC](https://www.ruby-forum.com/t/design-question-class-methods-verses-initialize/158372 "2009-01-22T16:42:19Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![leveille](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/a88e57/32.png) [@leveille](https://www.ruby-forum.com/u/leveille)\
**Post date:** [January 22, 2009, 4:42pm UTC](https://www.ruby-forum.com/t/design-question-class-methods-verses-initialize/158372/1 "2009-01-22T16:42:19Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![leveille](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/a88e57/32.png) [@leveille](https://www.ruby-forum.com/u/leveille)\
**Post date:** [January 22, 2009, 10:43pm UTC](https://www.ruby-forum.com/t/design-question-class-methods-verses-initialize/158372/2 "2009-01-22T22:43:45Z")

</div>

On Jan 22, 9:40 am, Jason L. [removed\_email\_address@domain.invalid](mailto: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://  
[Extract Class](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.

---

<div class="post-metadata">

**Author:** ![leveille](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/a88e57/32.png) [@leveille](https://www.ruby-forum.com/u/leveille)\
**Post date:** [January 22, 2009, 11:01pm UTC](https://www.ruby-forum.com/t/design-question-class-methods-verses-initialize/158372/3 "2009-01-22T23:01:16Z")

</div>

> 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.
