I thought Kathey/Dan's idea of generating copies of the common code
into two separate directories was interesting and solved a lot of problems,
and I thought it would be worthwhile to walk through this in a bit more
detail.
I took a look at all the relevant use cases I could think of and describe
the steps involved and what the user experience will be like. Through
this effort I did find a couple of possible issues that may make us want
to think twice about this approach. Perhaps others can think of ways around
these issues. I have labelled issues uncovered with the tag <ISSUE> in
the text below, rather than try and summarize them here.
CREATING A COMMON CLASS
Say a developer wants to add a new class for logging.
The developer creates the package directory
java/common/org/apache/derby/common/logging
Under this directory she creates the new class Logger. A simple
version is shown here.
===========
/**
Derby class org.apache.derby.common.logging.Logger
Copyright yada yada
*/
package org.apache.derby.common.logging;
/**
* Class description
*/
public class Logger
{
public void log(int level, String message)
{
// log this message
}
}
===========
Note that this looks like a regular class. This is so you
can edit it as a Java class in Java-aware IDEs.
BUILDING THE COMMON PACKAGE
The build script for the org/apache/derby/common directories
will not compile the class. Instead, it invokes a build-time
tool that will perform the following actions for each class
in the org/apache/derby/common hierarchy:
- Create a copy of the file in java/common/org/apache/derby/engine/common
and change the package name in this copy to
org.apache.derby.engine.common.
- Create a copy of the file in java/common/org/apache/derby/client/common
and change the package name in this copy to org.apache.derby.client.common
- No lines will be added or removed. This ensures that during debugging
the line numbers in the generated code match the line numbers in the
original source.
- Compile both copies
The client/common and engine/common directories will be created if
they don't exist and will NOT be included in the svn directory structure.
ant clobber/clean will remove the client/common and engine/common
directories.
The generated source files will NOT be removed after compilation so
that developers can use a source debugger and so that you can navigate
to the source for browsing in Java-aware IDEs. More on debugging below.
The classes under engine/common will be placed into derby.jar and
derbytools.jar. The classes under client/common will be placed into
derbyclient.jar.
<ISSUE>
QUESTION: is there a need for mixed versions between the tools and
engine code? If so we will need to generate a third package hierarchy
org.apache.derby.tools.common.*.
</ISSUE>
USING A COMMON CLASS
Code under java/engine, java/drda, java/tools and java/testing should
all import the classes under org.apache.derby.engine.common.
Code under java/client should import the classes under
org.apache.derby.client.common.
Common code unit tests can use either package hierarchy.
DEBUGGING A COMMON CLASS
Stack traces and debug stacks will point to the generated code
under engine/common or client/common depending on whether you
are debugging engine/tools/network code or client code.
<ISSUE>
If the debugger takes a developer to a common file and they see a bug,
the temptation will be to fix it in place and recompile. This will
not work -- their changes will be lost when they run the build script.
The developer must instead go to the original source file in
org/apache/derby/common and fix it there. I suspect this is going
to be confusing and annoying.
We could avoid this confusion by removing the generated source file
after compilation, but I think that this would be even more annoying,
as you wouldn't be able to do interactive source-level debugging. Most
debugging is just stepping through code that you aren't modifying; you
just want to follow the logic.
</ISSUE>
CHECKING IN A COMMON CLASS
You check in the original source, NOT the generated source.
<ISSUE>
This is another potential source of errors. A newbie developer
could check in the generated source, and we would have to clean
it out
</ISSUE>
RUNTIME WITH MIXED VERSIONS
If you have a 10.2 client and a 10.3 embedded driver in the same
VM, there is no conflict. The 10.2 client code uses the 10.2
client/common classes and the 10.3 embedded/engine code uses the
engine/common classes
Daniel John Debrunner wrote:
>Kathey Marsden wrote:
>
>
>
>
>>I liked your idea of adding just the needed classes to the existing
>>jars. The trick is to find a way to get Derby to always load the class
>>from the same jar file first, then no versioning is needed.
>>Suddenly, creating separate package namespaces for the common package
>>in the jars as last step of the jar build doesn't seem so weird to me.
>>
>>
>
>I've been thinking about suggesting that as well, e.g. the same code
>would be generated into two source java files in two (etc.) packages:
>
>org.apache.derby.engine.common
>org.apache.derby.client.common
>
>As I said in an earlier e-mail, you can share at many levels, a lot
>depends on why you are sharing? Is it to reduce development effort,
>reduce static/runtime footprint, add confusion for the user?
>
>
>
>>Obfuscators rename packages all the time and are widely accepted.
>>
>>
>
>And we already have generated code, so we handle that currently, ie. the
>java files from the parsers.
>
>
>
>>It could even happen as a special releasejar target so it wouldn't
>>confuse day to day development.
>>
>>
>
>I don't agree with this, a single build process is much better, it
>nmeans the normal development testing is in line with the released builds.
>
>
>Dan.
>
>
>
[david.vancouvering.vcf]
begin:vcard
fn:David W Van Couvering
n:Van Couvering;David W
org:Sun Microsystems, Inc.;Database Technology Group
email;internet:david.vancouvering@...
title:Senior Staff Software Engineer
tel;work:510-550-6819
tel;cell:510-684-7281
x-mozilla-html:TRUE
version:2.1
end:vcard