Aspect questions?

A

Arne Vajhøj

By the content of the message, duh.

The problem with using the logger to reflectively obtain the class and
method name is that the documentation claims it is a horrid performance
penalty, as you would know if you read the logger documentation.
As far as the cost of using the logger to elicit class and method
information, that probably won't matter as much as the documentation
claims. At level WARN[ING] and above, performance is probably not an
issue, and below that you usually have logging disabled, and performance
again is not an issue. When you do have DEBUG [FINE] enabled, you
probably aren't examining performance and again it doesn't matter. So I
tend to go ahead and use the logger to show class and method data.

Yep.

I think most actually do use the feature and live with its
consequences.

Arne
 
M

markspace

What does "interacts poorly with JEE classloaders" mean??


Did anybody read the link?

"Note that for application code, declaring the log member as "static" is
more efficient as one Log object is created per class, and is
recommended. However this is not safe to do for a class which may be
deployed via a "shared" classloader in a servlet or j2ee container or
similar environment. If the class may end up invoked with different
thread-context-classloader values set then the member must not be
declared static. The use of "static" should therefore be avoided in code
within any "library" type project. "
 
A

Arved Sandstrom

What does "interacts poorly with JEE classloaders" mean??

Arne
Probably this:

http://wiki.apache.org/commons/Logging/StaticLog

This is a page that's been out there for quite a few years.

As the blurb itself states, this is not a problem with your own code
that you're deploying as EARs. You can use static loggers in there all
you like. I've seen a number of long-running 24/7 J2EE/Java EE apps that
do just that, and they work fine, with perfectly independent logging,
because their own application classloaders take care of business.

AHS
 
A

Arne Vajhøj

Did anybody read the link?

"Note that for application code, declaring the log member as "static" is
more efficient as one Log object is created per class, and is
recommended.

But there is also just one Log object with a non-static ref??
However this is not safe to do for a class which may be
deployed via a "shared" classloader in a servlet or j2ee container or
similar environment. If the class may end up invoked with different
thread-context-classloader values set then the member must not be
declared static. The use of "static" should therefore be avoided in code
within any "library" type project. "

If the parent classloader of those classloaders is the
one that loads log4j, then you will end up with one
log object no matter what.

If log4j is loaded by those classloaders, then you will
end up with duplicate log objects no matter what you do.

So I still don't understand what the heck they are talking
about.

Arne
 
A

Arne Vajhøj

Probably this:

http://wiki.apache.org/commons/Logging/StaticLog

This is a page that's been out there for quite a few years.

As the blurb itself states, this is not a problem with your own code
that you're deploying as EARs. You can use static loggers in there all
you like. I've seen a number of long-running 24/7 J2EE/Java EE apps that
do just that, and they work fine, with perfectly independent logging,
because their own application classloaders take care of business.

I don't get it.

If log4j classes are loaded by the container classloader, then
the apps should share logging no matter whether the refs are
static or not.

Sure it can be a problem sharing logging.

But I can not see what static versus non static refs has
to do with that.

Arne
 
L

Lew

Arne said:
That is general question not specific to logging or AOP.

You need a good structure of your classes and source code.

A key factor in the decision between com.novice.common and
com.novice.common.xxxx must be the number of classes.

Do you have so many classes that it makes sense to split up?

That threshold would be one.

Every type should be in a package. Every type should be in its appropriate
package, irrespective of how many types (not just classes!) you have. A
model-view-presenter program could, and probably should, have three packages
with just the five or six types (including the three concrete classes but not
the test code, which would add more).
 
L

Lew

How about you summarize the answer for us, as a courtesy.

Please?
But there is also just one Log object with a non-static ref??


If the parent classloader of those classloaders is the
one that loads log4j, then you will end up with one
log object no matter what.

If log4j is loaded by those classloaders, then you will
end up with duplicate log objects no matter what you do.

So I still don't understand what the heck they are talking
about.

I'm with Arne on this one. How is having only one logger object per class more
efficient than having one logger object per class?

And you ignored Arne's question: 'What does "interacts poorly with JEE
classloaders" mean??'
 
N

Novice

Lew said:
The sentence began with "You don't...". I fail to see what can be
confusing there. An appositive phrase doesn't invert the sense of the
predicate.

