Program design - template design pattern


#1

although im making a rails app this is more specific to ruby and general
coding.

I want to access several preknown rss feeds, parse and extract the
relevant data and store it into an array. The feeds all have similiar
content but the structure differs. That means my extracting regexps etc
will differ for each feed.

I want to do something like this

items = []
feeds.each do |feed|
clean_up(feed) #squeeze and strip stuff etc
item = parse(feed)
items << item
end
return items

where the code in parse() will vary depedning on the feed.

i know of the template design patter and can implement it but how will i
select the correct parse method for a given feed?

will i have to have a case control structure in the block which will
determine which feed is currently being processed and then apply the
correct parse method? If i had 50 feeds that could be one huge case
structure… is there a more elegant way?

any tips would be greatly appreciated.


#2

While a lot depends on several other aspects of your project, this
specific
problem depends on a principle question:

Do you have any control over the feed object?

If you have any control, then you could make a polymorphic superclass
called
Feed and go on from there where each separate feed has its own related
methods to deal with its idiosyncrasies and polymorphic methods that
deal
with common tasks. For ex:

class Feed
def initialize
end
def parse_content
end
end

class BbcFeed < Feed
def parse_content
# do something relevant here
# probably return a string/hash/or content object
end

define other methods specific to BbcFeed etc

end

Once this is done, you just have to create the right object at runtime,
perhaps have a factory object detailing this.

If you don’t have control, there isn’t a way to run away from doing
checks
on the object. Depending on how you determine the regex to use, you
could
have specific solutions. Perhaps each feed has a different URL that you
could use to determine the parsing, or perhaps something else in the
xml…either way, you have to know what object you are dealing with, or
you
have to write a parser that deals with it.

From your pseudo code, it would seem that you are still not thinking in
terms of object oriented code. For ex:

clean_up(feed)
parse(feed)

If you have to do it using OO, you probably want to assign those
behaviors
to specific objects. But don’t listen to me, I am not very good at this.

Hope this helps.

Jayanth


#3

2009/3/26 Srijayanth S. removed_email_address@domain.invalid:

While a lot depends on several other aspects of your project, this specific
problem depends on a principle question:

Do you have any control over the feed object?

I second that. Also, what type is “feed”? That’s not clear to me.

If you have any control, then you could make a polymorphic superclass called
Feed and go on from there where each separate feed has its own related
methods to deal with its idiosyncrasies and polymorphic methods that deal
with common tasks. For ex:

class Feed
def initialize
end
def parse_content
end

One could also add

download the feed

def fetch(uri)

end

Once this is done, you just have to create the right object at runtime,
perhaps have a factory object detailing this.

Or stuff the relationship between feed URI’s and class that deals with
it in a Hash:

FEEDS = {
http://foo.bar/feed.rdf’ => BbcFeed,
http://baz.boz.buz/path.rdf’ => BbcFeed,
http://what.ever.you/like’ => OtherFeed,
}.freeze

Then you can do

FEEDS.each |uri, cl|
feed_handler = cl.new
feed_handler.fetch
feed_handler.parse_content
end

If you don’t have control, there isn’t a way to run away from doing checks
on the object. Depending on how you determine the regex to use, you could
have specific solutions. Perhaps each feed has a different URL that you
could use to determine the parsing, or perhaps something else in the
xml…either way, you have to know what object you are dealing with, or you
have to write a parser that deals with it.

Feed type checks could be done on the URI or the content. Depending
on that a different approach needs to be followed but the basic
pattern stays the same.

Kind regards

robert


#4

On Thu, Mar 26, 2009 at 4:23 PM, Robert K.
removed_email_address@domain.invalidwrote:

called
One could also add

 # do something relevant here

feed_handler.fetch

have to write a parser that deals with it.

Feed type checks could be done on the URI or the content. Depending
on that a different approach needs to be followed but the basic
pattern stays the same.

Yeah I thought of that too, but God knows what his criterion for
choosing
the parser are. It might be more complex than just a simple uri mapping.

Jayanth


#5

Hi all,

thanks for you comments. Yes Im referring to rss feeds and i am in full
controll of how they are represented. Im choosing the feed addresses,
fetching them and parsing them.

I actually got confused between my patterns, it was the strategy pattern
not the template pattern. But at the end of the day it all boiled down
to how I could dynamically initialize each feed_parser and thats where i
got stuck mainly due to lack of programming experience.

I didnt know I could store class names in hashes but after reading up on
Ruby Desing Patterns i found out they are objects themselves.

So Ill think ill use the hash idea!

Thank you all so much for your suggestions.


#6

2009/3/27 Adam A. removed_email_address@domain.invalid:

I actually got confused between my patterns, it was the strategy pattern
not the template pattern. But at the end of the day it all boiled down
to how I could dynamically initialize each feed_parser and thats where i
got stuck mainly due to lack of programming experience.

I didnt know I could store class names in hashes but after reading up on

Actually those were not class names but class objects themselves in
my example!

Ruby Desing Patterns i found out they are objects themselves.

So Ill think ill use the hash idea!

So I conclude from that that you know which feed needs which parsing
algorithm.

Thank you all so much for your suggestions.

You’re welcome!

Kind regards

robert