Aspect questions?

J

Jeff Higgins

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! :)

Look at other projects, lots of them.
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....
You need to develop your own sense of order and beauty, no one here can
give you one.
 
N

Novice

Lew said:
Yes.

Only do follow the naming conventions:

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

...

As Patricia said, just make a decision and refactor later if you
decide to.


Usually. You have to think of the consequences and decide if they're
the consequences you intend.


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.


That's pretty much the idea I'm promoting, save for concerns of
appropriate scope as discussed upthread.


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?
Of course not; all programs share the same monitor. (Or would share two
if I had a double-headed setup.)

Which is why I'm surprised to see you say "no" when I asked if all of my
classes in all of my projects should write to the same log. Your analogy
suggests that the loggers should all write to the same log. But I know
you wouldn't deliberately be that self-contradictory. So there's a subtle
distinction you're making that I'm not quite seeing....
Or thinking about many arrows hitting one target.
That works too.
...

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?
I certainly have. But it didn't turn up the missing log. I posted at
another place to get some more people involved and the person who replied
suggested I execute:

System.out.println(getClass().getClassLoader().getResource
("logging.properties"));

in my sandbox class. And that revealed something that surprised me: the
println() wrote "null". Clearly, and much to my surprise, my class isn't
seeing logging.properties and therefore isn't following its instructions.
That explains a lot!

My best guess is that it is seeing a different logging.properties file
than the one I want it to use but maybe it simply isn't seeing any
logging.properties at all and just defaulting in its behavior.

Now I need to figure out how to make it see the logging.properties file.
I need to do some googling to figure that out now. Or maybe ask in the
Eclipse forums if googling doesn't reveal the answer. Of course, if you
already know the answer, I wouldn't be adverse to hearing it ;-)

But I'm sure you've got your own work to do and I've already been a major
pain so I don't want to ask too much....
 
J

Jeff Higgins

Look at other projects, lots of them.

You need to develop your own sense of order and beauty, no one here can
give you one.

Look at the Eclipse API Specification:
<http://help.eclipse.org/indigo/topi...m.doc.isv/reference/api/overview-summary.html>
Do you find it orderly and beauteous? Why? Why not?

An exercise:
Write a package description and specification for each of the packages
in your project. Use the Eclipse API Specification as a template.

Package
org.eclipse.core.commands

Description
Application programming interfaces for commands and handlers.

Package Specification
This package provides API and implementation classes to define abstract
pieces of functionality. These pieces of functionality are intended to
provide a common way for plug-ins and the user interface to communicate
potential behaviour.

This package is designed so that its elements can be public and dynamic.
That is, elements in this package can appear and disappear over the life
of the application.

Package
org.eclipse.core.commands.common

Description
Application programming interfaces for common base classes.

Package Specification
This package provides some common base classes and exceptions that are
used in one or more packages elsewhere. Nothing in this package is
intended to be directly subclassed, or used. The code here only supports
code in other packages.

Package
org.eclipse.core.commands.contexts

Description
Application programming interfaces for contexts.

Package Specification
This package provides API and implementation classes to define abstract
representations of application state. These representations of
application state can be used as an abstraction of the event-listener
model -- where different sections of code do not (or cannot) refer to
each directly.

This package is designed so that its elements can be public and dynamic.
That is, elements in this package can appear and disappear over the life
of the application.

Package
org.eclipse.core.commands.operations

Description
Classes for the creation of undoable operations which can be added to an
operations history and later be undone and redone.

Package Specification
An undoable operation is a unit of work that can be executed, undone,
and redone. Operations can be added to an operation history so that they
can later be undone and redone according to the undo model for an
application. Operations may be assigned one or more undo contexts which
can be used to filter the available operations for undo or redo in the
operation history. Clients may choose to provide undo and redo function
for all operations in a history, or only for a particular undo context
in that history. Operation histories may be configured with an operation
approver so that applications can enforce any desired undo model, such
as strict linear (LIFO) undo. This package provides the definition and a
basic implementation for operations, undo contexts, histories, and
operation approvers.
 