Which leaves the question of how we got the miscommunication in the
first place, when I never suggested such a thing.
Okay, let's not flog this to death. I just want to figure this out, not
get into a detailed post mortem about what you meant and what I thought
you meant and all of that.

I've apparently jumped to some (several?) wrong conclusions. I admit
that. I'm trying to listen and work with what you're telling me but I'm
not quite getting things yet.

"Seemed" foists the responsibility off. I didn't do the "seeming".
Okay, it was all me then. Everything you've said has been crystal clear
and no reasonable human being could possibly misunderstand what you were
saying or implying.
...


I used the term in the exact same sense as the logging library
documentation and in computer programming generally.
Again, I've got some gaps in my education. Those are my fault, not yours.
I'm just trying to understand what you say. When I get confused, I echo
back to see if I've got things right. So far, I'm not doing too well.
Fair enough.
I have now. It doesn't help much though; I knew all of that stuff before.
Figuring out how to apply it to my situation is where I seem to be having
trouble.
Don't presume; design. It is very possible that the "Foo" project
will not have a package 'com.novice.foo', if it has
'com.novice.foo.qux', 'com.novice.foo.bleh' and so on.
Sure. Foo actually contains two programs, the main one which uses a file
to drive an application and a support program which simplifies the
editing of the file that drives the main program. Those could possibly be
in different packages within the same project, com.novice.foo.bart and
com.novice.foo.homer. But to my way of thinking, they are such close
cousins that they may just as well be in the same package.
No, it won't. First, you have completely ignored that I said "one
logger per class". How did you distort that into "one logger per
package"? Second, you don't design packages for the logger, you design
loggers for the packages.
Sorry, you're right. I muddled the two together.
Not yet.


STOP!

I don't know how you make these leaps, and I am defeated as to how to
advise you not to. You go on for paragraphs about bad ideas that were
never suggested to you.
Sorry, one mistake just leads to the next. Let me rephrase.

Assuming that project Foo has a single package, com.novice.foo and three
classes, hickory, dickory, and dock, class hickory's logger would be
"com.novice.foo.hickory", class dickory's logger would be
"com.novice.foo.dickory" and class dock's logger would be
"com.novice.foo.dock".

Is that right now?

Once again, I repeat, and you may recall the Javadoc quotes I provided
upthread on this matter, getting a logger with a particular name gets
a reference to that same-named logger. Already. Without additional
complication on your part. It's built in. You don't need to reinvent
it. It already happens. All you have to do is give the same name. You
will already have gotten the reference. You don't have to pass it
anywhere. It's already there. Read the Javadocs. Again. And again. And
again. And again. Don't read what isn't in there - read what it says.
It says that if you give the 'getLogger()' the same name, it will
return a reference to the same logger.

Yes, of course, you're absolutely right. I forgot that.
Aside from that, I have no idea at all what you intend to say by, "so
that they write to the logger used by the instantiating class from
Foo". What precisely do you mean there?
It doesn't really matter. In fact it's dumb; I still had the thought in
my brain that the main program was going to pass its logger to each class
that it instantiates it but it's not. Each class is going to be getting
it's own logger with

Logger logger Logger.getLogger(getClass().getName());
READ THE TUTORIAL!


It is better to group types into packages.
Yes, every class is already in one or another named package and has been
for a long time. I'm still struggling a bit over which classes belong in
the SAME package and which should not.

My thinking is that classes in the Common PROJECT should also be in
packages that are distinct from the packages used for Projects Foo or
Bar, which will have names like "com.novice.foo" and "com.novice.bar".

I think I want "com.novice.common" for the classes in the Common project
but I'm not sure if all classes in Common should be in the same package
or if it is better to group similar classes within the Common project
into distinct packages like "com.novice.common.lookups",
"com.novice.common.utilities", etc. etc. I'm not seeing a huge benefit to
separate packages although I'm using separate packages now so that
similar things are together. (That just feels like the right thing to do
but so far, most of my "feelings" have been wrong!)

Once again, as I stated upthread some time ago and others have
reiterated, the common practice (but by no means the only one) is one
logger per class.
Right. That is gradually sinking in, believe it or not! In fact, I'm just
about ready to replace all of the existing nonsense that I've been doing
with a

