[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

[ANN] Copland to Needle article on RubyGarden

Chad Fowler

11/12/2004 12:45:00 PM

For those not subscribed to RubyGarden's rss feed[1], Jamis Buck has
written a new feature piece discussing his journey from
dependency-injection-novice to two-time-IoC-frameworker. He also
discusses the (unusual) decision to start over on a framework that is
less than a year old and demonstrates the differences between these
two frameworks (Copland and Needle). Big thanks go to Jamis for his
fascinating contribution.

The article is available on RubyGarden's front page or at:
http://rubygarden.org/index.cgi/Libraries/copland-to-n...

Request: If you'd like to write an article or tutorial or conduct an
interview to be published on RubyGarden.org, please send me an email
directly. I'm working to establish a rhythm of new content releases,
so if you're interested in contributing I would love to hear from you.

Thanks,
Chad Fowler

[1] http://rubygarden.org/index.cgi...


34 Answers

ptkwt

11/13/2004 4:32:00 AM

0

In article <a2347a04041112044531ad44b1@mail.gmail.com>,
Chad Fowler <chadfowler@gmail.com> wrote:
>For those not subscribed to RubyGarden's rss feed[1], ...
>
>[1] http://rubygarden.org/index.cgi...

I've been meaning to get 'into' this RSS thing for a while now, but
haven't thought too seriously about it until the last couple of weeks.

So for those of us who are only just now figuring out that there's a
party going on out there (which has apparently been going on for quite a
while now - so I guess I'm fashionably late :), how does one get in?
What is the secret handshake? I know that one needs a thingy called an
aggregator. This sounds a bit like a combination of a news reader and an
email client. What are the recommended aggregators (esp. for Linux and OS X)?
Why is it that web pages will have an RSS link which only brings up a bunch
of XML in your browser when clicked? Do some browsers double as aggregators
and thus allow you to subscribe by clicking on the 'RSS' link? Do these
'aggregations' get emailed to you or do you start up a tool that goes and
looks for them? What if you're wanting to get these RSS feeds on multiple
machines in different locations?


....I feel so out of it.

Phil

Francis Hwang

11/13/2004 5:09:00 AM

0

On Nov 12, 2004, at 11:53 PM, Phil Tomson wrote:

> I've been meaning to get 'into' this RSS thing for a while now, but
> haven't thought too seriously about it until the last couple of weeks.
>
> So for those of us who are only just now figuring out that there's a
> party going on out there (which has apparently been going on for quite
> a
> while now - so I guess I'm fashionably late :), how does one get in?

Start by getting yourself an aggregator. There are tons of free apps
around, you might want to pick one from the list at
http://blogspace.com/r... or just Google around. I'm a Mac head,
and my aggregator of choice is NetNewsWire Lite.

Alternately, you can setup an account on a web-based aggregation
service, like http://blog... . Same thing, only on a web site.

Use the various RSS URIs ( like
http://rubygarden.org/index.cgi... ) to subscribe to a few
starter feeds. You could start with the list at
http://rubygarden.org/rub... , though that misses quite a lot,
too. You'll find yourself reading entries that refer to other sites,
then subscribing to those new sites' RSS feeds. Typically my
subscription list slowly grows, and then from time to time I get
disgusted with my info bingeing and I try to pare down the subscription
list. (I have the same problem with magazines.)

> Why is it that web pages will have an RSS link which only brings up a
> bunch
> of XML in your browser when clicked?

What I do with those (using Safari on Mac) is right-click those links,
select "Copy Link to Clipboard", and then switch to NNW and subscribe
to that feed. Yeah, you're not really meant to read it in a browser,
though some browsers make it easier to scan through XML files than
others.

> Do some browsers double as aggregators
> and thus allow you to subscribe by clicking on the 'RSS' link?

Don't know of any yet, but I believe that browser from both Apple and
Microsoft will have more RSS integration in their next major versions.

> Do these
> 'aggregations' get emailed to you or do you start up a tool that goes
> and
> looks for them?

Usually you start up the tool. You can get them emailed to you, but
that usually gives you less control over your time. Besides ruby-talk,
I'm not actively involved in a lot of email lists. I prefer blogish
conversations more, because I get to make a harder separation between
personal messages (email) and group messages (blogs). When I'm trying
to focus, I shut down my aggregator and only have the email running in
the background.

> What if you're wanting to get these RSS feeds on multiple
> machines in different locations?

Then a web-based service, like bloglines, is probably a better match
for you.

One cool thing is that RSS has all sorts of bizarre uses besides just
content from a single author. PubSub Concepts, for example, is a
company that has lightning-fast, free searching of millions of data
sources, and you can make URIs that represent feeds for strings you're
looking for. For example, this URI gives me every time it finds the
string "Francis Hwang", usually within hours of the content being
posted:

http://rss.pubsub.com/e7/93/819df23244dbc3a86c3f...

Sw33t.

F.



Curt Hibbs

11/13/2004 6:22:00 AM

0

Francis Hwang wrote:
>
> One cool thing is that RSS has all sorts of bizarre uses besides just
> content from a single author. PubSub Concepts, for example, is a
> company that has lightning-fast, free searching of millions of data
> sources, and you can make URIs that represent feeds for strings you're
> looking for. For example, this URI gives me every time it finds the
> string "Francis Hwang", usually within hours of the content being
> posted:
>
> http://rss.pubsub.com/e7/93/819df23244dbc3a86c3f...

I've been a longtime RSS user and have used many different readers over the
years. But I was unaware of PubSub. It looks like a fantastic resource --
thanks!

Also, linked off of the PubSub home page is an RSS client called Gush that I
also had not hear of. It has a very interesting mix of features and looks
very promising. I'm downloading it right now and it may replace my current
reader. So, thanks again!

Curt

PS
For those that want to check it out, here is the home page for Gush:

http://www.2en...

Be sure to read the "About Us" page... these guys have a great sense of
humor.



Curt Hibbs

11/13/2004 7:07:00 AM

0

Curt Hibbs rote:
>
> Francis Hwang wrote:
> >
> > One cool thing is that RSS has all sorts of bizarre uses besides just
> > content from a single author. PubSub Concepts, for example, is a
> > company that has lightning-fast, free searching of millions of data
> > sources, and you can make URIs that represent feeds for strings you're
> > looking for. For example, this URI gives me every time it finds the
> > string "Francis Hwang", usually within hours of the content being
> > posted:
> >
> > http://rss.pubsub.com/e7/93/819df23244dbc3a86c3f...
>
> I've been a longtime RSS user and have used many different
> readers over the
> years. But I was unaware of PubSub. It looks like a fantastic resource --
> thanks!
>
> Also, linked off of the PubSub home page is an RSS client called
> Gush that I
> also had not hear of. It has a very interesting mix of features and looks
> very promising. I'm downloading it right now and it may replace my current
> reader. So, thanks again!
>
> Curt
>
> PS
> For those that want to check it out, here is the home page for Gush:
>
> http://www.2en...
>
> Be sure to read the "About Us" page... these guys have a great sense of
> humor.

Well... I didn't really like Gush all that much, so I just uninstalled it.
My favorite reader for Windows is still RSS Bandit
(http://www.rssb...).

Curt



Francis Hwang

11/13/2004 7:15:00 AM

0


On Nov 13, 2004, at 2:06 AM, Curt Hibbs wrote:
>
> Well... I didn't really like Gush all that much, so I just uninstalled
> it.
> My favorite reader for Windows is still RSS Bandit
> (http://www.rssb...).
>
> Curt

I tried out Gush (for OS X, I think it's mostly the same thing) and
didn't like it either. Its polling model is quite interesting, though:
It opens a Jabber connection to the PubSub server so it receives
updates from PubSub instead of asking for them periodically. Bob Wyman
(PubSub CTO, also I know him since he sits on the board of the
non-profit I work at) writes about this issue quite a lot on his own
blog. POP clients get updates every few minutes, and we should be able
to get the same update rate with feeds like RSS and Atom.

F.



Sam Roberts

11/13/2004 4:57:00 PM

0

Quoteing sera@fhwang.net, on Sat, Nov 13, 2004 at 04:14:37PM +0900:
>
> On Nov 13, 2004, at 2:06 AM, Curt Hibbs wrote:
> >
> >Well... I didn't really like Gush all that much, so I just uninstalled
> >it.
> >My favorite reader for Windows is still RSS Bandit
> >(http://www.rssb...).
> >
> >Curt
>
> I tried out Gush (for OS X, I think it's mostly the same thing) and
> didn't like it either. Its polling model is quite interesting, though:
> It opens a Jabber connection to the PubSub server so it receives
> updates from PubSub instead of asking for them periodically. Bob Wyman
> (PubSub CTO, also I know him since he sits on the board of the
> non-profit I work at) writes about this issue quite a lot on his own
> blog. POP clients get updates every few minutes, and we should be able
> to get the same update rate with feeds like RSS and Atom.

Yeah, but pop clients do it by polling. Theres not difference between
that and polling for RSS with http.

Sam



Francis Hwang

11/13/2004 6:56:00 PM

0


On Nov 13, 2004, at 11:57 AM, Sam Roberts wrote:

> Quoteing sera@fhwang.net, on Sat, Nov 13, 2004 at 04:14:37PM +0900:
>>
>> I tried out Gush (for OS X, I think it's mostly the same thing) and
>> didn't like it either. Its polling model is quite interesting, though:
>> It opens a Jabber connection to the PubSub server so it receives
>> updates from PubSub instead of asking for them periodically. Bob Wyman
>> (PubSub CTO, also I know him since he sits on the board of the
>> non-profit I work at) writes about this issue quite a lot on his own
>> blog. POP clients get updates every few minutes, and we should be able
>> to get the same update rate with feeds like RSS and Atom.
>
> Yeah, but pop clients do it by polling. Theres not difference between
> that and polling for RSS with http.
>

There is. If you've downloaded 30 items from an RSS feed, and then the
feed gets updated with item 31, the basic HTTP get will download all
the items and leave it up to the client to sort out what's new or not.
POP doesn't work this way: If you've downloaded 2000 emails off of your
mail server, then your mail server receives email 2001, when you check
your email again you won't download all 2001 emails just to get the
last one.

RFC3229 ("Delta Encoding in HTTP") describes a way to solve this,
though nobody's implemented it for RSS or Atom. Here's a blog entry
that describes the details at a finer grain of detail than I can
manage:

http://bobwyman.pubsub.com/main/2004/09/using_rfc3...

Of course, for many feed consumers this is pretty far-out, most of us
are still getting to work with conditional GET.

F.



Joel VanderWerf

11/13/2004 10:19:00 PM

0

Chad Fowler wrote:
> For those not subscribed to RubyGarden's rss feed[1], Jamis Buck has
> written a new feature piece discussing his journey from
> dependency-injection-novice to two-time-IoC-frameworker. He also
> discusses the (unusual) decision to start over on a framework that is
> less than a year old and demonstrates the differences between these
> two frameworks (Copland and Needle). Big thanks go to Jamis for his
> fascinating contribution.
>
> The article is available on RubyGarden's front page or at:
> http://rubygarden.org/index.cgi/Libraries/copland-to-n...
>
> Request: If you'd like to write an article or tutorial or conduct an
> interview to be published on RubyGarden.org, please send me an email
> directly. I'm working to establish a rhythm of new content releases,
> so if you're interested in contributing I would love to hear from you.
>
> Thanks,
> Chad Fowler
>
> [1] http://rubygarden.org/index.cgi...

Jamis Buck's and Jim Weirich's articles are great. I could never get
through the Java-oriented discussion of this subject, and now that the
subject is presented for rubyists a dim bulb is finally going on in my
head.

What really helps me think about this is to reduce it to some simple,
standard Ruby idioms, which don't provide as many features as Needle,
but are close enough to code that I've actually written to make it all
seem meaningful.

Let's take Jim's example[1], which is clear, rubified, and explicit
about DI constructs, and translate it into some concrete,
mundane ruby code without those constructs. Here's the original:

def create_application
container = DI::Container.new
container.register(:logfilename) { "logfile.log" }
container.register(:db_user) { "jim" }
container.register(:db_password) { "secret" }
container.register(:dbi_string) { "DBI:Pg:example_data" }

container.register(:app) { |c|
app = WebApp.new(c.quotes, c.authenticator, c.database)
app.logger = c.logger
app.set_error_handler c.error_handler
app
}

container.register(:quotes) { |c|
StockQuotes.new(c.error_handler, c.logger)
}

container.register(:authenticator) { |c|
Authenticator.new(c.database, c.logger, c.error_handler)
}

container.register(:database) { |c|
DBI.connect(c.dbi_string, c.db_user, c.db_password)
}

container.register(:logger) { |c| Logger.new(c.logfilename) }
container.register(:error_handler) { |c|
errh = ErrorHandler.new
errh.logger = c.logger
errh
}
end

And here's a rewrite that functions in about the same way, but without
being explicit about containers and services.

class Application
def logfilename
@logfilename ||= "logfile.log"
end

def db_user
@db_user ||= "jim"
end

def db_password
@db_password ||= "secret"
end

def dbi_string
@dbi_string ||= "DBI:Pg:example_data"
end

def app
@app ||= WebApp.new(quotes, authenticator, database)
end

def quotes
@quotes ||= StockQuotes.new(error_handler, logger)
end

def authenticator
@authenticator ||=
Authenticator.new(database, logger, error_handler)
end

def database
@database ||= DBI.connect(dbi_string, db_user, db_password)
end

def logger
@logger ||= Logger.new(logfilename)
end

def error_handler
@errh ||= (
ErrorHandler.new
@errh.logger = logger
@errh
)
end
end

def create_application
Application.new
end

So we're using the Application class itself as the container, and
we're using the instance methods of this class as the service points.
The methods return the services, and also store them in instance
variables. A service is registered using "def". Instead of using the
block parameter to pass the container to the service definitions, you
just use self. The familiar ||= idiom provides the singleton service
model.

It's quick and dirty, and it obscures the conceptual structure, but if
you're familiar with ruby, you can see immediately what is going on.
You've probably even written code a little like this. Why would you
want to "upgrade" your code to a more explicit form of DI? There are
several disadvantages to this implicit DI style, aside from the
implicitness itself:

- It doesn't help much with things like interceptors, although you
could bring in your favorite AOP library.

- It mixes your service namespace with the namespace inherited from
Object and Kernel: maybe you want a service called "dup" or "puts",
but then you cannot call the Object and Kernel implementation of
these methods from within methods of the Application class.

- Reflection must be done using standard ruby reflection on classes,
so you have to, for example, filter out methods that are not really
services.

OTOH, you can use class inheritance and module inclusion to build
trees of container definitions in a very natural and familiar way,
emulating some of the functionality of Needle:

module LoggingServices
def logger; ...; end
end

module GUIServices
end

module DatabaseServices
end

class MyServiceContainer
include LoggingServices
include GUIServices
include DatabaseServices

def app
MyApp.new(logger, gui, database)
end
end

The other service models besides the singleton model are also easy to
implement with quick and dirty ruby code:

- Threaded:

def per_thread_logger
@per_thread_logger ||= {}
@per_thread_logger[Thread.current] ||= Logger.new
end

- Prototype:

def gui_button
MyButtonClass.new
end

- Deferred (ok, this one gets a little messy, and the details should
be abstracted away by some fancy metaprogramming):

def big_resource
@big_resource || big_resource_proxy
end

def big_resource_proxy
@big_resource_proxy ||= (
proxy = [proc {|br| @big_resource = br}]
def proxy.method_missing(*args, &block)
big_resource = BigResource.new
at(0).call(big_resource)
big_resource.send(*args, &block)
end
proxy
)
end
private :big_resource_proxy

There are other service models that are very easy to construct with
methods, but I'm not aware of an equivalent construct in Needle:

def printer(kind)
@printers ||= {}
@printers[kind] = Printer.new(kind)
end

def printer_for_code_files
@printer_for_code_files ||= printer(:monochrome)
end

def printer_for_images
@printer_for_images ||= printer(:color)
end

It might be possible to do the above in Needle using Pipelines.[2]

Namespaces, if I understand the Needle docs correctly, work something
like this:

class PictureApp
class ColorNamespace
def red; PrimaryColor(:red); end
def green; PrimaryColor(:green); end
def yellow; @yellow ||= red+green; end
end

def colors
@colors ||= ColorNamespace.new
end

def picture
@picture ||= Picture.new(:background => colors.yellow)
end
end

Alternately, if you want color instances to shared by all PictureApps,
you might want to define the colors service like this:

def colors
@@colors ||= ColorNamespace.new
end

I hope there aren't too many inaccuracies in the above, and that this
helps other folks move from older ruby idioms to the new idioms
that Needle gives us.

--

[1]
http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionI...

[2] Anybody know? Or are parameterized services a misuse of the DI
pattern?


Jamis Buck

11/13/2004 10:55:00 PM

0

Joel VanderWerf wrote:

> Jamis Buck's and Jim Weirich's articles are great. I could never get
> through the Java-oriented discussion of this subject, and now that the
> subject is presented for rubyists a dim bulb is finally going on in my
> head.

Yay! :)

>
> What really helps me think about this is to reduce it to some simple,
> standard Ruby idioms, which don't provide as many features as Needle,
> but are close enough to code that I've actually written to make it all
> seem meaningful.

Excellent approach, Joel. You've hit the nail right on the head. DI is
nothing new--most of us have been doing something at least similar to it
for a long time. It's like any of the design patterns--it's not that
they are new, so much as they've been given a name so that they can be
communicated better.

As far as the DI frameworks are concerned (like Needle and Copland),
they don't let you do anything you couldn't before. They just make it so
that you don't have to reimplement a DI framework yourself for every
project you create. Plus, they are tested and stable, so you can focus
on your application logic instead of your own custom DI infrastructure.

> There are other service models that are very easy to construct with
> methods, but I'm not aware of an equivalent construct in Needle:
>
> def printer(kind)
> @printers ||= {}
> @printers[kind] = Printer.new(kind)
> end
>
> def printer_for_code_files
> @printer_for_code_files ||= printer(:monochrome)
> end
>
> def printer_for_images
> @printer_for_images ||= printer(:color)
> end
>
> It might be possible to do the above in Needle using Pipelines.[2]

Hmm. I wouldn't call this a service model so much as a factory service.
In fact, I have a new favorite way of doing this kind of thing, as of
this morning. To complicate things a bit, suppose that the Printer class
needs to be dependency injected (with a logger instance, for example),
and the following approach really shines:

reg.define do |b|
b.printer do |ctr,info|
logger = ctr[:logs].get( info )
lambda { |kind| Printer.new( logger, kind ) }
end

b.code_printer { |ctr,| ctr.printer.call( :monochrome ) }
b.image_printer { |ctr,| ctr.printer.call( :color ) }
end

I've actually incorporated this approach into various places in the
upcoming new release of Net::SSH, and it works beautifully.

> I hope there aren't too many inaccuracies in the above, and that this
> helps other folks move from older ruby idioms to the new idioms
> that Needle gives us.

Excellent write-up, Joel. You ought to publish this somewhere on a
website...although the fact that you posted it _here_ means it will be
archived in the ruby-talk archives, which is probably good enough.

Thanks!

- Jamis


--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck...


David Ross

11/13/2004 10:58:00 PM

0


>
> Excellent write-up, Joel. You ought to publish this somewhere on a
> website...although the fact that you posted it _here_ means it will be
> archived in the ruby-talk archives, which is probably good enough.
>
Publish on Rubymine (rubymine.org), its one of the other points of the
site is to bring all news together kind of like a slashdot for the ruby
community without all the fuzz of other topics. ;)

David Ross