Re: Best Practices - common code
From: Rhino (rhino1_at_NOSPAM.sympatico.ca)
Date: Thu, 27 Jan 2005 15:20:21 -0500
"John C. Bollinger" <firstname.lastname@example.org> wrote in message
> Rhino wrote:
> > Let's say that we have a bunch of independent projects, among them Foo
> > Bar. Each of the projects has little to do with one another but they do
> > share some common code, things like certain standard GUI panels and some
> > frequently executed utility code. For example, all of the projects
> > an About panel via the same class and all of the projects use the same
> > to do various date manipulations. As a result, all of this common code
> > been organized into a Common project. Common is a rather large project
> > many classes.
> Java does not have "projects". Such a concept might be relevant to your
> programming environment, but not to the language. The closest analog in
> Java is probably "package", but the two may not be completely congruent.
Good point! Sorry, I am developing in Eclipse and I muddled up the question
by combinining Eclipse projects with Java packages.
> > When packaging project Foo, we know that it only needs a few of the
> > in Common, not all of the many classes found there. When packaging
> > Bar, we know it only needs a few of the classes in Common, and that some
> > them will be same as the Common classes needed by Foo and some will be
> > different.
> In that case, "Common" isn't really very common -- it's more
I see your point. "Common" isn't necessarily the best word to use for this
code but I couldn't think of anything else that gave the flavour I wanted.
My "Common" classes aren't necessarily things that *EVERY* program is going
to use but they represent some "reusable parts" that can (and are) used in
several different programs.
> My recommendation would be to break it up into smaller
> pieces that you don't object to distributing as indivisible units. The
> natural way of doing this would be to assign classes to packages so that
> you can break up the bulk along package or package family* lines.
> Technically, a Java package is little more than a namespace and access
> control domain for classes, but it is common practice to use packages to
> group classes into functional and/or distribution units.
> *Package family: a non-Java term by which I mean a collection of
> packages all having a common name prefix.
I've already broken my Common project into a variety of different packages
with names like this:
That's what you mean, right?
But in the case of project Foo, whose package names are mydomain.foo and
mydomain.foo.Resources, I only need some of the classes in
mydomain.common.utilities, not all of them. That's really the nub of my
question: should I be packaging all of mydomain.common.utilities when I only
need two of the dozen classes in it?
> > When it comes to packaging the Foo project for
> > which is the "best practice" in this case:
> > A. Distribute only the parts of Common that are needed by Foo?
> Depends on the structure of Common. If you subdivide it as I suggested
> then distributing only parts of Common would be natural. Note, however,
> that that doesn't necessarily mean distributing nothing but precisely
> those classes that Foo requires.
> > B. Distribute all of Common with Foo, even though most of it won't be
> > needed?
> If most of Common is not needed by Foo, then again, it's not very
> common. Break it up.
> > My strong inclination it to only do A for a variety of reasons:
> > a. less code to distribute: less space needed on CD -or- fewer files to
> > download and less bandwidth used
> Space on a CD is unlikely to be a real-world issue for the vast majority
> of cases. Downloading considerations, on the other hand, may be
> reasonable, depending on the actual sizes we're talking about.
> > b. slightly better performance of the application, assuming Jars are
> > used, since the classloaders won't need to inspect and ignore so many
> > that aren't being used
> If the size of the jars makes a noticeable difference then something is
> dreadfully wrong. This is in practice a non-issue.
Fair enough; I assumed that seek time for classes could be an issue in a
large jar but I have no idea how large a Jar would need to be in the real
world before you actually saw a performance degradation due to an
excessively large jar.
> > c. less code that can be reverse-engineered by competitors
> I guess you could argue that the hypothetical competitors keen on your
> technology would have to obtain multiple of your products to get their
> hands on all of "Common". If that makes a noticeable difference to your
> bottom line then you are small enough potatoes that your competitors
> either (a) for all intents and purposes don't exist or (b) are way out
> of your league.
I'll have to think about that one a bit more. I'm truly not sure how much
risk there is of competitors reverse-engineering code. I know that
obfuscators exist to make reverse-engineering more difficult but I don't
know how effective they actually are. Maybe the people who buy obfuscators
are just paranoid and the actual amount of reverse-engineering is
> > On the other hand, if I am selective about which parts of Common get
> > packaged, there is a fairly tedious process of figuring out precisely
> > classes in Common are needed by Foo. At least, it is fairly tedious to
> > since I only know how to do this mechanically: look at each 'import' and
> > 'implements' in each Foo class to determine which Common classes are
> > then look at each Common class to see what their dependencies are. If
> > knows a tool that will help me figure this out by simply clicking a
> > or filling out a dialog, I'd love to hear about it!
> You would have to do slightly more work than just click a button, but
> Ant can analyze class dependencies. Look at the ClassFileSet entity.
> Ant uses BCEL to perform that task, and it wouldn't be too hard to write
> your own tool for it if you didn't want to use Ant. I would expect that
> there are other possibilities, too; some may have a nice GUI.
I'm very fond of Ant but didn't realize it could analyze the dependencies. I
saw the acronymn BCEL in the docs but had no idea what it did or that it was
anything useful so thanks for telling me about it. I know that I could write
a tool that did that sort of analysis but I wasn't wild about re-inventing
the wheel when I was pretty sure there was some automated way of doing that
> On the other hand, if you reduce the scope of your problem by dividing
> up "Common" as I suggest, then you don't really need to worry much about
> it. Just jar up whole packages or package families and distribute them
> as units.
Based on what I've described above, would I be correct in understanding that
you are recommending that I incorporate all of the
'mydomain.common.utilities' package, even the classes that Foo doesn't need?
I'd be reluctant to incorporate all of the 'mydomain.common' package family
since much of it isn't used within Foo. I don't have as much of a problem
with distributing a few unneeded classes in 'mydomain.common.utilities'.
> Document package dependencies instead of individual class
> dependencies. Use a build and / or packaging tool for which you can
> prepare a static configuration file (e.g. Ant, most IDEs).
I assume that those two sentences represent indepedendent thoughts. What is
the best way of documenting package dependencies, Javadoc? What do you mean
by a 'static configuration file'? I don't recognize that term from Ant or
Eclipse so I'm not quite sure what you mean, what it would contain, or what
it would look like.
> > What experiences do the rest of you have with the question of common
> > Would you distribute all of Common or just the parts needed by Foo?
> Some of both. By subdividing the problem you can get some of the
> advantages of each approach while avoiding the worst problems of both.
That's what I expected. There are very few perfect solutions that don't
generate their own problems in turn ;-) I was just hoping to take advantage
of other people's experience to avoid the worst of the problems.