I trying to imagine a ruby translation of the pimpl idiom.
Let me be a bit more explicit about what I'm thinking about.
I ran a unit test that failed on a syntax error in another module/class.
Looking at the error message I realized that class A used B which used C
which used D which under certain error conditions that could never occur
while testing A, used E.
This left me feeling my program was too coupled. Why did the syntax of a
module that I wasn't using block me?
In C++ I could have hidden the implementation of E behind a pimpl, and all
would have been sweet.
So thinking out loud...
-------file A.rb------------------------------------------------------
require 'FixMe'
class A
def foo
dostuff()
rescue BadThingsHappening => details
b = FixMe.new( details, x, y, z)
b.make_it_all_better
end
def bah
end
end
----------------------------------------------------------------------
If I feed this to Ruby it insists that FixMe must be defined.
So if I do....
----------------------------------------------------------------------
require 'A'
class C
def initialize
a = A.new
a.bah
end
end
----------------------------------------------------------------------
Even though I never invoked foo, as soon as I "require 'A'", I must
have FixMe initialized.
So how about....
----------------------------------------------------------------------
class A
def A.helper( b_class)
@@helper = b_class
end
def foo
dostuff()
rescue BadThingsHappening => details
b = @@helper.new( details, x, y, z)
b.make_it_all_better
end
def bah
end
end
----------------------------------------------------------------------
This way I could have
-File C.rb---------------------------------------------------------------------
require 'A'
class C
def initialize
a = A.new
a.bah
end
end
----------------------------------------------------------------------
and C can be used without FixMe being defined and another script that did use foo do something like...
-File other.rb--------------------------------------------------------
require 'FixMe'
require 'A'
A.helper( FixMe)
a = A.new
a.foo
----------------------------------------------------------------------
Or even more self contained...
----------------------------------------------------------------------
class SimpleHelper
def initialize(details)
@Details = details
end
def make_it_all_better
raise "I can't make '#{details}' better, I'm too dumb"
end
end
class A
@@helper = SimpleHelper
def A.helper( b_class)
@@helper = b_class
end
def foo
dostuff()
rescue BadThingsHappening => details
b = @@helper.new( details, x, y, z)
b.make_it_all_better
end
def bah
end
end
----------------------------------------------------------------------
But this still requires a concrete definition of a Helper, so a simpler version might be..
----------------------------------------------------------------------
class A
@@helper = nil
def A.helper( b_class)
@@helper = b_class
end
def foo
dostuff()
rescue BadThingsHappening => details
raise details unless @@helper
b = @@helper.new( details, x, y, z)
b.make_it_all_better
end
def bah
end
end
----------------------------------------------------------------------
That looks good, and has simplified my tests, but has complicated the
client code for A.
Sorry for thinking out loud, excuse me for existing.
John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand
The universe is absolutely plastered with the dashed lines exactly one
space long.