Logger logger = Logger.getLogger(getClass().getName());

in all my classes.
Loggers "inherit", so that gives some flexibility in how you do
things.


What? You should only have one log, unless they use different
libraries to log.
No. I'm strictly using java.util.logging for now. Arved's got me thinking
about this new one, slf4j, but I'm not ready to go there yet.

So I want to end up with all of my classes in all of my Projects writing
to a single log?

Hmm. Yes, I suppose that makes sense. I need to review the whole
"inherit" aspect of logging but I've been thinking of one logger equating
to one log and that's not right, is it? See, the penny is dropping....

Lots of loggers but only one log.... Yes, I need to get my head around
that and think of how that works. Maybe rereading that logging overview
will make that sink in....
Huh? again.

What you name the logger is not connected to where it logs. Where it
logs is determined by the configuration for that logger. Usually it'll
write to the same log as its parent. The best practice here is to make
sense in the first place. You ask a question about naming a logger,
but cast it in turns of where it logs. Apples and oranges, dude.
Naming a logger doesn't change where it logs. Read the logger
documentation, please. All this information is in the documentation.
Yes, that's starting to become clear now.
The configuration determines where the log goes. No changes to logger
names are needed, just change the configuration file and restart.

We're starting to make the same points over and over again. It's
frustrating to provide you an answer and have you come back with the
same question. Please assimilate the answers already given.
I'm sure it is frustrating for you and I'm sorry. But believe me, it is
massively frustrating for me too!
To summarize the repeated points here:

- Configuration files usually suffice to configure logging. You rarely
need to programmatically configure logging, and should resist doing
so. Otherwise you defeat the point of changing logging strategy
without having to rebuild.

- The logger name determines which logger instance you get. NOT, and I
repeat, *NOT* where it logs.

- Conventionally, and usually most usefully, loggers are named for the
class in which they are used. So the logger for
'com.lewscanon.example.Foo' would come via
'getLogger(com.lewscanon.example.Foo.class.getName())'.

and emergingly,

- Packages are to organize your program irrespective of logging
strategy.

Some of this is material in the basic tutorial, particular the info
about packages, and should be mastered first before, say, learning how
to code a for-each loop.


Your commitment is duly noted and quite laudable.

But "starting" is still a long way from "hash ... the last bits out".
So I hope your patience is up to the task. You lack certain Java
fundamentals.

I think we're a lot closer to putting this to bed now than we were a few
hours ago. In fact, I may be able to proceed on my own now.

The only thing that REALLY bugs me still is that I can't find the darned
log records containing the weekdays that I mentioned elsewhere in the
thread. They're NOT at %h/java%u.log nor at the other place suggested in
the Tracing and Logging document. And THAT is really driving me crazy. I
can't think of anywhere else to look based on anything I've seen in the
references you and others have given me. I _think_ the logging.properties
file is ensuring that a physical log file is being written but maybe it's
messed up in some way to keep it from writing at all. Or from righting
INFO level records. But I don't think that's it.

If you have any insight into that, you'd really be helping me out. It's
hard to absorb the information you are giving me when my mind keeps
obsessing on where the darned log files are.
 
A

Arne Vajhøj

That threshold would be one.

Every type should be in a package. Every type should be in its
appropriate package, irrespective of how many types (not just classes!)
you have. A model-view-presenter program could, and probably should,
have three packages with just the five or six types (including the three
concrete classes but not the test code, which would add more).

Nobody is suggesting classes should not be in package.

If there is a good package structure given by the design, then
that should be used.

But the question was about com.novice.common vs
com.novice.common.lookups + com.novice.common.utilities.

I would let the number of classes decide that one.

And the critical number is bigger than one.

Arne
 
N

Novice

That is general question not specific to logging or AOP.

You need a good structure of your classes and source code.

A key factor in the decision between com.novice.common and
com.novice.common.xxxx must be the number of classes.

Do you have so many classes that it makes sense to split up?


It should write to the file specified in the properties file.

May we see that?

It's not very different from the standard one. I've just tweaked it a
little bit. Here it is with the comments stripped out:

============================================================
handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

..level=INFO

java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter =
java.util.logging.SimpleFormatter

