[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Needle and Parameterized Services

Rob Lally

4/13/2005 5:08:00 PM

Hi,

I've been using Needle to try to create an iBatis like framework in Ruby. I want register parameterized blocks but when
I do this they have to take the container and service point as the first two parameters. At least I think they need to
... I'm hoping they don't, can anyone suggest a way round it?

Thanks in advance,

R.


13 Answers

Jamis Buck

4/13/2005 6:00:00 PM

0

On Apr 13, 2005, at 11:08 AM, Rob Lally wrote:

> Hi,
>
> I've been using Needle to try to create an iBatis like framework in
> Ruby. I want register parameterized blocks but when I do this they
> have to take the container and service point as the first two
> parameters. At least I think they need to ... I'm hoping they don't,
> can anyone suggest a way round it?
>

First off, I'm not familiar at all with iBatis--could you give a little
background on that? I'm also not entirely sure I understand what you're
asking, but I *think* you're saying the following:

registry.register(:my_service, :model => :multiton) do |c,p,*args|
# do something with *args, like:
args.map { |i| "sing: #{i}" }
end

And you want to be able to register a block that does NOT use the first
two parameters for "c" (the container) and "p" (the service point),
right?

Please keep in mind that even though the block accepts those first two
parameters, the service point itself is parameterized only on the
remaining values. In other words, when you go to query the "my_service"
service, you do NOT pass in the "c" and "p" arguments--Needle does that
for you. Thus:

my_service = registry.my_service("do", "re", "mi")
p my_service

Would print

["sing: do", "sing: re", "sing: mi"]

Does that make sense? Or did I miss the gist of your question?

- Jamis



Rob Lally

4/13/2005 8:19:00 PM

0

Jamis Buck wrote:

> On Apr 13, 2005, at 11:08 AM, Rob Lally wrote:
>
>> Hi,
>>
>> I've been using Needle to try to create an iBatis like framework in
>> Ruby. I want register parameterized blocks but when I do this they
>> have to take the container and service point as the first two
>> parameters. At least I think they need to ... I'm hoping they don't,
>> can anyone suggest a way round it?
>>
>
> First off, I'm not familiar at all with iBatis--could you give a little
> background on that? I'm also not entirely sure I understand what you're
> asking, but I *think* you're saying the following:

iBatis is an OR mapping tool from the Java world based on the DAO pattern. I mentioned it more for colour than because
it was useful information. How I expected anyone else to know that I'm not sure ...

> registry.register(:my_service, :model => :multiton) do |c,p,*args|
> # do something with *args, like:
> args.map { |i| "sing: #{i}" }
> end
>
> And you want to be able to register a block that does NOT use the first
> two parameters for "c" (the container) and "p" (the service point), right?
>
> Please keep in mind that even though the block accepts those first two
> parameters, the service point itself is parameterized only on the
> remaining values. In other words, when you go to query the "my_service"
> service, you do NOT pass in the "c" and "p" arguments--Needle does that
> for you. Thus:
>
> my_service = registry.my_service("do", "re", "mi")
> p my_service
>
> Would print
>
> ["sing: do", "sing: re", "sing: mi"]
>
> Does that make sense? Or did I miss the gist of your question?

For this particular framework the container and service point are not likely ever to be useful to the party writing the
blocks; it is using Needle "under the covers" rather than as a top level object. So if the client wants to write
parameterized blocks they would need to include two mystery parameters. When I say mystery parameters I only mean
because the use of Needle under the covers isn't transparent.

Perhaps some code would be clearer:

A user of the framework would write

mapr.register_statement(:select_person_by_id) do |id|
"SELECT * FROM person WHERE id = #{id}"
end

Under the covers this stores this block in a needle registry. In order to be able to call the service with a parameter
it would need to have c and p at the start of the block parameter list.

At the moment I'm wrapping this block under the cover with another block

def register_statement(name, &statement)
@registry.statements.register(name, :model => :prototype) {|c, p, *args| statement.call(*args) }
end

Which works fine but feels a bit off.

I was hoping that there would be an option looking like:

def register_statement(name, &statement)
@registry.statements.register(name, :model => :prototype, :container_agnostic => true, &statement)
end

Which would enable parameterised services that don't get the c and p parameters.

Thanks for taking the time to respond.

R.








Jamis Buck

4/13/2005 10:35:00 PM

0

On Apr 13, 2005, at 2:19 PM, Rob Lally wrote:

> A user of the framework would write
>
> mapr.register_statement(:select_person_by_id) do |id|
> "SELECT * FROM person WHERE id = #{id}"
> end
>
> Under the covers this stores this block in a needle registry. In order
> to be able to call the service with a parameter it would need to have
> c and p at the start of the block parameter list.
>
> At the moment I'm wrapping this block under the cover with another
> block
>
> def register_statement(name, &statement)
> @registry.statements.register(name, :model => :prototype) {|c,
> p, *args| statement.call(*args) }
> end
>
> Which works fine but feels a bit off.
>

Ah, I understand now. Yah, currently there is no option to prevent
those parameters, so wrapping it as you did above is about your only
option. I don't know how I feel about adding an option to "turn off"
the c/p parameters. I know DI isn't a hugely popular approach in the
Ruby world, but...anyone out there have an opinion on this matter?
Personally, I think I'd lean towards just having consumers of Needle
use adapters of one kind or another to change the interface, as you did
above. It's an honorable and tried design pattern.

What about it "feels a bit off" to you? Maybe that would help change my
opinion. :)

