You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Jonathan Stimmel <jo...@stimmel.net> on 2000/05/23 23:28:31 UTC

DirectoryGenerator.java

Ok, so I stuck my neck out a little and put my reputation on the
line, so I had plenty of incentive for me to follow through
on my promise to start taking an active role. Last night I
jumped into "cleaning up" DirectoryGenerator.java, which I've
attached (a patch would have been larger than the resultant file).

I believe I've conformed to Sun's coding standards, though it also
reflects my own coding style:
  - I dislike single-character variables, except for indexes
  - I avoid lines longer than ~75 characters
  - I like short methods (less than 20-30 lines or so)
  - I like whitespace =)

Comments welcome (of course)... here are mine:

  I restructured the code a little to add some functionality.
  The generator now:
   - includes the modification time/date of each file/directory
   - optionally traverses multiple levels of directories

  I honestly don't understand the role of startPrefixMapping,
  so I just left it alone (I was tempted to remove it, since I
  wasn't sure it really made a difference in this case).

  I removed the file/directory name from the data of each node,
  since it already appears as an attribute. I also removed the
  trailing "/" that was being added to directory names, as I felt
  it was redundant. OTOH, I probably should have included more
  path information in each node, to make it easier to process
  nested directories.

  I used SimpleDateFormat to format the file modification date,
  but it cannot be used with all locales (and I'm unsure of the
  effect in that case).

  The original DirectoryGenerator used the Java2 method
  File.getCanonicalFile, so I assumed cocoon2 requires Java2
  or better

  It seems odd that two method calls (setup and generate) will be
  made to process a given request, forcing the class to store
  very short-lived data at the class level. My instinct tells
  me that setup (or something similar) would only be called
  when instantiating the class (while parsing the config file)
  and request-specific data would be passed directly to generate.

  I don't understand the need to both create an interface and an
  abstract class that implements the interface. I would expect that
  one or the other should suffice (I would tend towards an abstract
  class), and trying to use both just increases complexity (and
  maintenance overheatrying to use both just increases complexity
  and maintenance overhead. (This is not the only place this is done)

Re: Interfaces vs. Abstract classes (was Re: DirectoryGenerator.java)

Posted by Berin Loritsch <bl...@infoplanning.com>.

Jonathan Stimmel wrote:

> On Wed, May 24, 2000 at 08:59:43PM +0200, Giacomo Pati wrote:
>
> > The interface definition is made according to the design pattern in use.
> > The abstract class fills some commonly used method with code and/or
> > implements other interfaces as well (you know multiple inheritance from
> > abstract classes is not possible in java).
>
> Sure, interfaces let you implement mutliple inheritance (actually, that's
> probably a misnomer, since you're not inheriting actual method calls),
> but is that necessarily a Good Thing(tm)? Interfaces should be used
> for secondary relationships, not primary roles. Looking through
> O'Reilly's "Java in a Nutshell", I rarely see this kind of relationship
> (interface->abstract->xxx), and its mostly for truly abstract concepts
> or utilities (the collections classes, specifically).
>
> I realise that I'm the dissenting opinion here, and it's not really a
> battle worth fighting (feels like the start of coding-style holy war).
> IMO, though, encouraging this methodology as the rule (rather than the
> exception) only serves to increase cocoon's complexity by encouraging
> objects to have many relationships to each other. Maintenance is an
> important consideration for any project, but especially for a project
> that is still in an evolutionary phase. A future version (e.g. 2.5) can
> always add the interfaces back if it's discovered that they truly are
> needed (and, of course, they could always be removed later if I can
> prove that they're unecessary =).

It is important to note that while you can implement multiple interfaces
per class, you should not always do that.  Any time that a system uses
components, it should specify an interface so that the component behaves
in an expected manner.  Interfaces are an integral part of component
based engineering.  Cocoon definitely qualifies as a component based
architecture--so the interfaces should stay.

I also think your point about maintainability should be well taken.  Even
though I legally can implement multiple interfaces in an object, for
maintainability reasons I should really think about better/alternative
ways of handling that scenario.

Case and point about why interfaces should stay: JDBC.  Without interfaces
for programs to use, database programming in Java would be an unruly
mess.  We know have a well defined API, and we know what should happen
with a well behaved JDBC driver.  The same concept applies in Cocoon.



Re: Interfaces vs. Abstract classes (was Re: DirectoryGenerator.java)

Posted by Stefano Mazzocchi <st...@apache.org>.
Jonathan Stimmel wrote:
> 
> On Wed, May 24, 2000 at 08:59:43PM +0200, Giacomo Pati wrote:
> 
> > The interface definition is made according to the design pattern in use.
> > The abstract class fills some commonly used method with code and/or
> > implements other interfaces as well (you know multiple inheritance from
> > abstract classes is not possible in java).
> 
> Sure, interfaces let you implement mutliple inheritance (actually, that's
> probably a misnomer, since you're not inheriting actual method calls),
> but is that necessarily a Good Thing(tm)? 

Multiple inheritance for interface is a Good Thing(tm) IMO, without
that, the use of PolyMorphism as design pattern would be extremely
reduced.

> Interfaces should be used for secondary relationships, not primary roles. 

Who said that?

Intefaces are the equivalent of protocols, while abstract classes are
the equivalent of half-implemented protocol stacks.

Should we base our relationship on half-implemented protocol stacks, or
on RFC that define what to do?

> Looking through
> O'Reilly's "Java in a Nutshell", I rarely see this kind of relationship
> (interface->abstract->xxx), and its mostly for truly abstract concepts
> or utilities (the collections classes, specifically).

Well, sorry, but this doesn't mean anything. I haven't read the book,
but I did read and write lots of hardcore Java code and I learned it the
hard way, bouncing back when hitting the wall at full speed.

Interfaces make the _real_ difference between other object oriented
languages where polymorphism wasn't included right into the language.
Luckily it is so for Java.

Know which one is my favorite Java class? java.lang.Serializable.

Go take a look... yes, it's empty. It's hard to find the case where an
empty interface is required... but when it is so, they are _so_
incredibly elegant.

Let's make an example: suppose you want to create a Cocoon2 component,
say a JDBC pool manager. So you start by:

 public interface PoolManager extends Component {

ok, cool, now Cocoon is able to see it's a component and you are able to
access it thru all the other components that required access to other
components.

Yes, because there are two types of classes:

 - Components -> are used by others
 - Composers -> need to use external components

Ok, now you decide you need, say, a logger in order to function (this is
not really the case since logging should be a system API and not a
component, but just as an example). So your pool is _both_ a component
and a composer... so you must tell Cocoon about this

 public interface PoolManager extends Component, Composer {

Cool, but I need Cocoon to pass me my configurations, so 

 public interface PoolManager extends Component, Composer, Configurable
{

Hmmm, but most pool managers need their own thread to manage the
connections so

 public interface PoolManager extends Component, Composer, Configurable,
Runnable {
   public Connection getConnection(Query query);
 }

Now you are left with an interface that has _lots_ of methods and you
need a way to simply the creation of this component.

So you create an abstract class that takes care of all the component
machinery and declares abstract only those methods that _need_ to be
overloaded when providing the actual component logic.

Well, it took me, Pierpaolo and Federico almost a year to come up with
such a design pattern for componentized frameworks (see the Avalon
project on java.apache.org) and if you think this is abusing of
interfaces, well, I _strongly_ disagree with you since your abstract
classes do almost nothing compared to the flexibility of these patterns.
 
> I realise that I'm the dissenting opinion here, and it's not really a
> battle worth fighting (feels like the start of coding-style holy war).

No, this is not a religious war: there are -evident- proofs of
functionality here.

> IMO, though, encouraging this methodology as the rule (rather than the
> exception) only serves to increase cocoon's complexity by encouraging
> objects to have many relationships to each other. 

It guarantees that components work well between each other. 

When you do dynamic loading of components you have to sacrifice
compilation strong-typing for something else. Creating a good
infrastructure of casting types is the only way we found to glue
together the system, expecially when developped by many different
individuals.

In fact, it has proven to be extremely scalable and easy to be adopted
by new developers (isn't it so, guys?)

> Maintenance is an
> important consideration for any project, but especially for a project
> that is still in an evolutionary phase. A future version (e.g. 2.5) can
> always add the interfaces back if it's discovered that they truly are
> needed (and, of course, they could always be removed later if I can
> prove that they're unecessary =).

It's _exactly_ the opposite: without a good type-casting framework, this
project is not going to reach a stable point due to problems between
components.

-- 
Stefano Mazzocchi      One must still have chaos in oneself to be
                          able to give birth to a dancing star.
<st...@apache.org>                             Friedrich Nietzsche
--------------------------------------------------------------------
 Missed us in Orlando? Make it up with ApacheCON Europe in London!
------------------------- http://ApacheCon.Com ---------------------



Re: Interfaces vs. Abstract classes (was Re: DirectoryGenerator.java)

Posted by Donald Ball <ba...@webslingerZ.com>.
On Thu, 25 May 2000, Jonathan Stimmel wrote:

> On Wed, May 24, 2000 at 08:59:43PM +0200, Giacomo Pati wrote:
> 
> > The interface definition is made according to the design pattern in use.
> > The abstract class fills some commonly used method with code and/or
> > implements other interfaces as well (you know multiple inheritance from
> > abstract classes is not possible in java).
> 
> Sure, interfaces let you implement mutliple inheritance (actually, that's
> probably a misnomer, since you're not inheriting actual method calls),
> but is that necessarily a Good Thing(tm)? Interfaces should be used
> for secondary relationships, not primary roles. Looking through
> O'Reilly's "Java in a Nutshell", I rarely see this kind of relationship
> (interface->abstract->xxx), and its mostly for truly abstract concepts
> or utilities (the collections classes, specifically).
>
> I realise that I'm the dissenting opinion here, and it's not really a
> battle worth fighting (feels like the start of coding-style holy war).
> IMO, though, encouraging this methodology as the rule (rather than the
> exception) only serves to increase cocoon's complexity by encouraging
> objects to have many relationships to each other. Maintenance is an
> important consideration for any project, but especially for a project
> that is still in an evolutionary phase. A future version (e.g. 2.5) can
> always add the interfaces back if it's discovered that they truly are
> needed (and, of course, they could always be removed later if I can
> prove that they're unecessary =).

cocoon objects hardly ever have direct relationships to each other. the
cocoon framework provides a central service called director (maybe
something else in cocoon2, can't remember) from which a cocoon object can
request a reference to the object which plays a certain role (parser,
transformer, whatever). i find that to be a very clean way to manage
interobject relationships.

interfaces in cocoon also provide important clues to the director when
it's creating and initializing its actors. the director knows that if an
actor implements a certain interface, certain things should occur (e.g.
configuration information should be read from the properties file, a
logging channel should be created, etc.)

- donald


Interfaces vs. Abstract classes (was Re: DirectoryGenerator.java)

Posted by Jonathan Stimmel <jo...@stimmel.net>.
On Wed, May 24, 2000 at 08:59:43PM +0200, Giacomo Pati wrote:

> The interface definition is made according to the design pattern in use.
> The abstract class fills some commonly used method with code and/or
> implements other interfaces as well (you know multiple inheritance from
> abstract classes is not possible in java).

Sure, interfaces let you implement mutliple inheritance (actually, that's
probably a misnomer, since you're not inheriting actual method calls),
but is that necessarily a Good Thing(tm)? Interfaces should be used
for secondary relationships, not primary roles. Looking through
O'Reilly's "Java in a Nutshell", I rarely see this kind of relationship
(interface->abstract->xxx), and its mostly for truly abstract concepts
or utilities (the collections classes, specifically).

I realise that I'm the dissenting opinion here, and it's not really a
battle worth fighting (feels like the start of coding-style holy war).
IMO, though, encouraging this methodology as the rule (rather than the
exception) only serves to increase cocoon's complexity by encouraging
objects to have many relationships to each other. Maintenance is an
important consideration for any project, but especially for a project
that is still in an evolutionary phase. A future version (e.g. 2.5) can
always add the interfaces back if it's discovered that they truly are
needed (and, of course, they could always be removed later if I can
prove that they're unecessary =).

Re: DirectoryGenerator.java

Posted by Ross Burton <ro...@mail.com>.
> getCanonicalFile is gone, but I added another java2 method
> (java.io.File.listFiles())...

listFIles() is just a conventient way of using list() and new File()
together.  Easy to remove!

Ross


Re: DirectoryGenerator.java

Posted by Giacomo Pati <Gi...@pwr.ch>.
Jonathan Stimmel wrote:
> 
> On Wed, May 24, 2000 at 08:59:43PM +0200, Giacomo Pati wrote:
> 
> > have you removed it?
> 
> getCanonicalFile is gone, but I added another java2 method
> (java.io.File.listFiles())...
> 
> I will revisit my changes and refine the class further based on
> input from the list. Part of my intention was to get a taste of
> cocoon internals development, and from that standpoint I would suggest
> you *not* check it in just yet (but then again, that's contrary to
> the "release early, release often" philosophy...)

Oops, already gone. But it sounds that you are doing a new version
anyway. Could you maybe check if java2 dependencies can be removed?

Giacomo

-- 
PWR GmbH, Organisation & Entwicklung      Tel:   +41 (0)1 856 2202
Giacomo Pati, CTO/CEO                     Fax:   +41 (0)1 856 2201
Hintereichenstrasse 7                     Mailto:Giacomo.Pati@pwr.ch
CH-8166 Niederweningen                    Web:   http://www.pwr.ch

Re: DirectoryGenerator.java

Posted by Jonathan Stimmel <jo...@stimmel.net>.
On Wed, May 24, 2000 at 08:59:43PM +0200, Giacomo Pati wrote:

> 
> >   I restructured the code a little to add some functionality.
> >   The generator now:
> >    - includes the modification time/date of each file/directory
> 
> It can be used as an example to implement other information (someone
> mentioned MIME types). I've realized that the 'modified' attribute is
> implemented twice! 

I had thought about adding mime-types, but decided to to that at a later
date (incremental updates, rather than "hoarde and post" =) I was
also concerned about feature bloat (a concern Stefano has already brought
up).

As for including the modification time twice, I don't like it either,
and after more thought I'm inclined to take one out. Including the time
as milliseconds is useful for sorting; my main reason for adding a human
readable time was so that it could easily be displayed using an xsl
stylesheet.


> >    - optionally traverses multiple levels of directories
> 
> What is it good for?

Very little that I can think of. It falls into the, "oh, that
would be trivial to add with little to no performance hit" feature
category.


> >   I also removed the
> >   trailing "/" that was being added to directory names, as I felt
> >   it was redundant. 
> 
> The trailing '/' was only used to make the <a> tag work in the
> stylesheet without any further adjustment.

I can understand that. Personally, I find it easier to add delimiters
when I need them than to remember to remove them when I don't.


> >   OTOH, I probably should have included more
> >   path information in each node, to make it easier to process
> >   nested directories.
> 
> I still don't see the reason for nested directories.

Here's a possible application. I have an xsp page (cocoon1) which
scans a total of six directories and presents a digest/summary of
their contents (sorted by timestamp and location):
  dir1/good	dir1/bad
  dir2/good	dir2/bad
  dir3/good	dir3/bad
An "ideal" (to me) structure for doing this in cocoon2 would be to
us DirectoryGenerator to create the file list, then use a filter
to fill in the details of the files (title, first paragraph, etc.).
Allowing DirectoryGenerator to do a recursive list would simplify
the configuration in this case.

Actually, given the model I just outlined, you could argue (and I
am now inclined to agree) that even including the timestamp is
too much, as the filter will need to do further processing of
the file anyway. Or perhaps DirectoryGenerator should provide a
simple (optional) filter and sorting mechanism to make it
easy to trim the listing to relevant files, so that the filter
can focus on less mundane tasks? (Pardon me as I think out loud
a bit... =)


> >   The original DirectoryGenerator used the Java2 method
> >   File.getCanonicalFile, so I assumed cocoon2 requires Java2
> >   or better
> 
> have you removed it?

getCanonicalFile is gone, but I added another java2 method
(java.io.File.listFiles())...


I will revisit my changes and refine the class further based on
input from the list. Part of my intention was to get a taste of
cocoon internals development, and from that standpoint I would suggest
you *not* check it in just yet (but then again, that's contrary to
the "release early, release often" philosophy...)


I'm getting long-winded (as usual =) and will respond to your other
comments in a new thread.

Re: DirectoryGenerator.java

Posted by Giacomo Pati <Gi...@pwr.ch>.
Jonathan Stimmel wrote:
> 
> Ok, so I stuck my neck out a little and put my reputation on the
> line, so I had plenty of incentive for me to follow through
> on my promise to start taking an active role. Last night I
> jumped into "cleaning up" DirectoryGenerator.java, which I've
> attached (a patch would have been larger than the resultant file).

I will check it in soon (as long as nobody is against this)

>   I restructured the code a little to add some functionality.
>   The generator now:
>    - includes the modification time/date of each file/directory

It can be used as an example to implement other information (someone
mentioned MIME types). I've realized that the 'modified' attribute is
implemented twice! 

>    - optionally traverses multiple levels of directories

What is it good for?

> 
>   I honestly don't understand the role of startPrefixMapping,
>   so I just left it alone (I was tempted to remove it, since I
>   wasn't sure it really made a difference in this case).

It is part of the SAX ContentHandler interface. A description can be
found in the xerxes code (org.xml.sax.ContentHandler.java)

> 
>   I removed the file/directory name from the data of each node,
>   since it already appears as an attribute. 

I've realized it and modified the corresponding stylesheet, which
renders it to html. I will commit it soon.

>   I also removed the
>   trailing "/" that was being added to directory names, as I felt
>   it was redundant. 

The trailing '/' was only used to make the <a> tag work in the
stylesheet without any further adjustment.

>   OTOH, I probably should have included more
>   path information in each node, to make it easier to process
>   nested directories.

I still don't see the reason for nested directories.

>   The original DirectoryGenerator used the Java2 method
>   File.getCanonicalFile, so I assumed cocoon2 requires Java2
>   or better

have you removed it?

>   It seems odd that two method calls (setup and generate) will be
>   made to process a given request, forcing the class to store
>   very short-lived data at the class level. My instinct tells
>   me that setup (or something similar) would only be called
>   when instantiating the class (while parsing the config file)
>   and request-specific data would be passed directly to generate.

Maybe the separate generate method with no parameters leaves room to use
it outside the request/response context (it's my personal presumtion).

> 
>   I don't understand the need to both create an interface and an
>   abstract class that implements the interface. I would expect that
>   one or the other should suffice (I would tend towards an abstract
>   class), and trying to use both just increases complexity (and
>   maintenance overheatrying to use both just increases complexity
>   and maintenance overhead. (This is not the only place this is done)

The interface definition is made according to the design pattern in use.
The abstract class fills some commonly used method with code and/or
implements other interfaces as well (you know multiple inheritance from
abstract classes is not possible in java).

Giacomo

-- 
PWR GmbH, Organisation & Entwicklung      Tel:   +41 (0)1 856 2202
Giacomo Pati, CTO/CEO                     Fax:   +41 (0)1 856 2201
Hintereichenstrasse 7                     Mailto:Giacomo.Pati@pwr.ch
CH-8166 Niederweningen                    Web:   http://www.pwr.ch

Re: DirectoryGenerator.java

Posted by Jonathan Stimmel <jo...@stimmel.net>.
On Wed, May 24, 2000 at 01:06:08AM +0200, Stefano Mazzocchi wrote:

> Can you send us the DTD that results, or, at least, a sample document?

I intend to write a DTD, but haven't yet. Here's a sample, where
the depth is set to "2":

  <directory name="startDir" lastModified="959205940"
             date="Wed May 24 15:05:40 2000">

    <file name="file3"  lastModified="959206113"
          date="Wed May 24 15:08:33 2000"/>

    <directory name="subdir" lastModified="959206150"
               date="Wed May 24 15:09:10 2000">

      <file name="this" lastModified="959206237"
            date="Wed May 24 15:10:37 2000"/>

      <file name="that" lastModified="959206243"
            date="Wed May 24 15:10:43 2000"/>

      <directory name="other" lastModified="959206320"
                 date="Wed May 24 15:12:00 2000"/>

    </directory>

    <file name="file1" lastModified="959206132"
          date="Wed May 24 15:08:52 2000"/>

  </directory>

(Whitespace added by me. Unlike the original generator, mine
does not try to "format" the xml by adding newlines and spaces).