x.y.level = SEVERE
x.y.z.level = WARNING
org.sscce.level = WARNING
org.sscce.baz3.level = INFO

=========================================================================
I don't think the last four lines are going to do anything since I don't
believe I have any packages with those names. I think those are just
examples that I created when I first looked at logging a few years ago.

The code that I'm executing is:

==================================================================
package test;

import java.util.logging.Level;
import java.util.logging.Logger;

public class TestLogging {

public static void main(String[] args) {

@SuppressWarnings("unused")
TestLogging test = new TestLogging();
}

public TestLogging() {

Logger logger = Logger.getLogger("test");
logger.logp(Level.INFO, "myClass", "myMethod", "Monday");
logger.logp(Level.INFO, "myClass", "myMethod", "Tuesday");
logger.logp(Level.INFO, "myClass", "myMethod", "Wednesday");
logger.logp(Level.INFO, "myClass", "myMethod", "Thursday");
logger.logp(Level.INFO, "myClass", "myMethod", "Friday");
logger.logp(Level.INFO, "myClass", "myMethod", "Saturday");
logger.logp(Level.INFO, "myClass", "myMethod", "Sunday");
}
}
===================================================================

I'm running Windows XP so I know that %h is C:\Documents and Settings
\Novice. There are five log files there, java0.log through java4.log, but
none of them contain the days of the week or any log record that contain
today's date. So those logs are not getting written to that path.

I'm not sure if I'm doing something that is keeping them from being
written at all or if they are being written to somewhere else in the file
system. I don't _think_ I am suppressing them and I don't know where else
to look for them. The logs aren't where the docs say they should be....
 
N

Novice

@news.sunsite.dk:

[snip]

I forgot to answer this part of your post in my other reply.
That is general question not specific to logging or AOP.
You're absolutely right. This is a bit of a sidetrack. I think I need to
be sure I've structured my packages correctly in order to do a good job
with this.
You need a good structure of your classes and source code.
Agreed. I'm trying to figure out the best approach.
A key factor in the decision between com.novice.common and
com.novice.common.xxxx must be the number of classes.

Do you have so many classes that it makes sense to split up?
I'm not sure what "so many" means in this case ;-)

I actually split my Common project the other day into two parts. I left
only the code that I consider polished and (more or less) correct in
Common and moved all the stuff that is still crude and needs improving to
a new project called Common Candidate. The latter is far bigger!

But Common itself contains 9 classes in package com.novice.common, 8
classes in package com.novice.common.lookups, 3 classes in
com.novice.common.menus, 2 classes in com.novice.common.prefs, and 18
classes in com.novice.common.utilities.

The resource bundles for each package are in separate packages that have
Resources as the last qualifier, e.g.
com.novice.common.utilities.Resources. I have the impression, perhaps
mistaken, that resource bundles are supposed to be in different packages
than the classes they support.I don't remember where I got that; I think
it was a newsgroup post a few years ago but it could have been in one of
the online magazines....

I have no idea if this is a reasonable approach. Maybe this should all be
simplified so that all of those common classes and enums and resource
bundles are in one package together. Or just two, one for classes and
enums and the other for resource bundles.

Everything in the Common project is something I use regularly in various
projects or that I expect to use regularly.

The Commons Candidate project has quite a bit more code than the Common
project and is organized the same way with the same package names (and
maybe an additional package or two where none of the members are ready
for the Common project.) Some of the members of that project don't belong
there because they are just snippets that I've downloaded for learning
purposes or simple sandbox code where I'm trying something out. It needs
to be moved elsewhere but that's not a priority for me right now. But the
bulk of it has the potential to go to the Common project as something I'd
use regularly.

I'd like to start the process of doing things correctly with my current
project and Common so anything you can tell me about organizing things
would be appreciated.


[snip]
 
N

Novice

I'd say generally yes, unless you see a definite reason to put another
(set of) class(es) in a separate package. Example:

My common set forms the org.gregorie.environ package because I regard
these as setting an environment for the stuff I write. However, I also
do a bit of image manipulation and found I was writing repetitive
common code in this area, so that got refactored as classes in the
org.gregorie.image package. And so forth....

