hi!
i have a design question. for example i have a class which reads a file
and prints out each line with line numbers. what if now i wanna be able
to plugin some functionality which sorts the file, depending on some
conditions (extension, etc) before its passed on to the line numbering
functionality. the class should be as less tied as possible to the sorting
functionality as possible..
how would you normally design that in ruby?
would you just overwrite the method which calls the file read method
and passes it to the numbering method?
would you pack an object in between, which would check if the file
has to be sorted, because the conditions are true, read the file and
the return the sorted or unsorted content?
basically im wondering if its considered a good practice to overwrite
methods on the same class or if its kinda hackish.. =)
thanks a lot!
ciao!
florian
I would maybe add a filter class (TextFilter maybe?) and then add them as an
aggregate objects to your File reading class, I'd maybe have 2 types of
filters.
- Inprocess filter (while you're reading in the files by lines)
- Postprocess filter (after you've read the file in)
So maybe a outline like:
class TextFilter
def read( text )
return text
end
end
class SortTextFilter < TextFilter
def read( text )
text = self.sort( text )
end
def sort( text )
#Sort text, maybe ascending by default
return text
end
end
fr = FileReader.new( SortTextFilter.new() );
fr.read( "myfile.txt" )
puts fr
Whatcha think?
Zach
···
-----Original Message-----
From: Florian Weber [mailto:csshsh@structbench.com]
Sent: Wednesday, June 16, 2004 11:11 AM
To: ruby-talk ML
Subject: how to design plugin functionality
hi!
i have a design question. for example i have a class which reads a file
and prints out each line with line numbers. what if now i wanna be able
to plugin some functionality which sorts the file, depending on some
conditions (extension, etc) before its passed on to the line numbering
functionality. the class should be as less tied as possible to the
sorting
functionality as possible..
how would you normally design that in ruby?
would you just overwrite the method which calls the file read method
and passes it to the numbering method?
would you pack an object in between, which would check if the file
has to be sorted, because the conditions are true, read the file and
the return the sorted or unsorted content?
basically im wondering if its considered a good practice to overwrite
methods on the same class or if its kinda hackish.. =)
thanks a lot!
ciao!
florian
---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.705 / Virus Database: 461 - Release Date: 6/12/2004
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.705 / Virus Database: 461 - Release Date: 6/12/2004
first i'd separate the notion of a file's lines into it's own class - one that
simply loads a file and provides a method to access those lines, but does no
printing. then i'd design outputter classes that operate on line sets.
somewhere in between you can filter/munge the lines - possible using a class
hierarchy of Mungers, possibly using duck-typed objects which respond_to?
'munge', possibly just using callbacks (Procs). this uses the last approach:
~ > cat a.rb
class LineSet < Array
attr :path
def initialize path
super()
@path = path
replace(IO.readlines(path))
end
def munge(*procs)
c = self.cp
unless procs.empty?
procs.each{|pc| c = pc.call(c)}
else
c = yield c
end
c
end
def munge!(*procs, &block)
replace(munge(*procs, &block))
end
def cp
Marshal.load(Marshal.dump(self))
end
end
class Outputter
def initialize lines
@lines = lines
end
def output out
raise NotImplementedError
end
end
class NumberedOutputter < Outputter
def output out = STDOUT
@lines.each_with_index do |line, idx|
out << "#{ idx }: #{ line }"
end
end
end
lines = LineSet.new __FILE__
reverser = lambda{|ls| ls.reverse}
shrinker = lambda{|ls| ls[0,2]}
puts '----'
munged = lines.munge reverser, shrinker
no = NumberedOutputter.new munged
no.output
puts '----'
lines.munge! shrinker, reverser
no = NumberedOutputter.new lines no.output
~ > ruby a.rb
···
On Thu, 17 Jun 2004, Florian Weber wrote:
hi!
i have a design question. for example i have a class which reads a file
and prints out each line with line numbers. what if now i wanna be able
to plugin some functionality which sorts the file, depending on some
conditions (extension, etc) before its passed on to the line numbering
functionality. the class should be as less tied as possible to the
sorting
functionality as possible..
how would you normally design that in ruby?
would you just overwrite the method which calls the file read method
and passes it to the numbering method?
would you pack an object in between, which would check if the file
has to be sorted, because the conditions are true, read the file and
the return the sorted or unsorted content?
basically im wondering if its considered a good practice to overwrite
methods on the same class or if its kinda hackish.. =)
thanks a lot!
ciao!
florian
----
0: no.output
1: no = NumberedOutputter.new lines ----
0: attr :path
1: class LineSet < Array
-a
--
EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it; and a weed grows, even though we do
not love it. --Dogen
===============================================================================
I'd say that you could use some kind of pattern and so on.
You may find this thread useful:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/48648
As of now I'd probably use some trick similar to this:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/97440
to allow the user to write something like add_filter(:read) do.. end
···
il Thu, 17 Jun 2004 00:10:40 +0900, Florian Weber <csshsh@structbench.com> ha scritto::
hi!
i have a design question. for example i have a class which reads a file
and prints out each line with line numbers. what if now i wanna be able
to plugin some functionality which sorts the file, depending on some
conditions (extension, etc) before its passed on to the line numbering
functionality. the class should be as less tied as possible to the
sorting
functionality as possible..
how would you normally design that in ruby?
You could use modules:
module SortedOutput
def read
@lines = File.readlines(@file).sort
end
end
Then you can do:
class MyFileOutputter
def initialize(file)
@file = file
end
def read
@lines = File.readlines(@file)
end
def output(io=$stdout)
read unless @lines
@lines.each_with_index do |line, i|
io.puts "#{i+1}. #{line}"
end
end
end
outputter = MyFileOutputter.new("myfile.txt")
outputter.extend SortedOutput
outputter.output
I find mixing in Modules that replace methods on object instances pretty
handy.
-rich
···
On 6/16/04 11:10 AM, "Florian Weber" <csshsh@structbench.com> wrote:
hi!
i have a design question. for example i have a class which reads a file
and prints out each line with line numbers. what if now i wanna be able
to plugin some functionality which sorts the file, depending on some
conditions (extension, etc) before its passed on to the line numbering
functionality. the class should be as less tied as possible to the
sorting
functionality as possible..
how would you normally design that in ruby?
would you just overwrite the method which calls the file read method
and passes it to the numbering method?
would you pack an object in between, which would check if the file
has to be sorted, because the conditions are true, read the file and
the return the sorted or unsorted content?
basically im wondering if its considered a good practice to overwrite
methods on the same class or if its kinda hackish.. =)
thanks a lot!
ciao!
florian
im really sorry. i think it was really misleading to give such a
concret example. basically the example i gave is purely fictional.
basically i was more wondering if overwriting methods (methods of
the same class, not methods of a superclass) is a recommended
good practice for functionality which can be plugged in or
if such things should be done in a traditional way, where a object
is 'plugged' in between, which decides if the additional functionality
should be executed or not.
sorry for the misunderstanding =)
ciao!
florian
I think overriding the methods of the existing class is poor choice. The
only reason that I would suggest this is if there was some drastic
performance issue when moving the functionality outside of the class, but I
don't see that happening. It is better program design to leave the original
class alone. It makes your code more readable, reusable and maintainable. It
also allows your class to be more reusable for other projects and other
people.
I suggest a book reading...
"Design Patterns
Elements of Reusable Object-Oriented Software" by Erich Gamma, Richard
Helm, Ralph Johnson and John Vlissides.
It's a deep reading, but it's a good one.
HTH,
Zac
···
-----Original Message-----
From: Florian Weber [mailto:csshsh@structbench.com]
Sent: Wednesday, June 16, 2004 4:42 PM
To: ruby-talk ML
Subject: Re: how to design plugin functionality
im really sorry. i think it was really misleading to give such a
concret example. basically the example i gave is purely fictional.
basically i was more wondering if overwriting methods (methods of
the same class, not methods of a superclass) is a recommended
good practice for functionality which can be plugged in or
if such things should be done in a traditional way, where a object
is 'plugged' in between, which decides if the additional functionality
should be executed or not.
sorry for the misunderstanding =)
ciao!
florian
---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.705 / Virus Database: 461 - Release Date: 6/12/2004
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.705 / Virus Database: 461 - Release Date: 6/12/2004
im really sorry. i think it was really misleading to give such a
concret example. basically the example i gave is purely fictional.
basically i was more wondering if overwriting methods (methods of
the same class, not methods of a superclass) is a recommended
good practice for functionality which can be plugged in or
if such things should be done in a traditional way, where a object
is 'plugged' in between, which decides if the additional functionality
should be executed or not.
Well, methods can be replaced on classes at runtime as then can on instances
of classes. Although changing class methods changes the behavior of all
instances (and _could_ be very bad), changing methods on objects can be very
powerful. I don't see any reason not to do it if the design requires that
kind of changeable behavior. But again, all these choices need to be
balanced against the requirements of what you are trying to do.
sorry for the misunderstanding =)
No problem!
-rich
···
On 6/16/04 4:41 PM, "Florian Weber" <csshsh@structbench.com> wrote:
ciao!
florian