# How to model something

**URL:** <https://www.ruby-forum.com/t/how-to-model-something/138548>\
**Category:** Ruby\
**Created:** [May 24, 2008, 1:10pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548 "2008-05-24T13:10:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 24, 2008, 1:10pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/1 "2008-05-24T13:10:49Z")

</div>

Hi,  
my programm needs to store persons. They have a weight and a gender. You  
are only allowed to ask males for their weight, females will throw  
dishes/exceptions. There _is_ a method to change someones gender.

I could have ‘if gender’ in every accessor or use the state pattern. But  
that has no state, so I’m confused. I would have to access the variable  
in the wrapper class.

The programm can also shoot people into space, in which case the  
implementation of weight changes but the same restrictions apply.  
The proxy pattern will help here, probably by having weight first call  
delegate.weight, and if that isn’t NoMethodException multiplying with  
gravity.

Any advice or implementations of similar problems I could look at?

(and in reality people are TV series with 6 genders and 5 other  
attributes, and space is just but a remote place to store things)

---

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 24, 2008, 2:54pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/2 "2008-05-24T14:54:37Z")

</div>

-------- Original-Nachricht --------

> Datum: Sat, 24 May 2008 20:09:51 +0900  
> Von: Tobias W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> An: removed\_email\_address@domain.invalid  
> Betreff: How to model something

> implementation of weight changes but the same restrictions apply.  
> Tobias W.  
> Hi Tobias,

I’d use Struct …

Best regards,

Axel

* * *

Human=Struct.new(:name,:gender,:weight,:position)

def check\_and\_multiply(arg,default\_value,factor)

# return factor, if arg==default\_value, else return 1

if arg==default\_value  
return factor  
else  
return 1  
end  
end  
class Human  
def ask\_for\_weight(weight\_loss\_factor=0.5)  
if self.gender==‘female’  
return “Don’t ask me this!”  
else  
return  
self.weight\*check\_and\_multiply(self.position,‘space’,weight\_loss\_factor)  
end  
end  
def change\_sex  
temp=self.dup  
if self.gender==‘male’  
temp.gender=‘female’  
end  
if self.gender==‘female’  
temp.gender=‘male’  
end  
return temp  
end  
def change\_position  
temp=self.dup  
if self.position==‘earth’  
temp.gender=‘space’  
end  
if self.gender==‘space’  
temp.gender=‘earth’  
end  
return temp  
end

end

man1=Human.new(‘John’,‘male’,75.0,‘space’)  
man2=Human.new(‘James’,‘male’,75.0,‘earth’)  
woman=Human.new(‘Mary’,‘female’,55.0)  
p woman.ask\_for\_weight  
p man1.ask\_for\_weight  
p man2.ask\_for\_weight  
p man2.change\_sex.name

---

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 25, 2008, 3:43pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/3 "2008-05-25T15:43:09Z")

</div>

> Hi,  
> my programm needs to store persons. They have a weight and a gender.  
> You  
> are only allowed to ask males for their weight, females will throw  
> dishes/exceptions. There _is_ a method to change someones gender.
> 
> I could have ‘if gender’ in every accessor

That seems like the simplest approach. The person object is the one  
who’s creating this restriction - weight shouldn’t know about gender  
and gender shouldn’t know about weight. Wouldn’t that only affect one  
accessor - weight?

///ark

---

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 24, 2008, 3:00pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/4 "2008-05-24T15:00:29Z")

</div>

Some random thougths…

On 24.05.2008 13:08, Tobias W. wrote:

> my programm needs to store persons. They have a weight and a gender. You  
> are only allowed to ask males for their weight, females will throw  
> dishes/exceptions. There _is_ a method to change someones gender.
> 
> I could have ‘if gender’ in every accessor or use the state pattern. But  
> that has no state, so I’m confused. I would have to access the variable  
> in the wrapper class.

I am not sure what you mean here. Here’s one way to do it:

class Person  
GENDERS = {  
:male =\> Class.new do  
def gender; :male; end  
def weight\_check; end  
end.new,  
:female =\> Class.new do  
def gender; :female; end  
def weight\_check; raise “Go away!” end  
end.new,  
}.freeze

def initialize(gender)  
self.gender = gender  
end

def gender=(g)  
@gender = GENDERS[g] or raise “Illegal gender #{g.inspect}”  
end

def gender; @gender.gender; end

def weight=(w)  
raise IllegalArgumentException, “negative” if w \< 0  
@weight = w  
end

def weight; @gender.weight\_check; @weight; end  
end