Any time you find this approach puts a class where you don't expect to
find it, consider changing your package structure. Its helpful if your
'common' package only contains classes that are likely to be useful
for any program you write (e.g logging and command line parsing) and
that your other packages contain classes that are often used together.
I've really struggled with this. I have things set up a certain way now
but I'm constantly second-guessing myself and wondering if its the best
way to do things.

For instance, I've got some utilities classes and I put them altogether
in a single package. But they are a mix of very different kinds of
utilities. Some deal with String manipulation, some with dates, some with
databases, etc. etc. Sometimes I wonder if I should take utilities that
deal with dates and group them with lookup classes that deal with dates
rather than group them on the basis of them being a utility or lookup.
After all "utility" is not something I could easily define in a
satisfying way and "lookup" is similarly unsatisfying.

Thanks for sharing your views on this, Martin!
 
L

Lew

Arne said:
Nobody is suggesting classes should not be in package.

If there is a good package structure given by the design, then
that should be used.

But the question was about com.novice.common vs
com.novice.common.lookups + com.novice.common.utilities.

I would let the number of classes decide that one.

And the critical number is bigger than one.

I disagree, with respect for your position.

Not that the number will be greater than one, but that it's a motivator for
the distinctions.

The difference between 'com.novice.common' and 'com.novice.common.lookups' and
'com.novice.common.utilities' should take no note of how many types (NOT just
classes!) would go in each package, but whether those in the first are merely
"common", those in the second are common to "lookups", and those in the third
are common "utilities".

If you have a hard time semantically distinguishing one package from another,
then you shouldn't have more than one package. Regardless of the number of
types in it.

A package is a namespace, not some finite-sized bucket that holds some
particular number range of items. Its purpose is to semantically group related
types together. What determines co-residence in a package is semantic
similarity, not quantity.
 
L

Lew

Novice said:
I actually split my Common project the other day into two parts. I left
only the code that I consider polished and (more or less) correct in
Common and moved all the stuff that is still crude and needs improving to
a new project called Common Candidate. The latter is far bigger!

But Common itself contains 9 classes in package com.novice.common, 8
classes in package com.novice.common.lookups, 3 classes in
com.novice.common.menus, 2 classes in com.novice.common.prefs, and 18
classes in com.novice.common.utilities.

The number isn't what's important. It's how related the types (not just
classes - you had better gosh-darned well have some interfaces in there!) It's
the relatedness of the types. Types in the same package are closely related to
each other. Those in different packages aren't. It's how related the types
should be that determines the designer's choice of which package holds them.
The resource bundles for each package are in separate packages that have
Resources as the last qualifier, e.g.
com.novice.common.utilities.Resources. I have the impression, perhaps

The usual (but not universal) convention is to name packages in all lower-case
with no underscores. That name looks like 'Resources' should be a type, not a
package name element.

Putting resources in a different package from the consuming type makes it
harder for the consumer to locate the resource, but it's not really wrong.
mistaken, that resource bundles are supposed to be in different packages
than the classes they support.I don't remember where I got that; I think
it was a newsgroup post a few years ago but it could have been in one of
the online magazines....

There's no real rule like that. You sure have a lot of vague, half- (not to
say mis-) remembered rules you try to live by without understanding.

Why don't you abandon all these rules and substitute thought about the
consequences of choices, and whether those consequences suit your purpose?
I have no idea if this is a reasonable approach. Maybe this should all be

You tell us. What are the consequences? Do you want those consequences?

I can tell you one. If you use something like 'Class#getResource[asStream]()'
you have to be more careful specifying the resource location with a resource
in a different package from the class represented by the instance making the
call. Not that that is bad, but it's a consequence.
simplified so that all of those common classes and enums and resource
bundles are in one package together. Or just two, one for classes and
enums and the other for resource bundles.

Why do you call that "simplified"? That seems like a recipe for an unholy mess.

Again, use the degree of relatedness to determine package co-residence.
Everything in the Common project is something I use regularly in various
projects or that I expect to use regularly.

The Commons Candidate project has quite a bit more code than the Common
project and is organized the same way with the same package names (and
maybe an additional package or two where none of the members are ready
for the Common project.) Some of the members of that project don't belong
there because they are just snippets that I've downloaded for learning
purposes or simple sandbox code where I'm trying something out. It needs
to be moved elsewhere but that's not a priority for me right now. But the
bulk of it has the potential to go to the Common project as something I'd
use regularly.

