By value - by reference, circular reference

Hi,

i have a circular reference between two classes. Initialize of one needs
the other. Small example:

A.new b_instance
B.new a_instance

So I thought I could do:

a = A.new nil
b = B.new a
a = A.new B

The attached valuedemo.rb contains a executable example of how i tried
to do and shows the problem. It also showes where i get confused about
call by value or call by reference.

As I understand param in the example is not equal but the same to
@param. So param and @param are references to the same object, rather
identical copies of an object. So if the value changes in one place, it
should change every where.
It doesn’t, so its clear my understanding is wrong.

I would be happy about general advice on solving circular references
too.

On Sat, Dec 15, 2012 at 6:15 PM, Michael S. [email protected]
wrote:

a = A.new nil
should change every where.
No. It’s: if the object changes the change is visible in all
locations which reference it. There is no call by reference in Ruby.

It doesn’t, so its clear my understanding is wrong.

I would be happy about general advice on solving circular references
too.

Attachments:
http://www.ruby-forum.com/attachment/7971/valuedemo.rb

You initialize instance of A with nil. The object reference contained
in “param” is copied so @param still references nil when you update
“param” to point to 2.

Kind regards

robert

Allright, thanks robert. Its clear now how this attempt failed.

There was a working solution, where all references where class variables
of one big class. The constructors of all classes where unparameterized.
If a resource was needed, it was accessed through the big class. I
didn’t like this solution, because the classes where tightly coupled to
the big class. But it was a good thing, that exchanging one resource was
trivial.

Before that the circularly intertwined classes called each others
initialize in their constructors, where self had an adress already.
Worked. In my opinion it was the ultimate form of cuppling.

Now i have rather long parameterlists. I don’t like that either.

Another solution would be to use setter methods. But that would mean
writing a few lines of code per initialisation extra.

The latter three solution also leave the question of globally exchanging
a resource open.

The circular reference must go. But this topic is interesting. What are
the established ways to treat circular references, long parameter lists
and globally used (and potentially variable) objects?

On Sat, Dec 15, 2012 at 12:35 PM, Michael S. [email protected]
wrote:

initialize in their constructors, where self had an adress already.
The circular reference must go. But this topic is interesting. What are
the established ways to treat circular references, long parameter lists
and globally used (and potentially variable) objects?


Posted via http://www.ruby-forum.com/.

if you object to long parameter lists, consider passing a hash.
This may still have a lot of code on the calling side, but it
is at least rather more understandable vs. just passing
in values.

a = A.new({
:option1 => ‘Something’,
:option2 => ‘or’
:option3 => ‘other’
})

then the method definition is

def initialize(options = {})

  # ... code

end

This form is used all over the place, all the time.

On Sun, Dec 16, 2012 at 3:22 AM, tamouse mailing lists
[email protected] wrote:

if you object to long parameter lists, consider passing a hash.
This may still have a lot of code on the calling side, but it
is at least rather more understandable vs. just passing
in values.

a = A.new({
:option1 => ‘Something’,
:option2 => ‘or’
:option3 => ‘other’
})

Curly brackets are superfluous here. And you can use the new Syntax in
1.9:

a = A.new(
option1: ‘Something’,
option2: ‘or’,
option3: ‘other’
)

then the method definition is

def initialize(options = {})

  # ... code

end

This form is used all over the place, all the time.

I don’t like that too much because what seems to be a good idea in the
beginning can come back later to haunt you. Stuffing everything in a
Hash just to avoid longer parameter lists is worthless without
documenting which keys the class expects. But if you write the
documentation you can as well also use proper arguments. This is
really only a good solution if a lot of arguments are optional. If
not, I’d prefer a proper argument list because the caller must provide
them anyway.

Kind regards

robert

On Sat, Dec 15, 2012 at 7:35 PM, Michael S. [email protected]
wrote:

Allright, thanks robert. Its clear now how this attempt failed.

Good!

There was a working solution, where all references where class variables
of one big class. The constructors of all classes where unparameterized.
If a resource was needed, it was accessed through the big class. I
didn’t like this solution, because the classes where tightly coupled to
the big class. But it was a good thing, that exchanging one resource was
trivial.

That sounds like the god object anti pattern. And it’s made worse by
the fact that the god object was not passed around but made accessible
like a global variable (the class instance in this case). That is
awful for testing.

Before that the circularly intertwined classes called each others
initialize in their constructors, where self had an adress already.
Worked. In my opinion it was the ultimate form of cuppling.

It’s difficult to properly evaluate that without more knowledge about
your use case. It does sound though that functionality might be
improperly distributed across classes if so many of them need to know
each other.

Now i have rather long parameterlists. I don’t like that either.

You can avoid that by grouping arguments into a class of its own. Of
course, that grouping must make sense. Often Struct can be used to
create such containers in a single like of code.

Another solution would be to use setter methods. But that would mean
writing a few lines of code per initialisation extra.

Or use Struct to create classes with a number of properties. You can
even add methods:

Window = Struct.new :width, :height, :pos_x, :pos_y do
def paint(screen)
screen.go_to pos_x, pos_y
screen.paint …
end
end

The latter three solution also leave the question of globally exchanging
a resource open.

The circular reference must go. But this topic is interesting. What are
the established ways to treat circular references, long parameter lists
and globally used (and potentially variable) objects?

There is definitively not a one size fits all solution to get rid of
all three together. Even for individual items on your worklist
(circular refs, long parameter lists, global variables) there might be
multiple solutions.

As long as we do not know more about the nature of the application we
cannot really come up with good suggestions, I am afraid.

Kind regards

robert

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs