Directory Structure for java

A

Andy Dingley

I've worked this bit out:

<jar jarfile="${dist}/${ant.project.name}.jar">
<fileset dir="${build}"}/>
<fileset dir="resources" includes="**/*.jpg"/>
</jar>

Couple of hints:

* Ant coding practice (at least our local flavour of it) likes to be
verbose. Verbose and simple works when concise either doesn't, or even
worse it _might_ not (according to the phase of the moon). Ant's worst
problem is the non-obviousness of how it interprets things - you make
one tiny change, all hell breaks loose and it's really not obvious
why.

* Use properties throughout.

* Use structured names on these properties ${build.dir} and $
{component-foo.jar.file} etc. Yes, it's Hungarian notation through
the back door, but Ant doesn't have a useful type system so you're out
on your own here and need the help.

* Use location when setting (filesystem related) properties rather
than value. This is especially important if you're cross platform
Windows/Unix. Ruthlessly avoid putting hard-coded directory separators
into value properties, or at least use the system property $
{file.separator} if you do so.

* Split the build process down into small stages and keep them
separate. You might make .class files, then .jars, then .wars,
then .ears, finally a .zip for shipping. Rather then slapping
everything into dist, keep the sub-sections of build distinct in their
own sub-tres. Don't be afraid to "waste" effort copying tree fragments
around, conceptually simple and robust trumps "optimized" every time
with Ant.
 
A

Andy Dingley

What constructs are you talking about?

Reflection, factories (meaning very broadly as constructors wrapped
inside other methods).

f there's nothing in there except objects on the LHS and constructors
on the RHS of an expression (which is an awful lot of the world's more
simplistic Java code) then tracking dependencies isn't too hard at all.
 
A

Andy Dingley

Personally, I am using a few xterms with vim in it. Compilation goes
through maven. I have none of the fancy things such as [...]

Automated unit test?

More important, useful and productive than people who haven't worked
with it realise that it is.
 
L

Lew

Part of the maven machinery. Junit tests. There is a cvs server on
which code is committed, and a specialized build machine which
performs continuous integration (including running the tests,
producing the HTML from Javadoc, performing zillions of measures
and verifications of coding style, code complexity and so on...).

None of this has any relation with the IDE (or lack thereof) that I use
to write the code. The build machine accesses the cvs server. The cvs
server is filled with files. Whether the files were graphically
presented to my eyes through Eclipse, NetBeans, vim-in-xterm or whatever
else has no bearing on the cvs server and the build machine.

A very important benefit of this approach is that it keeps IDE-
specific artifacts such as Eclipse's .project files out of the build
and out of the repository trunk.

I've worked in places where they "standardized" the IDE, for example
to Rational Application Developer. They felt it was easier if all the
developers shared their project files, so those got checked in with
the source. Naturally, every developer winds up marking their project
files writable outside the version control's control, so that they
won't pollute the "standard" project files with their workstation-
specific tweaks. This did not alert project leadership to the
weakness of the approach. Nor did the six weeks of effort it took to
migrate the project files when they upgraded the IDE. Twice, within a
year. Then went back to a reduced version.

Project files can be managed on a repository branch. Given a project
"foo" I'll create, say, a branch "Lew.nb.odin" for NetBeans-specific
files that apply to workstation "odin", "Lew.eclipse.odin" for Eclipse-
specific files on that same workstation, "Lew.nb.freja" for NetBeans
project files that pertain to the working directories on workstation
"freja", and so forth. Developer Jo would substitute "Jo" for "Lew"
in those branch tags.

Naturally those branches are never merged with the trunk and do not
participate in builds.

Trunk files should appear as though edited only with vi or emacs and
contain no project-specific or workstation-specific artifacts.

Developers should be free to use whatever development environment
tools suit their work style best. Their work product should adhere to
standards, e.g., be devoid of warnings or errors when built by the
central build process. How they achieve that, be it by setting their
IDE to highlight those warnings or by running Ant at their
workstation, is tertiary at best.
 
T

Tom Anderson

Reflection,

I thought we were talking about tracking dependencies in which a change to
a depended-on class could break the depending class at *compile* time. I
don't think reflection can do that.
factories (meaning very broadly as constructors wrapped inside other
methods).