- Jamis



Rob Lally

4/14/2005 7:22:00 AM

0

Jamis Buck wrote:

> On Apr 13, 2005, at 2:19 PM, Rob Lally wrote:
>> At the moment I'm wrapping this block under the cover with another block
>>
>> def register_statement(name, &statement)
>> @registry.statements.register(name, :model => :prototype) {|c,
>> p, *args| statement.call(*args) }
>> end
>>
>> Which works fine but feels a bit off.
>>
>
> Ah, I understand now. Yah, currently there is no option to prevent those
> parameters, so wrapping it as you did above is about your only option. I
> don't know how I feel about adding an option to "turn off" the c/p
> parameters. I know DI isn't a hugely popular approach in the Ruby world,
> but...anyone out there have an opinion on this matter? Personally, I
> think I'd lean towards just having consumers of Needle use adapters of
> one kind or another to change the interface, as you did above. It's an
> honorable and tried design pattern.
>
> What about it "feels a bit off" to you? Maybe that would help change my
> opinion. :)

I'm not exactly sure what makes me uncomfortable about it. I think that it is the lack of symmetry; if you want 0
parameters you define 0 parameters, if you want n you define n + 2.

I think that at the moment DI isn't very popular in the Ruby world for a couple of reasons:

1) People are writing relatively small applications. DI becomes more important on larger code bases with multiple
developers; amongst other things the physical decoupling makes it easier to perform the mental decoupling needed to
concentrate on the corner of the code base you're working on. More and more people seem to be working collaboratively on
Rails based projects so I would expect DI and needle to become more important here.

2) The dynamic nature of Ruby means it isn't as hard to 'roll your own' DI solution. If Needle got some more publicity I
reckon people would use it more.

One of the things I noticed on another thread about performance of unit test was a discussion of combinatoric complexity
in unit tests. The posters solution was to spin of chunks of code into modules, a not unreasonable solution. Another
alternative would be to use DI to rid the units under test of direct dependencies and eliminate the combinatoric explosion.

Something I would like to see would be integration of Needle into Rails. I seem to recall quite a few threads on the
Rails list along the lines of 'How do I make something available to all of my controllers'? The answer normally involves
inheritance of environment.rb. If ActionController::Base had a registry associated with it or even if there was a
(heaven forfend) global rails registry it would provide a single definitive place to put these kind of services. Rails
itself could provide ActionMail, Logging or other services via this registry as well.

IMHO dependency injection is a good thing and Needle is an excellent example of a DI framework. With lots of non OO
developers coming in to Ruby via Rails it would be an excellent opportunity to spread the word about a valuable and
powerful technique. I know that Rails values convention over configuration ... but sometimes configuration is necessary.
When is it Needle provides a solid, flexible solution.

R.


Jamis Buck

4/14/2005 2:55:00 PM

0

On Apr 14, 2005, at 1:22 AM, Rob Lally wrote:

