Jeremias Maerki wrote:

> I got a little shock when I realized a problem I didn't think 
> of when we discussed moving FOP components over to XML 
> Graphics Commons. We said we would try to remove logging code 
> from these basic components entirely.
>
> Now, I forgot to consider the decision to use FOrayFont made earlier.
> The external dependency on FOrayFont also would be a problem 
> in itself because the Batik side has strong feelings against 
> external dependencies.
> We need to think about what to do about this WRT the PDF and 
> PS transcoders. Optimized text painting in these two 
> transcoders depends a lot on the font subsystem.

Well, the little change I just made removes entirely any dependency on
Avalon in any FOray code, except for the fact that Ant seems to need it for
logging (needed for creating hyphenation patterns and such). There is no
longer any Avalon code in FOrayFont. In fact, that was the primary
motivation for making the change. The Avalon Logger interface would have
been quite a sufficient solution for anything that FOray needs, and, since
it is an interface, adapters could be written from it to anything else, just
as Vincent and I have been discussing for the PseudoLogger interface.

> Aside from that, a thought about the aXSL APIs: Being an 
> ex-Avaloner SoC (separation of concerns) is a big concern to 
> me. The functional API of a package should IMO actually not 
> deal with (or rather expose) logging at all. It's a separate 
> concern. I'm ever growing more cofident that 
> developer-oriented logging should be done through a static 
> logging facility (like Commons Logging) and that 
> end-user-oriented logging needs to operate per processing run 
> (like Avalon Logger) but not necessarily through a standard 
> logging abstraction interface, but rather an 
> application-specific one that provides exactly what the 
> application needs to send feedback to the end-users. In that 
> light, a PDF or font library shouldn't expose any logging 
> facilities at all or at least to static logging that is 
> externally configured.

First, do you understand that the FOrayFont library does not "expose any
logging facilities" to the client, but instead asks the client to expose the
logging facilities to it? A PseudoLogger is required (but can be passed
null) in the FontServer constructor and is required in a method in
FontConsumer. But FontConsumer is implemented on the client side, in which
the client application tells FOray about itself.

Second, why should FOray limit its clients to only use static logging? If
the client has to expose a static logging mechanism to FOray in order to get
static logging to work, what can possibly be wrong with exposing a
non-static logging mechanism to FOray? Right now, FOray doesn't care whether
static or non-static logging is used. Why should it?

Third, lets define the "concern". <important>My understanding of Separation
of Concerns in this case is that FOrayFont owns the concern that a message
needs to be logged, and that the client application owns the concern of how
that logging should be accomplished.</important>

In order to maintain that Separation of Concerns, one of two things must
happen:
1. The client must tell the component how stuff should be logged.
2. The server must tell the client what should be logged.

This means some logging-related stuff will appear in the interface between
the two.

The design considerations are as follows:
1. FOrayFont needs to be able to log messages.
2. FOrayFont needs to be able to work with any client system, regardless of
their preferences on logging.

I can keep all logging internal to the FOrayFont subsystem, which would mean
that the client application (FOP) has no control over the logging
whatsoever. Very bad. FOray has to guess what kind of logger to use, and it
will never be right.

I can expose a logging interface that allows the client application to
handle logging its own way. This has been the approach used so far.

The only other solution is a bit more complex, and IMO, quickly becomes
ugly. FOrayFont currently asks some client object to implement the
FontConsumer interface. Instead of having FontConsumer provide a
PseudoLogger, it could have a method instead that logs messages:

    /**
     * @param level An integer describing the level at which this message
should be logged,
     * that is, error, warning, debug, etc.
     */
    public void logMessage(String message, int level) ;

The problem here is that I need to then create another interface that has
something similar that can pass itself to FontServer so that general (not
document-specific) logging messages can be handled. I also need to create
one for Graphics, Text, FOTree, etc. I will have 10 or 12 methods in various
interfaces that all do the same thing. This seems silly to me. This begs for
a type to do this, which the Avalon Logger interface provided and which
PseudoLogger provides as well.

Further, does a logMessage() method still expose logging functionality in a
way that is objectionable to you and to Batik?

> Now, I know this has the potential to spark a heated debate 
> again and it raises question marks about the FOrayFont 
> integration, but ATM I really don't know what to do about it 
> right now. I just realized we have a problem here. I/we made 
> promises on general@xmlgraphics.apache.org to try to remove 
> logging and other external dependencies (like Avalon) for the 
> common components because that's something which is very 
> important to the Batik side.

So, then, how are those components supposed to log anything? Or, if they are
to log using their own static stuff, how can this be configured by the
client?

> Maybe we could have two different implementations of the 
> PDFTextElementBridge so Batik can do native text rendering in 
> a different way than FOP but there's still the PDF library 
> that depends largely on the font subsystem. But maybe this 
> could be handled in a similar way. I need to investigate that 
> a little more.

I'll be glad to help any way I can, and at this stage FOray can be flexible.
But I must admit that I don't follow the logic. I need for someone to do one
of the following:
1. explain which of the two design considerations listed above you would
have your components abandon
2. suggest a solution that allows *both* design considerations to be
retained, but does not have the client either doing the logging or telling
the component how to do the logging.

I still find myself learning new tricks, so perhaps there is some other
elegant alternative that I am simply too blind to yet see.

The deeper question here is whether it is really wise to avoid all external
dependencies. FOray is invested heavily in the idea that reusability is A
Good Thing. My sense is that FOP still struggles with this question.

Victor Mote

Reply via email to