On 2/9/07, Jukka Zitting <[EMAIL PROTECTED]> wrote:
Hi,Jackrabbit currently implements the JCR interfaces directly in the various Impl classes that directly access the underlying repository state. This approach has a few drawbacks: a) The Impl classes are huge, partly because the JCR interfaces typically declare such a large number of methods. For example: NodeImpl = 4.2kLOC, SessionImpl = 1.4kLOC, PropertyImpl = 1.2kLOC. b) Related to the above, the Impl classes have a large number of separate responsibilities, but as of now the fixed nature of the JCR interfaces prevent easy refactoring of those responsibilities to separate classes. c) Many Impl classes expose extra public or protected methods in addition to the ones declared in the JCR interfaces. This introduces potential security issues, especially when in some cases exposing some internal features to other internal classes would in fact be beneficial (for example access to the system session). d) The JCR interfaces contain many utility methods that can be implemented in terms of other JCR methods. Such default methods could easily be shared across JCR implementations but the nature of the current Impl classes prevents such sharing. e) Name parsing and formatting is normally only performed just when entering or leaving a JCR method. This mapping activity is currently duplicated in almost all method implementations. I would like to suggest that we introduce a new layer just beneath the JCR API for getting rid of or reducing the above drawbacks. This layer would consist of the following three parts: 1) Set of abstract AbstractSession, AbstractItem, etc. classes that implement as much of the respective JCR interfaces using nothing else but calls to other JCR methods. These would be just like the AbstractMap, etc. classes in java.util. 2) Set of QSession, QItem, etc. (or with some better naming) interfaces that declare QName and Path versions of those JCR methods that can't reasonably be implemented by the above abstract classess. Potentially we could also break strict one-to-one correspondence with the JCR interfaces to allow for better separation of concerns. 3) Set of adapter (or facade) classes that extend the above abstract classes and implement the remaining methods using name mapping and implementations of the above interfaces. These classes could also take care of backreferences like Session.getRepository() and Item.getSession(). All these parts could be implemented within jackrabbit-jcr-commons so that they can be reused in other JCR implementations, for example in the client part of the SPI project. The current Impl classes in jackrabbit-core would be refactored to implement the above interfaces instead of the standard JCR interfaces. What do you think? At least the first part of the proposal should be easy to implement incrementally without destabilizing anything. The granularity of implementing the other parts is a bit bigger, but could still be performed just one interface at a time.
sounds good, +1 in general. however, we should IMO be careful not to blindly sacrifice performance for cleaner code. a move operation could e.g. be modeled as a copy&delete, this might make sense from a design perspective, but not performance wise. cheers stefan
BR, Jukka Zitting