> Jamis Buck wrote:
>
>> On Apr 13, 2005, at 2:19 PM, Rob Lally wrote:
>>> At the moment I'm wrapping this block under the cover with another
>>> block
>>>
>>> def register_statement(name, &statement)
>>> @registry.statements.register(name, :model => :prototype)
>>> {|c, p, *args| statement.call(*args) }
>>> end
>>>
>>> Which works fine but feels a bit off.
>>>
>> Ah, I understand now. Yah, currently there is no option to prevent
>> those parameters, so wrapping it as you did above is about your only
>> option. I don't know how I feel about adding an option to "turn off"
>> the c/p parameters. I know DI isn't a hugely popular approach in the
>> Ruby world, but...anyone out there have an opinion on this matter?
>> Personally, I think I'd lean towards just having consumers of Needle
>> use adapters of one kind or another to change the interface, as you
>> did above. It's an honorable and tried design pattern.
>> What about it "feels a bit off" to you? Maybe that would help change
>> my opinion. :)
>
> I'm not exactly sure what makes me uncomfortable about it. I think
> that it is the lack of symmetry; if you want 0 parameters you define 0
> parameters, if you want n you define n + 2.

Well, actually, if you want 0 parameters, you can define 2 parameters,
so the symmetry is still there. It is just that you can optionally
leave the parameters out of the block if you don't need to use them.
But I understand what you are saying, and there is something to be said
about that. However, I still feel like adding an option to specify that
the c/p parameters are optional complicates the API. I'll do some
thinking about it.

> 2) The dynamic nature of Ruby means it isn't as hard to 'roll your
> own' DI solution. If Needle got some more publicity I reckon people
> would use it more.

I sure did my best to push Copland about a year ago, and Needle in the
few months after RubyConf '04. But as you said, most Ruby developers
are working on smaller projects, and so it was difficult to demonstrate
the value of DI in those situations. I know a few developers were/are
using Needle in their software, though--Christian Neukirchen is using
it in his Nukumi2 blog software, and the RPA team was using it
(although RPA seems to have become defunct). I used Needle in Net::SSH.

It would help if DI wasn't so hard to explain. :) Jim Weirich did an
excellent job in his dependency injection article of several months
ago, but I think the whole concept still leaves a lot of people
scratching (and shaking) their heads.

> Something I would like to see would be integration of Needle into
> Rails. I seem to recall quite a few threads on the Rails list along
> the lines of 'How do I make something available to all of my
> controllers'? The answer normally involves inheritance of
> environment.rb. If ActionController::Base had a registry associated
> with it or even if there was a (heaven forfend) global rails registry
> it would provide a single definitive place to put these kind of
> services. Rails itself could provide ActionMail, Logging or other
> services via this registry as well.