J

Jeff Higgins

L

Lew

Novice said:
Then I'm definitely bundling things incorrectly. The classes in my
package are not typically closely related. As for interfaces, I do have

If you have a package called "miscellaneous", the types are related by virtue
of having no relationship to each other or anything else. "Related" is up to
you to define.
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
Relax.

writing interfaces. Another beginner mistake brought on by the helter-
skelter way I've learned Java....

Relax.

Interfaces are a promise. Classes are a way to keep that promise.

It's entirely possible to write a program without creating any new interfaces.

It's likely that any program you write will have some classes that do not
implement new custom interfaces.

Interfaces are a tool. You're panicking as a carpenter would were they
freaking out that they weren't using their ratchet wrench often enough.

To which I can only say, WTF?

Why don't you just learn what interfaces are and stop panicking?
I really need to review some of the fundamentals! But then I suppose
we've already established that over the last few days....

Interfaces are to specify and be clear what's supposed to happen. Consider the
Java standard 'java.util.List<E>' interface. It promises certain methods, such
as 'add(E element)', for example. It does not promise that the underlying
implementation will have an array, or fast insertion, or any other particular
about how it does the 'add()', only that it can and will do it.

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?

First of all, enums *are* classes!

Second, for God's sake, man! Use a search engine once in a while!
<http://lmgtfy.com/?q=what+is+a+type+in+computer+programming>

Types are anything that classify a variable to the compiler, so yes,
interfaces and classes. Also primitive types. Also arrays.

Any classification of a variable. This is a very fundamental concept to
computer programming, and present in every computer language in one way or
another. "Type" is right up there with "operator" and "variable", "literal",
"integer".

I really wish you'd read the tutorial:
<http://docs.oracle.com/javase/tutorial/java/nutsandbolts/index.html>
"... basic data types (primitive types, character strings, and arrays), ..."

<http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html>
"The Java programming language is statically-typed, which means that all
variables must first be declared before they can be used. This involves
stating the variable's type and name, ..."
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.

Because those are types, so your reasoning is sound to this degree.
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.

If you saw a recommendation somewhere to jump off a bridge, would you "just do
it"?
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....

Abandon all the rules. Well, abandon all the rules you don't completely
understand.

Do what makes your desired outcome happen. Rules exist to make that easier.
Follow whatever rules make your desired outcome happen with the least hassle
to your customer.
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.

Because you can't recall the source or rationale for the rule, don't
understand the rule, and perhaps don't even recall the rule accurately, you
should not follow that rule. The policy of following ritual mumbo-jumbo from
half-remembered sources in a way not intended by the original promulgator of
that ritual mumbo-jumbo is that old, surefire path to failure known as
"cargo-cult programming".

....
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.


That sounds valid.
 
L

Lew

Of course not; all programs share the same monitor. (Or would share two
if I had a double-headed setup.)

Which is why I'm surprised to see you say "no" when I asked if all of my
classes in all of my projects should write to the same log. Your analogy

All of your projects writing to the same log is like everyone's computer
sharing one screen.

Is there only one computer screen in the world that we all share for our projects?
suggests that the loggers should all write to the same log. But I know
you wouldn't deliberately be that self-contradictory. So there's a subtle
distinction you're making that I'm not quite seeing....

It's not subtle, that is, unless you consider a piano falling on your head subtle.
That works too.

Are there not many targets at the archery range?
in my sandbox class. And that revealed something that surprised me: the
println() wrote "null". Clearly, and much to my surprise, my class isn't
seeing logging.properties and therefore isn't following its instructions.
That explains a lot!

My best guess is that it is seeing a different logging.properties file
than the one I want it to use but maybe it simply isn't seeing any
logging.properties at all and just defaulting in its behavior.

Now I need to figure out how to make it see the logging.properties file.

Put it in the place in the classpath that matches the location specified in
the 'getResource()', use a "-D" parameter to the "java" command as suggested
upthread, study the Javadocs for 'getResource[AsStream]()'.
 
N

Novice

Lew said:
If you have a package called "miscellaneous", the types are related by
virtue of having no relationship to each other or anything else.
"Related" is up to you to define.


Relax.

Interfaces are a promise. Classes are a way to keep that promise.

It's entirely possible to write a program without creating any new
interfaces.

It's likely that any program you write will have some classes that do
not implement new custom interfaces.

Interfaces are a tool. You're panicking as a carpenter would were they
freaking out that they weren't using their ratchet wrench often
enough.

To which I can only say, WTF?

Why don't you just learn what interfaces are and stop panicking?
I wasn't panicking; I was just wondering if I needed to add that to my
"to do" list of things to re-learn. Which is basically what you're
suggesting I do. :)

Interfaces are to specify and be clear what's supposed to happen.
Consider the Java standard 'java.util.List<E>' interface. It promises
certain methods, such as 'add(E element)', for example. It does not
promise that the underlying implementation will have an array, or fast
insertion, or any other particular about how it does the 'add()', only
that it can and will do it.

Implementations of 'List<E>' include 'ArrayList<E>' and 'TreeList<E>'.
Why don't you take a break and read the Javadocs for these three
types?
I've got interface List<E> and class ArrayList<E> (which implements List
<E> among other interfaces) but I don't have TreeList<E>. I mostly still
use the Java 1.6 API but even the Java 1.7 API doesn't have a TreeList.
What did you mean to say? And what do you want me to learn? I'm guessing
you want me to see how a class makes use of an Interface but possibly you
have something more specific in mind?
First of all, enums *are* classes!
Okay, I had forgotten that. Eclipse has a separate dialog for creating an
enum so it makes it feel as if it ISN'T a class but a whole different
animal.
Second, for God's sake, man! Use a search engine once in a while!
<http://lmgtfy.com/?q=what+is+a+type+in+computer+programming>
Sorry. I'm not as lazy as you think. It's just that I feel like we're
having a conversation in (almost) real time. I wouldn't tell someone to
go off to look something up in a dictionary in a real time conversation;
I'd just ask them what they meant. It's now clear to me that you don't
view it that way; more like a student coming to a lesson and being given
homework. Okay, I can do that too.
Types are anything that classify a variable to the compiler, so yes,
interfaces and classes. Also primitive types. Also arrays.

Any classification of a variable. This is a very fundamental concept
to computer programming, and present in every computer language in one
way or another. "Type" is right up there with "operator" and
"variable", "literal", "integer".
Java is something like my 10th programming language and I don't remember
seeing 'type' as standard terminology in any of the others. Forgive my
ignorance....
I really wish you'd read the tutorial:
<http://docs.oracle.com/javase/tutorial/java/nutsandbolts/index.html>
"... basic data types (primitive types, character strings, and
arrays), ..."

<http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.htm
l> "The Java programming language is statically-typed, which means
that all variables must first be declared before they can be used.
This involves stating the variable's type and name, ..."
You've made your point, Again, sorry.
Because those are types, so your reasoning is sound to this degree.


If you saw a recommendation somewhere to jump off a bridge, would you
"just do it"?
No, of course not. But if you're suggesting that I'm a little too quick
to take advice without thinking through just whether it is the right
thing to do, then yes, I'm probably guilty of that sometimes. I will work
on that.
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....

Abandon all the rules. Well, abandon all the rules you don't
completely understand.

Do what makes your desired outcome happen. Rules exist to make that
easier. Follow whatever rules make your desired outcome happen with
the least hassle to your customer.
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.

Because you can't recall the source or rationale for the rule, don't
understand the rule, and perhaps don't even recall the rule
accurately, you should not follow that rule. The policy of following
ritual mumbo-jumbo from half-remembered sources in a way not intended
by the original promulgator of that ritual mumbo-jumbo is that old,
surefire path to failure known as "cargo-cult programming".
Agreed. Which is the why I'm asking some of these questions now.
 
N

Novice

I think brilliance is overrated, so I would not worry about whether
you have it or not. I know brilliant people who have achieved little
or nothing. Besides, you can't choose to be brilliant.
Very good points, especially the last one. We have to work with what we
have, not with what we wish we had!
You can choose, and apparently have chosen, to ask questions, read and
try to understand the answers, and apply the answers in your own
programming. That will take you a long way. The very fact that you do
care about style and organization will help you program well.
I sure hope that's true. In the absence of brilliance, I have to make do
with slogging away, just like 99.99% of the human race.... :)

Thanks for the encouragement, Patricia!
 
J

Jeff Higgins

An exercise:
Write a package description and specification for each of the packages
in your project. Use the Eclipse API Specification as a template.

Another exercise:
Think of a new software product.
Describe the product and it's features.
Think about the implementation of the product.
What major subsystems does it incorporate.
Think about the implementation of each subsystem.
What types does it handle,
what behaviors does it provide,
how does it interact with other subsystems?
Open a new Eclipse project.
Add appropriate packages to your project.
Add appropriate types and interfaces to the packages.
Add appropriate methods to your types and interfaces.
Do not implement any of the functionality,
only declarations and javadoc comments.
Run the javadoc tool over your project,
and save the resulting project javadoc somewhere.
Delete the project and forget it for a couple of months.
After that time give the project javadoc to a friend
and ask him if he thinks that he can implement your
product from this complete specification.
Could you?
 
N

Novice

Look at the Eclipse API Specification:
<http://help.eclipse.org/indigo/topic/org.eclipse.platform.doc.isv/refe
rence/api/overview-summary.html> Do you find it orderly and beauteous?
Why? Why not?
You do mean these questions and your proposed exercise rhetorically,
right? I'm willing to actually do them if it would help me do a better
job but I'm inclined to think that you don't mean that you literally want
me to do this right in the newsgroup. Correct me if I'm wrong. (I'm
speaking about the suggestions in your follow-on posts too.)

Don't get me wrong, they actually look like good ideas!
 
M

Martin Gregorie

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.
In that case, leave the package structure as it is unless you find
problems with it. In fact I'd go so far as to say don't subdivide it into
separate packages unless there's a really good reason for doing so. Once
you've written a few programs, particularly if most of the classes in
them require access to at least one of your common classes it becomes a
real pain to repartition them between packages because doing so will cost
significant effort to go through all your application classes and
adjusting their 'import' statements.

Most common classes tend to be quite small and you probably won't have
all that many of them: my collection has evolved over the last 10 years
and stand at 21 classes which contain 5800 lines of source including the
Javadocs documentation comments, so the collection would have to grow by
at least 50% before I'd consider splitting up that package.

This number of classes hasn't changed for a while now, though some
classes may gain a method or two as I find extra things I need them to
do. For example my logging class has methods corresponding to 'info' and
'error' logging levels but there is no method equivalent to a 'warning'
logging level. However, it is something I may need some day because
calling error() causes the program to stop after dumping the circular
trace buffer (if its enabled) but there is currently no way of dumping
the buffer and letting the run continue. This is something a warn()
method might do if I find a need for it.
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.
So are mine, which range from my logging class to a pair of classes that
handle the client and server ends of a message oriented socket connection
via a command line parsing class and a class for calculating and checking
numeric identifiers that use Luhn check digits.
 
N

Novice

Lew said:
All of your projects writing to the same log is like everyone's
computer sharing one screen.

Is there only one computer screen in the world that we all share for
our projects?
Of course not.
It's not subtle, that is, unless you consider a piano falling on your
head subtle.
That's not subtle at all in my book ;-)

But then assuming we're agreed that all of _my_ classes should NOT write to
the same log - let alone every class in the world! - what is the proper
scope of a log. I could be persuaded that each application should write its
own distinct log, although I'm not sure we'd have the same definition of
application in mind. A better scope for logs would probably be all the
applications that belong to system X, where X might be the company's
payroll system, consisting of many applications and hundreds of classes.
What is your view of what the scope should be?
Are there not many targets at the archery range?
I'm not an archer but I seem to remember seeing archery ranges on TV shows
that had several targets....
Put it in the place in the classpath that matches the location
specified in the 'getResource()', use a "-D" parameter to the "java"
command as suggested upthread,

