From: Mike Schilling on
Lew wrote:
> Mike Schilling wrote:
>> "The most obvious example of these limitations is that the task
>> can't tell which classes to recompile when a constant primitive data
>> type exported by other classes is changed. For example, a change in
>> the definition of something like
>> public final class Constants {
>> public final static boolean DEBUG=false;
>> }
>>
>> will not be picked up by other classes. "
>>
>> That is, it's an incremental (no pun intended) improvement on the
>> usual Ant algorithm of "recompile what onviouslt needs
>> recompilation; if that doesn't seem to work, do a clean build"
>
> You can't blame Ant for that one.

True; it's the design of Java that doesn't lend itself to calculating
dependencies with a reasonable amount of effort.

> The class that depends on the
> compile-time constant, such as 'DEBUG' in your example, compiles the
> constant into its class, not the symbol. Without some external
> indication of the dependency, there's not any way for a compiler or
> build tool to detect that it exists.

Other than by noting it when the symbol is used during compilation, and
storing that bit of information somewhere. But the details of that get
messy.

>
> With respect to dependencies where the symbol is stored in the class
> rather than its value, even 'javac' handles the situation pretty well.

There are other difficult cases, like a method being added in class A that
results in a method in B (one of A's descendents) becoming overloaded, such
that a client of B should now choose the new overload. Java really makes
this stuff hard. (C# is no better.)


From: Lew on
Lew wrote:
>> The class that depends on the
>> compile-time constant, such as 'DEBUG' in your example, compiles the
>> constant into its class, not the symbol. Without some external
>> indication of the dependency, there's not any way for a compiler or
>> build tool to detect that it exists.

Mike Schilling wrote:
> Other than by noting it when the symbol is used during compilation, and
> storing that bit of information somewhere. But the details of that get
> messy.

I said that there is no way, not that there couldn't be a way.

Lew wrote:
>> With respect to dependencies where the symbol is stored in the class
>> rather than its value, even 'javac' handles the situation pretty well.

Mike Schilling wrote:
> There are other difficult cases, like a method being added in class A that
> results in a method in B (one of A's descendents) becoming overloaded, such
> that a client of B should now choose the new overload. Java really makes
> this stuff hard. (C# is no better.)

How would any language handle this?

Short of a class being aware of every possible past, present and future
extension of it.

You do present a good argument against overuse of inheritance.

--
Lew
From: markspace on
Lew wrote:
>
> How would any language handle this?

Class A exports a method:

public class A {
public void m( Object o ) {}
}

which B uses:

public class B {
public void b(A a) { a.m( "Hello" ) }
}

Now B has a dependency on A. If A changes, for any reason:

public class A {
public void m( Object o ) {}
public void m( String s ) {}
}

or:

public class A {
public void x( Object o ) {}
}


then B has to recompiled. That's pretty standard stuff I think. There
really isn't any need to detect an overloaded method, this simple
dependency graph catches it, and many other cases too.



From: Mike Schilling on
Lew wrote:
> Lew wrote:
>>> The class that depends on the
>>> compile-time constant, such as 'DEBUG' in your example, compiles the
>>> constant into its class, not the symbol. Without some external
>>> indication of the dependency, there's not any way for a compiler or
>>> build tool to detect that it exists.
>
> Mike Schilling wrote:
>> Other than by noting it when the symbol is used during compilation,
>> and storing that bit of information somewhere. But the details of
>> that get messy.
>
> I said that there is no way, not that there couldn't be a way.
>
> Lew wrote:
>>> With respect to dependencies where the symbol is stored in the class
>>> rather than its value, even 'javac' handles the situation pretty
>>> well.
>
> Mike Schilling wrote:
>> There are other difficult cases, like a method being added in class
>> A that results in a method in B (one of A's descendents) becoming
>> overloaded, such that a client of B should now choose the new
>> overload. Java really makes this stuff hard. (C# is no better.)
>
> How would any language handle this?

Languages that store the defintion of a class in a different file than its
implementation (e.g. C++) handle it by simple comparisons of file dates.
It's also possible to do this by having the compiler update a repository of
class definitions (I used to develop a system that did just that.)

>
> Short of a class being aware of every possible past, present and
> future extension of it.

You'd need to do it the other way around -- have the client of B ask B if
its definition had changed, and have B in turn ask A.


From: Mike Schilling on
markspace wrote:
> Lew wrote:
>>
>> How would any language handle this?
>
> Class A exports a method:
>
> public class A {
> public void m( Object o ) {}
> }
>
> which B uses:
>
> public class B {
> public void b(A a) { a.m( "Hello" ) }
> }
>
> Now B has a dependency on A. If A changes, for any reason:
>
> public class A {
> public void m( Object o ) {}
> public void m( String s ) {}
> }
>
> or:
>
> public class A {
> public void x( Object o ) {}
> }
>
>
> then B has to recompiled. That's pretty standard stuff I think. There
> really isn't any need to detect an overloaded method, this
> simple dependency graph catches it, and many other cases too.

The overload is a subtle case, because the added method isn;t actually used
by anyone, so dependencies at the granularity of method usage won't catch
it. (Unless you conflate all overloads as being "the same method", which is
probably a good idea.)