Nor do i see how that could.

Am i wrong about either of those?
f there's nothing in there except objects on the LHS and constructors on
the RHS of an expression (which is an awful lot of the world's more
simplistic Java code) then tracking dependencies isn't too hard at all.

As far as compilation is concerned, i think that's always the case.

Of course, all sorts of things can break at runtime, but that's why we
have tests!

tom
 
A

Andy Dingley

Part of the maven machinery. Junit tests.

You need them in the IDE too, running as fast as you lift your finger
from the keyboard.

Believe me, this works.
 
T

Tom Anderson

See Mike Schilling's example up-thread.

Do you mean the one where the constructor became private? That would
detected by source-based dependency analysis - A depends on B, so if the
interface to B changes, as it does, A needs to be recompiled.

Do try again, though.

tom
 
J

Joshua Cranmer

Mike said:
We must mean different things by circular dependencies. I mean two classes
(in C++, of course), each of which needs to know about the other.

I was referring to dependency between header files. Class circular
dependences are resolved by forward declarations.
 
M

Mike Schilling

Joshua said:
I was referring to dependency between header files. Class circular
dependences are resolved by forward declarations.

Consider the case where class A has a member of type B* (or B&) and class B
has a member of type A* (or A&). I do not want clients of A to need to
include b.h in addtion to a.h, and vice versa. Thus I'll include b.h in a.h
and vice versa, using the mechanism shown upthread (the correct version that
Andreas supplied.) Any code that analyzes header inclusion to generate
dependencies will need to be prepared for that sort of circularity.
 
J

Joshua Cranmer

Mike said:
Consider the case where class A has a member of type B* (or B&) and class B
has a member of type A* (or A&). I do not want clients of A to need to
include b.h in addtion to a.h, and vice versa. Thus I'll include b.h in a.h
and vice versa, using the mechanism shown upthread (the correct version that
Andreas supplied.) Any code that analyzes header inclusion to generate
dependencies will need to be prepared for that sort of circularity.

The standard form of dependency generation involves asking the compiler
to tell you which headers it needs. Since the includes would have to be
preprocessor-conditional, this is not a problem in practice.
 
M

Mike Schilling

Andy said:
See Mike Schilling's example up-thread.

Removing any member, whether it be field, method, or constructor,
would cause the same problem, I just used factories as one example.
 
T

Tom Anderson

Removing any member, whether it be field, method, or constructor, would
cause the same problem, I just used factories as one example.

But if you knew, from analysis of the source, that A depended on B, then
removing any member from B would trigger recompilation of A, and you'd
catch it.

Are we arguing at cross purposes here?

tom
 
A

Andreas Leitgeb

Mike Schilling said:
Consider the case where class A has a member of type B* (or B&) and class B
has a member of type A* (or A&).

That's where the separation between implementation and
prototypes (including class-declarations) comes in:

a.h:
class B; // forward declaration instead of including b.h
class A {
private: B* myB;
public:
B* getB() { return myB; }
void doSthgWithMyB(); // not implemented here, but in the .cpp
// constructor and/or setters that initialize/set myB
}
b.h: // exactly like a.h, but a<->b, A<->B swapped.

a.cpp:
#include "a.h"
#include "b.h"
void A::doSthgWithMyB() {
// use mebers of B, which is known due to inclusion of b.h
... myB->getA() ... ; // all fine
}
b.cpp: ditto

No cyclic inclusion necessary here.

If you wanted to do B's member-access in an inlined method
of A (thus in a.h) and vice versa in b.h, then you're in
trouble, and the cyclic-include trick will *NOT* help you
out of that trouble. Only non-inlining will.
 
M

Mike Schilling

Tom said:
But if you knew, from analysis of the source, that A depended on B,
then removing any member from B would trigger recompilation of A,
and
you'd catch it.

Are we arguing at cross purposes here?

Probably. My point (probably quite obsolete as the discussion has
progressed) is that this is a case where Ant's simpleminded "Recompile
Java files that have changed" loses. But as yiu say, there's nothing
special about factories or constructors.
 

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
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top