I just spent half an hour looking for that post and I cannot find it. I
skimmed each and every post in the thread and did not find it. I located a
find command in my news reader, whose scope is limited to a single post at
a time, and used it in every post in the thread. Still nothing. I went into
Google groups and searched it there with the browser's find command and
still nothing. I know it was there because I remember seeing it but I can't
find it now. Can you possibly remind me what I was supposed to do?
study the Javadocs for
'getResource[AsStream]()'.

Do I actually need to open the logging.properties file and read it, as if
it were a routine text file, to find the desired log path? That seems
improbable....

For what it's worth, someone else told me to add it to the classpath for
the project so I went into Run Configurations, chose the Classpath tab and
added the folder containing logging.properties under "User Entries". I also
deleted my old java%u.log files because I'm sick of looking at them and
finding that no new java.log has joined them and none of the old ones has
changed. I ran the sandbox program again and the println() displayed the
path to the logging.properties file. The INFO, SEVERE, and WARNING messages
got displayed on the console, just as they did before I made the
logging.properties visible. But there is STILL NO LOG FILE in the
%h directory!

This is really getting annoying. I really want to play with logging now
that I have a better grasp on it and I can't find the bloody thing for love
or money....
 
L

Lew

Oops, I got the standard API and the Apache Commons Collections API mixed up.
Sorry.
I've got interface List<E> and class ArrayList<E> (which implements List
<E> among other interfaces) but I don't have TreeList<E>. I mostly still
use the Java 1.6 API but even the Java 1.7 API doesn't have a TreeList.
What did you mean to say? And what do you want me to learn? I'm guessing
you want me to see how a class makes use of an Interface but possibly you
have something more specific in mind?

No, I made a mistake. There is such a thing but I didn't really mean to
recommend something outside the standard API.

But if you ever do want 'TreeList', here's what I was misremembering:
<http://commons.apache.org/collections/api-release/org/apache/commons/collections/list/TreeList.html>

Commons Collections is a very popular package that aims to expand and augment
the standard Collections API.
 
L

Lew

Novice said:
But then assuming we're agreed that all of _my_ classes should NOT write to
the same log - let alone every class in the world! - what is the proper
scope of a log. I could be persuaded that each application should write its
own distinct log, although I'm not sure we'd have the same definition of
application in mind. A better scope for logs would probably be all the
applications that belong to system X, where X might be the company's
payroll system, consisting of many applications and hundreds of classes.
What is your view of what the scope should be?

You do ask very good questions.

Each program should have its own log. I don't know what you mean when you say
"project", but conventionally a project is tied to one specific program or
application.
I'm not an archer but I seem to remember seeing archery ranges on TV shows
that had several targets....

And as there is a different target for each archer, there should be a
different log for each program.

Really, I've already given you the advice you need to answer your own
question. I told you to design logs to benefit people who need them to
troubleshoot.

How will it help an operations engineer or reliability engineer to have to
sift through dozens of applications' output to find what they need? It's bad
enough to sift through one application's log, especially the way most
programmers fail to think through their logging output.
I just spent half an hour looking for that post and I cannot find it. I
skimmed each and every post in the thread and did not find it. I located a
find command in my news reader, whose scope is limited to a single post at
a time, and used it in every post in the thread. Still nothing. I went into
Google groups and searched it there with the browser's find command and
still nothing. I know it was there because I remember seeing it but I can't
find it now. Can you possibly remind me what I was supposed to do?