David and I actually discussed this possibility quite seriously a while
ago, but for several reasons Needle is not a very good fit inside Rails
itself. I know several people are using it on top of Rails, which I
think is great, but adding Needle support to Rails itself is not
necessarily adding value. A few tweaks to your environment.rb and you
can add the Needle support yourself (thanks to Ruby's ability to reopen
classes). Or, you can do like I did
(http://ruby.jamisbuck.org/rails-inj...) and work out a more
object-oriented solution, which is what I originally proposed to David.
(That link, incidentally, builds on a pre-0.9 version of Rails, so you
may need to tweak it considerably to get it to work in modern releases.
Also, the document describes how Rails now solves the problems I was
addressing).

> IMHO dependency injection is a good thing and Needle is an excellent
> example of a DI framework. With lots of non OO developers coming in to
> Ruby via Rails it would be an excellent opportunity to spread the word
> about a valuable and powerful technique. I know that Rails values
> convention over configuration ... but sometimes configuration is
> necessary. When is it Needle provides a solid, flexible solution.
>

Thank-you, Rob. I'm glad you have found Needle useful. What I think
would really help the understanding of DI in Ruby is if you could maybe
write a brief article about how, specifically, you are using DI in your
projects. I'd be happy to host that article on my blog if you'd like,
or perhaps even Chad could host it on RubyGarden.

- Jamis



pat eyler

4/14/2005 3:10:00 PM

0

On 4/14/05, Jamis Buck <jamis@37signals.com> wrote:
> Thank-you, Rob. I'm glad you have found Needle useful. What I think
> would really help the understanding of DI in Ruby is if you could maybe
> write a brief article about how, specifically, you are using DI in your
> projects. I'd be happy to host that article on my blog if you'd like,
> or perhaps even Chad could host it on RubyGarden.

Another good option might be to write it for Linux Journal. You'd get paid
for it and, after 30 days, it could be incorporated into the Needle
distribution
as documentation -- specifics are available from the LJ editors. (Not to
mention the boost in Ruby publicity everytime a magazine publishes an
article about it.)

>
> - Jamis
>
>


--
thanks,
-pate
-------------------------
We are often unable to tell people what they need to know, because
they want to know something else, and would therefore only
misunderstand what we said
- the Raven (George MacDonald, Lilith)



Rob Lally

4/14/2005 6:17:00 PM

0

Jamis Buck wrote:
>> On Apr 13, 2005, at 2:19 PM, Rob Lally wrote:
>> IMHO dependency injection is a good thing and Needle is an excellent
>> example of a DI framework. With lots of non OO developers coming in to
>> Ruby via Rails it would be an excellent opportunity to spread the word
>> about a valuable and powerful technique. I know that Rails values
>> convention over configuration ... but sometimes configuration is
>> necessary. When is it Needle provides a solid, flexible solution.
>>
>
> Thank-you, Rob. I'm glad you have found Needle useful. What I think
> would really help the understanding of DI in Ruby is if you could maybe
> write a brief article about how, specifically, you are using DI in your
> projects. I'd be happy to host that article on my blog if you'd like, or
> perhaps even Chad could host it on RubyGarden.


I will dig out my writers hat and see what I can put together. If people here think it is worthwhile I'll see if it's
worth putting up somewhere permenantly.

R.


Chad Fowler

4/15/2005 1:40:00 PM

0

On 4/14/05, Rob Lally <ruby@roblally.plus.com> wrote:
> Jamis Buck wrote:
> >> On Apr 13, 2005, at 2:19 PM, Rob Lally wrote:
> >> IMHO dependency injection is a good thing and Needle is an excellent
> >> example of a DI framework. With lots of non OO developers coming in to
> >> Ruby via Rails it would be an excellent opportunity to spread the word
> >> about a valuable and powerful technique. I know that Rails values
> >> convention over configuration ... but sometimes configuration is
> >> necessary. When is it Needle provides a solid, flexible solution.
> >>
> >
> > Thank-you, Rob. I'm glad you have found Needle useful. What I think
> > would really help the understanding of DI in Ruby is if you could maybe
> > write a brief article about how, specifically, you are using DI in your
> > projects. I'd be happy to host that article on my blog if you'd like, or
> > perhaps even Chad could host it on RubyGarden.
>
> I will dig out my writers hat and see what I can put together. If people here think it is worthwhile I'll see if it's
> worth putting up somewhere permenantly.
>
> R.
>
>

RubyGarden welcomes you. :)

--

Chad Fowler
http://chad...
http://rubyc...
http://ruby...
http://rubygems.rub... (over 100,000 gems served!)



Joel VanderWerf

4/19/2005 7:15:00 PM

0

Rob Lally wrote:
> Hi,
>
> I've been using Needle to try to create an iBatis like framework in
> Ruby. I want register parameterized blocks but when I do this they have
> to take the container and service point as the first two parameters. At
> least I think they need to ... I'm hoping they don't, can anyone suggest
> a way round it?

It's not Needle, but MinDI does have parameterized services with the
same signature for both the service definition and invocation. See
http://raa.ruby-lang.org/pro.... Example:

-----------
require 'mindi'

class SimpleContainer
extend MinDI::Container

string { "Hello, world\n" }

point_at { |x,y| [x,y] }

stuff { [string, point_at(100,200)] }
end

cont = SimpleContainer.new

p cont.stuff # ==> ["Hello, world\n", [100, 200]]
-----------

MinDI is only about 100LOC and ruby licensed, so you can hack away...


Dick Davies

4/19/2005 9:05:00 PM

0

* Joel VanderWerf <vjoel@PATH.Berkeley.EDU> [0414 20:14]:
> It's not Needle, but MinDI does have parameterized services with the
> same signature for both the service definition and invocation.

*please* tell me there is a library in the pipeline called mork :)

--
'Interesting. No, wait, the other thing - Tedious.'
-- Bender
Rasputin :: Jack of All Trades - Master of Nuns