I'd like to start the process of doing things correctly with my current
project and Common so anything you can tell me about organizing things
would be appreciated.

Did you read the tutorial link?
 
L

Lew

Novice said:
Assuming that project Foo has a single package, com.novice.foo and three
classes, hickory, dickory, and dock, class hickory's logger would be
"com.novice.foo.hickory", class dickory's logger would be
"com.novice.foo.dickory" and class dock's logger would be
"com.novice.foo.dock".

Is that right now?

Yes.

Only do follow the naming conventions:

com.novice.foo.Hickory
com.novice.foo.Dickory
com.novice.foo.Dock

....
... Each class is going to be getting it's own logger with

Logger logger Logger.getLogger(getClass().getName());
....
Yes, every class is already in one or another named package and has been
for a long time. I'm still struggling a bit over which classes belong in
the SAME package and which should not.

As Patricia said, just make a decision and refactor later if you decide to.
My thinking is that classes in the Common PROJECT should also be in
packages that are distinct from the packages used for Projects Foo or
Bar, which will have names like "com.novice.foo" and "com.novice.bar".

Usually. You have to think of the consequences and decide if they're the
consequences you intend.
I'm using separate packages now so that
similar things are together. (That just feels like the right thing to do
but so far, most of my "feelings" have been wrong!)

It's the right thing to do. Now find a rationale why - there is one, since it
is the right thing to do. That way if pressed to explain your feeling you can.
Right. That is gradually sinking in, believe it or not! In fact, I'm just
about ready to replace all of the existing nonsense that I've been doing
with a

Logger logger = Logger.getLogger(getClass().getName());

in all my classes.

That's pretty much the idea I'm promoting, save for concerns of appropriate
scope as discussed upthread.
So I want to end up with all of my classes in all of my Projects writing
to a single log?
No.

Hmm. Yes, I suppose that makes sense. I need to review the whole
"inherit" aspect of logging but I've been thinking of one logger equating
to one log and that's not right, is it? See, the penny is dropping....

A logger is an object that writes to a log. There's no essential reason the
ratio should be one to one. Au contraire, just like everything else in Java
it's reasonable to expect multiple pointers to point to one thing and multiple
writers to write to one output.

Let me ask you this. In your favorite windowing OS, don't you have many
programs each of them writing to a screen? Don't they all write to the same
screen? You don't have a separate monitor for each program, do you?
Lots of loggers but only one log.... Yes, I need to get my head around
that and think of how that works. Maybe rereading that logging overview
will make that sink in....

Or thinking about many arrows hitting one target.

....
The only thing that REALLY bugs me still is that I can't find the darned
log records containing the weekdays that I mentioned elsewhere in the
thread. They're NOT at %h/java%u.log nor at the other place suggested in
the Tracing and Logging document. And THAT is really driving me crazy. I
can't think of anywhere else to look based on anything I've seen in the
references you and others have given me. I _think_ the logging.properties
file is ensuring that a physical log file is being written but maybe it's
messed up in some way to keep it from writing at all. Or from righting
INFO level records. But I don't think that's it.

If you have any insight into that, you'd really be helping me out. It's
hard to absorb the information you are giving me when my mind keeps
obsessing on where the darned log files are.

When I can't find a log file I'm searching for (it follows the rules for
finding resources via a classloader, btw), I do a variant of

$ find / -name foo.log 2> /dev/null

Have you not tried searching your hard drive?
 
A

Arved Sandstrom

I disagree, with respect for your position.

Not that the number will be greater than one, but that it's a motivator
for the distinctions.

The difference between 'com.novice.common' and
'com.novice.common.lookups' and 'com.novice.common.utilities' should
take no note of how many types (NOT just classes!) would go in each
package, but whether those in the first are merely "common", those in
the second are common to "lookups", and those in the third are common
"utilities".

If you have a hard time semantically distinguishing one package from
another, then you shouldn't have more than one package. Regardless of
the number of types in it.

A package is a namespace, not some finite-sized bucket that holds some
particular number range of items. Its purpose is to semantically group
related types together. What determines co-residence in a package is
semantic similarity, not quantity.
Agreed. It's hard not to agree, your position is that taken by all
credible documentation on Java packages.