I must have remembered this wrong. I coulda sworn someone suggested to use the
"-D" option per
<http://docs.oracle.com/javase/7/docs/technotes/guides/logging/overview.html>
which in the section entitled "Configuration File"
<http://docs.oracle.com/javase/7/docs/technotes/guides/logging/overview.html#a1.8>
points you to "See the LogManager API Specification for details."
<http://docs.oracle.com/javase/7/docs/api/java/util/logging/LogManager.html>
where it tells you

«In addition, the LogManager uses two optional system properties that allow
more control over reading the initial configuration:

"java.util.logging.config.class"
"java.util.logging.config.file"
These two properties may be set via the Preferences API, or as command line
property definitions to the "java" command, or as system property definitions
passed to JNI_CreateJavaVM.»

I don't have these link chains memorized, dude. I'm literally reading the
documentation on your behalf and reporting what I discover.

There's only so far you can get as a programmer asking others to read the
documentation for you.
study the Javadocs for
'getResource[AsStream]()'.

Do I actually need to open the logging.properties file and read it, as if
it were a routine text file, to find the desired log path? That seems
improbable....

I'm only suggesting you study those Javadocs to understand how the system
searches for resources.
For what it's worth, someone else told me to add it to the classpath for
the project so I went into Run Configurations, chose the Classpath tab and
added the folder containing logging.properties under "User Entries". I also

Umm - cargo cult.
deleted my old java%u.log files because I'm sick of looking at them and
finding that no new java.log has joined them and none of the old ones has
changed. I ran the sandbox program again and the println() displayed the
path to the logging.properties file. The INFO, SEVERE, and WARNING messages
got displayed on the console, just as they did before I made the
logging.properties visible. But there is STILL NO LOG FILE in the
%h directory!

This is really getting annoying. I really want to play with logging now
that I have a better grasp on it and I can't find the bloody thing for love
or money....

Didn't someone already ask you to share your logging.properties file with us?
Have you done so?

Regardless, you are asking questions now that the documentation answers. I
have read the documentation for you and reported what I found, to a degree.

So will your next post be another request to read the documentation for you?
 
A

Arved Sandstrom

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
I must admit, Arne, you've got a point. I'd read that commons logging
piece some years back, not too critically I see, and never thought twice
about it. Like I mentioned above, the uses of static loggers I've seen
or employed myself have not caused problems, so I figured whatever they
were talking about was something I might run across at some point, with
3rd party JARS in a shared library configuration, and recognize it if I
saw it.

I just now set up a test case using oc4j 10.1.3.5, where I created a
shared library with a JAR containing a couple of classes with log4j
loggers, one with a static Logger, one with an instance Logger.

This shared library is referenced at runtime by 2 servlets in 2 separate
web apps. Each web app has a slightly different log4j.xml, one allows
the library log statements, one is at a level that filters them out.

I tweaked the code in between various server restarts to ensure that
only the static Logger *or* the instance Logger was in use.

There was no difference between the two. We observe the expected
_undesirable_ behaviour, which is that whichever servlet is hit first,
it's the logging configuration for that web app which is used for both
web apps. *But* regardless of which Logger is in use, static or
instance, we get the same undesirable behaviour.

So I agree with you, after rigorous experimentation. :) It's nice of
the commons logging folks to point out the hazards of shared loggers;
it's considerably less clear why they thought shared static vs. shared
instance was important.

AHS
 
N

Novice

In that case, leave the package structure as it is unless you find
problems with it. In fact I'd go so far as to say don't subdivide it
into separate packages unless there's a really good reason for doing
so. Once you've written a few programs, particularly if most of the
classes in them require access to at least one of your common classes
it becomes a real pain to repartition them between packages because
doing so will cost significant effort to go through all your
application classes and adjusting their 'import' statements.

Most common classes tend to be quite small and you probably won't have
all that many of them: my collection has evolved over the last 10
years and stand at 21 classes which contain 5800 lines of source
including the Javadocs documentation comments, so the collection would
have to grow by at least 50% before I'd consider splitting up that
package.
I'm surprised that your common class is so small in terms of number of
classes, especially after 10 years! I would have thought you'd have
written many more by now....

