[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Ruby observer module

vc

5/23/2008 6:46:00 PM

Hi,
I am reading Design Patterns in Ruby, and was looking at the code of the
observer module. On line 184, in notify_observers, there is a loop on all
registered observers:

for i in @observer_peers.dup
i.update(*arg)
end

Why is there a "dup" on the array? Is that really necessary? Isn't this a
waste of memory? I am sure there is a really good explanation, but I don't
grasp it.

I also have another question: why does the subject (the notifying class)
need to call "changed"? Wouldn't it be sufficient to call notify_observers?
I mean, if I call notify_observers in the Subject class, doesn't that imply
has something has changed?


--
http://s2.d...
9 Answers

James Gray

5/23/2008 6:57:00 PM

0

On May 23, 2008, at 1:49 PM, S2 wrote:

> I am reading Design Patterns in Ruby, and was looking at the code of
> the
> observer module. On line 184, in notify_observers, there is a loop
> on all
> registered observers:
>
> for i in @observer_peers.dup
> i.update(*arg)
> end
>
> Why is there a "dup" on the array? Is that really necessary? Isn't
> this a
> waste of memory? I am sure there is a really good explanation, but I
> don't
> grasp it.

I'm totally guessing here, but could it be to keep the list from
changing while it iterates?

James Edward Gray II

vc

5/23/2008 7:11:00 PM

0

James Gray wrote:

> I'm totally guessing here, but could it be to keep the list from
> changing while it iterates?
>

How could that ever happen?

def notify_observers(*arg)
if defined? @observer_state and @observer_state
if defined? @observer_peers
for i in @observer_peers.dup
i.update(*arg)
end
end
@observer_state = false
end
end

@observer_peers will contain objects that implement the update method.

--
http://s2.d...

Avdi Grimm

5/23/2008 7:22:00 PM

0

On Fri, May 23, 2008 at 2:49 PM, S2 <x@y.z> wrote:
> I also have another question: why does the subject (the notifying class)
> need to call "changed"? Wouldn't it be sufficient to call notify_observers?
> I mean, if I call notify_observers in the Subject class, doesn't that imply
> has something has changed?

Consider the case:

def do_stuff
step_that_might_change_self()
another_step_that_might_change_self()
yet_another_step_that_might_change_self()
end

Any of the methods called by do_stuff MIGHT change the data, but then
again they might not. do_stuff should appear as an atomic operation
from outside the object, so we don't want to call notify_observers in
all three methods. What we really want to do is do all of the steps
and then, when they are finished, notify our observers - but only if
we've actually been changed. So we write it like this:

def do_stuff
step_that_might_change_self()
another_step_that_might_change_self()
yet_another_step_that_might_change_self()
notify_observers
end

And then it is each step's responsibility to call #changed if and only
if they actually made a change. If a change was made by one or more
steps, our observers are notified ONCE at the end.

--
Avdi

Home: http:...
Developer Blog: http:.../devblog/
Twitter: http://twitte...
Journal: http://avdi.livej...

vc

5/23/2008 7:31:00 PM

0

Avdi Grimm wrote:

> And then it is each step's responsibility to call #changed if and only
> if they actually made a change.  If a change was made by one or more
> steps, our observers are notified ONCE at the end.

Yes, in this case it makes sense, but think of this:

def do_stuff
@mint = 'blue'
notify_observers
end

Nice and clean, isn't it?
If I implement something like you sad, wouldn't it make more sense to create
a @changed variable in the Subject class, and call notify_observers only if
@changed == true instead of forcing a call to changed every time?

Well, it's perfectly fine to me how it is implemented now, it just looks a
bit ugly to me, but maybe it's just me (that call to changed does not
really add anything, and the functionality it provides is trivial (if it is
intended like you explained it)).

--
http://s2.d...

Ryan Davis

5/23/2008 7:58:00 PM

0


On May 23, 2008, at 11:49 , S2 wrote:

> for i in @observer_peers.dup
> i.update(*arg)
> end
>
> Why is there a "dup" on the array? Is that really necessary? Isn't
> this a
> waste of memory? I am sure there is a really good explanation, but I
> don't
> grasp it.

(waste of memory? one array? ... who cares?)

what if one of the members of @observer_peers' update method removes
everything from @observer_peers? How will the rest of the members get
their update? What if they needed to do stuff to properly clean up too?


vc

5/23/2008 8:05:00 PM

0

Ryan Davis wrote:

> (waste of memory? one array? ... who cares?)

It just looks like an instruction to much.

> what if one of the members of @observer_peers' update method removes
> everything from @observer_peers? How will the rest of the members get
> their update? What if they needed to do stuff to properly clean up too?

That's a really good reason. Thanks.

--
http://s2.d...

Mark Wilden

5/24/2008 4:12:00 AM

0

On May 23, 2008, at 12:34 PM, S2 wrote:

> Yes, in this case it makes sense, but think of this:
>
> def do_stuff
> @mint = 'blue'
> notify_observers
> end
>
> Nice and clean, isn't it?
> If I implement something like you sad, wouldn't it make more sense
> to create
> a @changed variable in the Subject class, and call notify_observers
> only if
> @changed == true instead of forcing a call to changed every time?

Maybe it's because there might be another event beside changed ?

///ark

Mark Wilden

5/24/2008 4:16:00 AM

0

On May 23, 2008, at 12:57 PM, Ryan Davis wrote:

> what if one of the members of @observer_peers' update method removes
> everything from @observer_peers? How will the rest of the members
> get their update? What if they needed to do stuff to properly clean
> up too?

How would an observer peer have the ability to change the list (other
than removing itself, of course)? it seems to me that the list owner
would not allow that kind of access. On the other hand, perhaps
removing itself from the list might also hose the iteration.

///ark


Robert Klemme

5/24/2008 8:47:00 AM

0

On 23.05.2008 21:30, S2 wrote:
> Avdi Grimm wrote:
>
>> And then it is each step's responsibility to call #changed if and only
>> if they actually made a change. If a change was made by one or more
>> steps, our observers are notified ONCE at the end.
>
> Yes, in this case it makes sense, but think of this:
>
> def do_stuff
> @mint = 'blue'
> notify_observers
> end
>
> Nice and clean, isn't it?
> If I implement something like you sad, wouldn't it make more sense to create
> a @changed variable in the Subject class, and call notify_observers only if
> @changed == true instead of forcing a call to changed every time?

What you describe is exactly what happens if you use #changed and
#notify_observers the way they are intended. Look into the
implementation of #changed and #notify_observers.

And for simple cases nothing stops you from doing something like this:

def force_notify
changed
notify_observers
end

> Well, it's perfectly fine to me how it is implemented now, it just looks a
> bit ugly to me, but maybe it's just me (that call to changed does not
> really add anything, and the functionality it provides is trivial (if it is
> intended like you explained it)).

What's wrong with having a method with trivial implementation? Note,
that the method has the added advantage to be overridable and changeable
- so you are a lot more flexible.

Kind regards

robert