AHS
 
A

Arved Sandstrom

I've really struggled with this. I have things set up a certain way now
but I'm constantly second-guessing myself and wondering if its the best
way to do things.

For instance, I've got some utilities classes and I put them altogether
in a single package. But they are a mix of very different kinds of
utilities. Some deal with String manipulation, some with dates, some with
databases, etc. etc. Sometimes I wonder if I should take utilities that
deal with dates and group them with lookup classes that deal with dates
rather than group them on the basis of them being a utility or lookup.
After all "utility" is not something I could easily define in a
satisfying way and "lookup" is similarly unsatisfying.

Thanks for sharing your views on this, Martin!
The general guideline for Java packages is that, as Lew has pointed out
several times, they contain classes of related functionality. Often a
"utils" type class is specific enough to classes in one of your packages
(or a sub-hierarchy of packages) that there is an obvious package to put
that *Util or *Utils class into.

But sometimes a "utils" type class doesn't relate closely to any single
package you have. In that case it sure doesn't offend most people's
sense of propriety to have a separate "util" or "utils" package at some
level (typically fairly high in your package tree, though). This can
actually be useful to quickly locate a "utils" class in large codebases
also, because it becomes a convention. Like Patricia said, don't beat
yourself up over decisions like this.

Another note on "utils" type classes. If they really are that general
purpose, consider developing them in an IDE as a separate project
containing that "util" or "utils" package. Ultimately they should be
providable to other work as a JAR.

AHS
 
N

Novice

Lew said:
The number isn't what's important. It's how related the types (not
just classes - you had better gosh-darned well have some interfaces in
there!) It's the relatedness of the types. Types in the same package
are closely related to each other. Those in different packages aren't.
It's how related the types should be that determines the designer's
choice of which package holds them.
Then I'm definitely bundling things incorrectly. The classes in my
package are not typically closely related. As for interfaces, I do have
some but now you've got me worried that I'm not using as many as I
should. It's entirely possible that I write classes when I should be
writing interfaces. Another beginner mistake brought on by the helter-
skelter way I've learned Java....

I really need to review some of the fundamentals! But then I suppose
we've already established that over the last few days....
The usual (but not universal) convention is to name packages in all
lower-case with no underscores. That name looks like 'Resources'
should be a type, not a package name element.
I'd like to clarify what you mean by "type". (And I'm not saying this is
a usage that you invented; I have seen it in other places.) I tend to
read "type" as a synonym for "class" but I'm getting the impression now
that you mean classes, enums, interfaces, etc. In other words, classes,
enums, and interfaces are _all_ types in the sense that you are using the
word. Is that right?

I've noticed that the Java Search in Eclipse lets you search for types,
packages, fields, methods and constructors but doesn't give you an option
for class (or enum). But if I select Type and look for a specific class
or enum or interface, it will find them.
Putting resources in a different package from the consuming type makes
it harder for the consumer to locate the resource, but it's not really
wrong.
I have no objection to putting the resources in the same packages as the
classes they are supporting. As I said, I was just doing something that I
saw recommended somewhere. And I may just have misinterpreted the intent
of that suggestion as I have other things. If there's no good reason to
keep the resources separate, I'm inclined to move them into the packages
of the classes they support.
There's no real rule like that. You sure have a lot of vague, half-
(not to say mis-) remembered rules you try to live by without
understanding.

Why don't you abandon all these rules and substitute thought about the
consequences of choices, and whether those consequences suit your
purpose?
That's an excellent suggestion and one I've been thinking of for some
time! It's just a matter of isolating which things need to be abandoned.
I don't want to throw out the baby with the bathwater....
I have no idea if this is a reasonable approach. Maybe this should
all be

You tell us. What are the consequences? Do you want those
consequences?

I can tell you one. If you use something like
'Class#getResource[asStream]()' you have to be more careful specifying
the resource location with a resource in a different package from the
class represented by the instance making the call. Not that that is
bad, but it's a consequence.
That's hardly the end of the world. I think I can cope with that. I wish
I could recall where I got the suggestion in the first place and why it
was seen as a good thing to do but I just don't recall.
Why do you call that "simplified"? That seems like a recipe for an
unholy mess.