> The programm can also shoot people into space, in which case the  
> implementation of weight changes but the same restrictions apply.  
> The proxy pattern will help here, probably by having weight first call  
> delegate.weight, and if that isn’t NoMethodException multiplying with  
> gravity.

Well, in that case #weight isn’t just a simple accessor but it needs an  
argument (gravity). You probably want to have an attribute “mass” which  
stores the proper value.

> Any advice or implementations of similar problems I could look at?
> 
> (and in reality people are TV series with 6 genders and 5 other  
> attributes, and space is just but a remote place to store things)

What are the other four genders? :-))

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 25, 2008, 4:20pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/5 "2008-05-25T16:20:39Z")

</div>

In article [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
Mark W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> [Note: parts of this message were removed to make it a legal post.]

?

> > I could have ‘if gender’ in every accessor
> 
> That seems like the simplest approach. The person object is the one  
> who’s creating this restriction - weight shouldn’t know about gender  
> and gender shouldn’t know about weight. Wouldn’t that only affect one  
> accessor - weight?

In the example, yes. In reality it’s 3 attributes and writing is  
forbidden as well. I implemented it using one class and an Integer for  
the genders and it got pretty messy as (storage) space needs to  
manufacture persons and therefore write female’s weight where it  
normally wouldn’t be allowed.

I worked around that using set\_instance\_variable but felt awful.

So I rewrote everything using the state pattern, but with a Struct  
containing the attributes being passed around between state instances.  
Even uglier code.

I hate Java, but its protected package access would help with this.

---

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 25, 2008, 4:57pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/6 "2008-05-25T16:57:45Z")

</div>

On May 25, 2008, at 7:19 AM, Tobias W. wrote:

> In article [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
> Mark W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > [Note: parts of this message were removed to make it a legal post.]
> 
> ?

Beats me!

> manufacture persons and therefore write female’s weight where it  
> normally wouldn’t be allowed.
> 
> I worked around that using set\_instance\_variable but felt awful.
> 
> So I rewrote everything using the state pattern, but with a Struct  
> containing the attributes being passed around between state instances.  
> Even uglier code.
> 
> I hate Java, but its protected package access would help with this.

To my mind, you’ve got a “smell” here that’s caused by wanting to use  
inheritance instead of composition (the State pattern mimics  
inheritance, of course). You want a person to be-a gender, not have-a  
gender. This is implemented via State by having-a gender-weight  
gatekeeper. This is motivated by wanting to localize knowledge of the  
relationship between gender and weight, which is a good goal. However,  
it’s causing you to need to use backdoors like set\_instance\_variable  
or Java’s protected package access. To me, that indicates that the  
object model may be wrong.

Even though gender conditions access to weight, that doesn’t mean that  
gender has to know about weight (which it does in your  
implementation). Is gender a behavior (or state), or is it an  
attribute? I think it’s the latter. If you have the person object  
mediate access to one of its attributes based on another of its  
attributes, you put the responsibility where it truly lies.

But this is me just thinking out loud. It’s your model and you know it  
better than I do. I think I would give the ‘if gender’ approach a shot  
before resorting to State, especially if the latter forces you to  
violate encapsulation. I’m not a big fan of State (or Mediator, for  
that matter) when there are simpler, more direct, more obvious  
approaches. But that’s just my armchair perspective. Good luck! 🙂

///ark

---

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 27, 2008, 1:01pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/7 "2008-05-27T13:01:02Z")

</div>

In article [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
Mark W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> attribute? I think it’s the latter. If you have the person object  
> mediate access to one of its attributes based on another of its  
> attributes, you put the responsibility where it truly lies.

I now distributed the possible states along two dimensions and represent  
one by the persons being observed by two different storage models, one  
offline and one in space.

The observers know a bit about the gender dimension and don’t ask  
females their weight.

Of course I left the checks in Person, nevertheless. As the class has to  
do much less now it looks clean despite them.

---

<div class="post-metadata">

**Author:** ![polarapfel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/958977/32.png) [@polarapfel](https://www.ruby-forum.com/u/polarapfel)\
**Post date:** [May 27, 2008, 4:25pm UTC](https://www.ruby-forum.com/t/how-to-model-something/138548/8 "2008-05-27T16:25:43Z")

</div>

On May 27, 2008, at 3:59 AM, Tobias W. wrote:

> do much less now it looks clean despite them.  
> Sounds interesting, but I’m not quite able to visualize it. If you’d  
> care to, it would be great to see some pared-down code illustrating  
> the method you adopted.

///ark