I've got 40 classes in mine already and those are just the ones I
consider more-or-less finished. I've got many more in my CommonCandidates
project where I store the ones that are still just half-baked (or
less!).I'm regularly thinking of new ones to add....

Of course some of mine are pretty trivial, like enums that only have two
constants in them. I'm not sure how many lines of code they comprise; I
don't know a quick way to add them up and don't quite feel like manually
opening each, counting the lines and adding them up. I very much doubt
mine comprise as many lines as yours. So mine are probably dramatically
shorter than yours and probably do far less. Yours average almost 3000
lines; DateTimeUtils, which must be my longest, is only 1300 lines long.
It has 31 methods but most of them are quite short.

But quantity is irrelevant in any case. I'm sure yours are far higher in
quality than mine!
This number of classes hasn't changed for a while now, though some
classes may gain a method or two as I find extra things I need them to
do. For example my logging class has methods corresponding to 'info'
and 'error' logging levels but there is no method equivalent to a
'warning' logging level. However, it is something I may need some day
because calling error() causes the program to stop after dumping the
circular trace buffer (if its enabled) but there is currently no way
of dumping the buffer and letting the run continue. This is something
a warn() method might do if I find a need for it.
Well, there's not much point in building it until you find you need it.
It sounds like you're doing well enough without it for now.
So are mine, which range from my logging class to a pair of classes
that handle the client and server ends of a message oriented socket
connection via a command line parsing class and a class for
calculating and checking numeric identifiers that use Luhn check
digits.
Today, I decide to keep everything in my Common class in a single
package. After discussing the merits of splitting them out into different
packages, I realized there just wasn't any benefit to it aside from being
able to see the whole list of elements in the package on a single page.
And that didn't seem important at all. We'll see how this goes.

If it turns out to be a problem, I'll split them out again on some
reasonable basis. I'm using Eclipse so creating packages and moving
things to and from packages is a breeze; it does all the hard work of
renaming things for you.
 
A

Arne Vajhøj

Of course not; all programs share the same monitor. (Or would share two
if I had a double-headed setup.)

Which is why I'm surprised to see you say "no" when I asked if all of my
classes in all of my projects should write to the same log. Your analogy
suggests that the loggers should all write to the same log. But I know
you wouldn't deliberately be that self-contradictory. So there's a subtle
distinction you're making that I'm not quite seeing....

Typical:
- one logger instance per class
- one log file per app

Note that configuration of log files and other destinations for
logging should not be in the code but in the log config file.

Arne
 
A

Arne Vajhøj

I must admit, Arne, you've got a point. I'd read that commons logging
piece some years back, not too critically I see, and never thought twice
about it. Like I mentioned above, the uses of static loggers I've seen
or employed myself have not caused problems, so I figured whatever they
were talking about was something I might run across at some point, with
3rd party JARS in a shared library configuration, and recognize it if I
saw it.

I just now set up a test case using oc4j 10.1.3.5, where I created a
shared library with a JAR containing a couple of classes with log4j
loggers, one with a static Logger, one with an instance Logger.

This shared library is referenced at runtime by 2 servlets in 2 separate
web apps. Each web app has a slightly different log4j.xml, one allows
the library log statements, one is at a level that filters them out.

I tweaked the code in between various server restarts to ensure that
only the static Logger *or* the instance Logger was in use.

There was no difference between the two. We observe the expected
_undesirable_ behaviour, which is that whichever servlet is hit first,
it's the logging configuration for that web app which is used for both
web apps. *But* regardless of which Logger is in use, static or
instance, we get the same undesirable behaviour.

So I agree with you, after rigorous experimentation. :) It's nice of
the commons logging folks to point out the hazards of shared loggers;
it's considerably less clear why they thought shared static vs. shared
instance was important.

I think it happens frequently. Someone claims X without investigating
too much. Because X really does not have much practical impact, then
nobody else checks the claim. Instead it get quoted by someone and
another quote that. And suddenly we have an "accepted fact" that
nobody remembers where it originally came from.

Arne
 

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