Again, use the degree of relatedness to determine package
co-residence.
Makes sense to me, now that you say it. So I'm going to put things that
are frequently used together and not let other considerations enter into
it because they are unimportant. And resources are going to go in the
same package as their classes. There! I've just moved the stuff from the
"...Resources" packages to the packages that had the corresponding
classes and deleted the empty Resources packages.

As for the other packages in Common and CommonCandidate, I think the vast
majority are very soon going to be sitting in the same package,
com.novice.common since they are unrelated except that they are commonly
used. The vast majority are used independently, not together, so they
aren't really related. The few that are both related and common will get
their own packages. There! I've just put all the code in the Common
project into one big package. A small handful of types will get moved
again into separate packages as I figure out which ones really need that
treatment.

Did you read the tutorial link?

The one about packages? Yes. But I found it very vague. I didn't know if
the considerations I had were reasonable factors in grouping things
together or not. But if the key thing is relatedness and the number of
members in a package is irrelevant and I should not group all enums or
data classes into separate packages to recognize those similarities, then
things get a lot clearer. Since the various types are almost entirely
unrelated, the only reasonable thing to do is put them all in the same
package. I suppose I could put each type in its own distinct package to
emphasize it's distinctiveness from the others but that just seems dumb.
 
N

Novice

Novice wrote:
...

Are you designing an interface that will be expensive to change later?
No. I'm just trying to figure out the best way to group the code in my
Common project, the stuff that gets used by many of the other projects.
If not, my advice is to not second-guess yourself. If there is something
seriously wrong with how you have the code organized now, it will become
obvious during program maintenance. Refactor then.
I am chronic about second-guessing myself. I suppose I've never had a lot
of encouragement of the "you're brilliant" kind along the way ;-)
Especially if you have perfectionist tendencies, it is very easy to
spend far more time and energy thinking about decisions than they are
worth. I am very, very familiar with that problem. :)
At least you know what you're doing! I have perfectionist tendencies
without really being sure what I'm doing; try finding perfection when you
don't really have a clear picture of what it is! :)

I don't really see packages as that big a deal though. Whether I import
one or five to twenty-five in a given class doesn't seem that important
though. More packages probably makes the Javadocs more impressive looking
at first glance but if the underlying code doesn't make sense, then it's
all nonsense anyways....
 
N

Novice

The general guideline for Java packages is that, as Lew has pointed
out several times, they contain classes of related functionality.

Yes, I've been reading his remarks (and the rest of this big thread) and
digesting the advice.

I've basically grouped all of my Common project code into a single
package, com.novice.common, including all the resources. (A few select
items that are closely related will probably get moved again to their own
packages but I don't expect many of those.)
Often a "utils" type class is specific enough to classes in one of
your packages (or a sub-hierarchy of packages) that there is an
obvious package to put that *Util or *Utils class into.

But sometimes a "utils" type class doesn't relate closely to any
single package you have. In that case it sure doesn't offend most
people's sense of propriety to have a separate "util" or "utils"
package at some level (typically fairly high in your package tree,
though). This can actually be useful to quickly locate a "utils" class
in large codebases also, because it becomes a convention. Like
Patricia said, don't beat yourself up over decisions like this.
Agreed. As I said in my reply to her, I don't really see the packages
issue as being terribly important. The smaller packages are a bit more
convenient for finding things but that's about the only real advantage.
My new approach with everything in the Common project being in the same
package means that my com.novice.common now spans a page and a half in
the Eclipse Package Explorer but that's not that inconvenient. I may
change the Eclipse preferences to sort the list a bit differently so that
the resources for a class follow it rather than come at the end of the
list but that's no biggie.

Commons Candidate, which is my other project containing less polished
common code, is now seven pages long but i will be better once I move out
things that don't belong in there, like sandbox code or downloaded
fragments that I use to learn things.
Another note on "utils" type classes. If they really are that general
purpose, consider developing them in an IDE as a separate project
containing that "util" or "utils" package. Ultimately they should be
providable to other work as a JAR.
I'm not sure if my utils classes merit separate projects. They really
just provide convenience methods in most cases. I can't see any of them
becoming a standalone product of some kind. But I'll keep an open mind.
If I develop something that actual has promise as a standalone product,
I'll certainly put it in a separate project.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top