ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefan Bodewig <bode...@bost.de>
Subject Why Properties became immutable
Date Fri, 21 Jul 2000 07:58:23 GMT
Hi,

Seems like we have a most hated feature 8^). And given the work it
might take to convert older buildfiles I can fully understand it.

I'm trying to give a little bit of a rationale for the decision to
make properties immutable (AFAIR - I hardly recognized the change or
would have said so in the ANNOUNCE message in the first place).

After that I want to explore how people have been using mutable
properties, what can be done and what kind of changes would become
necessary. Different Thread, mail should follow.

The top two reasons (there might have been more) were (1) ensure
sub builds don't override properties of parent projects and (2) make
properties less confusing.

I don't think I need to explain (1), but obviously we've failed with
regard to (2). I'll need to go into some implementation details - even
though this might not be of interest to users - to explain why
properties behave like they do.

Let me start by saying that the ${} replacement is the root of all
evil. This translation happens at parser time - and there isn't much
you could do about that unless you wanted to bother each and every
task with it.

One step further this obviously means, properties need to have their
value at parser time as well - this is long before we know which tasks
are actually part of the build process that is supposed to happen.

This leads to the first - very confusing - feature of properties, they
get evaluated even if the corresponding property task is not part of
any target the build depends on. Meaning

<target name="1">
  <property name="a" value="a" />
</target>

<target name="3" depends="2">
  <property name="a" value="b" />
</target>

<target name="2" depends="1">
  <echo message="a has the value ${a}" />
</target>

leads to the result "a has the value b" even though target 3 shouldn't
be executed before target 2. Even worse, the outcome depends on the
order you've placed the targets in your file. Put target 2 at the top
and the result is going to be "a has the value null" or "a has the
value ${a}" depending on which version 1.0.8 you've been using. Place
it between 1 and 3 and everything looks like one would expect it - but
it does so by accident.

The constructs

<target>
  <property name="a" value="a" />
  <tasks that use ${a} />
</target>

<target>
  <property name="a" value="b" />
  <tasks that use ${a} />
</target>

didn't work like they did because properties would be scoped, but
merely because the last definition the parser found had been used to
replace the ${a}. Again - it worked by accident.

So - from the implementation point of view - properties have always
been mutable only during parse time and they've always been global -
executed right then when the parser had found them.

The first step was to allow property tags outside of targets to
reflect their global nature - maybe it would have been better if we
had disallowed <property> tags inside targets at the same step. They
don't make sense anywhere there at all.

The second step was to make them immutable right from the start - as
they've been immutable once the parser had done it's work anyway.

We obviously failed to realize, that some patterns of property usage
had evolved that would be broken by this change - other than the
concatenation mentioned at the download page.

But these usage patterns might lead to something better than mutable
properties could do.

Stefan

Mime
View raw message