A Question Of Coupling

T

Trans

I have a choice to make about a class interface. This is a very very
simplified "foo" demo of that choice.

#1

class Foo
def initialize(bar)
@bar = bar
end

def okay?
bar.okay?
end
end

bar = Bar.new
Foo.new(bar)

Or #2

class Foo
def initialize( opts )
@okay = opts[:eek:kay]
end

def okay?
@okay
end
end

bar = Bar.new
Foo.new:)okay => bar.okay?)

Now, my inner OOP Angel is telling me to take door #2 in order to
avoid strong coupling between Bar and Foo. But, my Red Ruby Devil is
saying "Duck typing, you fool. It doesn't matter anymore!"

Is he right? Has Ruby completely changed the game? If so, why aren't
more Rubyists using OStruct-esque option passing?

T.
 
M

MenTaLguY

Now, my inner OOP Angel is telling me to take door #2 in order to
avoid strong coupling between Bar and Foo. But, my Red Ruby Devil is
saying "Duck typing, you fool. It doesn't matter anymore!"

Is he right? Has Ruby completely changed the game?

I don't see why that would be true in this case. In #1, Foo's
implementation depends on Bar's public interface, whereas in #2,
there is no coupling at all between them.

Put another way: duck typing is still, in a sense, typing. In #1,
you aren't constrained to pass in a Bar, specifically, but you must
still pass in an object which satisfies the same un-named object
protocol as instances of Bar do.

(Perhaps we should call it "ninja typing"?)
If so, why aren't more Rubyists using OStruct-esque option passing?

Ruby doesn't make it as frictionless as it could be, particularly if
you want default values for your options.

-mental
 
M

MenTaLguY

That said, I'm not sure that the issue of coupling necessarily settles
the question. The more actual behavior (rather than POD) embodied by Bar,
the more #1 could potentially be desirable as an embodiment of the
Strategy Pattern.

-mental
 
J

Jason Roelofs

My issue with #2 is that the return value of bar.okay? might change,
but with this implementation Foo#okay? won't ever change.

Jason
 
T

Trans

My issue with #2 is that the return value of bar.okay? might change,
but with this implementation Foo#okay? won't ever change.

That's a good point. I guess that crystalizes the coupling.

Coupled:

class Foo
def initialize(bar)
@bar = bar
end

Decoupled:

class Foo
def initialize(bar)
@bar = bar.dup
end

T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,279
Latest member
LaRoseDermaBottle

Latest Threads

Top