On 10/02/2011, at 10:36 PM, Peter Niederwieser wrote:
>
> I fully agree that we need to solve this problem. However, I'd rather not
> want to be forced into creating a class around a dynamic property.
Thinking about it, 'dynamic properties' is probably the wrong term for us to
use. I think we're actually after a way to statically declare additional
properties and methods for domain objects. I use 'static' in the sense that one
can infer from the build language that these properties exist and are usable in
the build script, without having to actually run the build script. For example,
the declarative statement: apply plugin: 'java' infers that the project has a
'sourceCompatibility' property. Or that there is a 'runtime' configuration, and
so on. You don't need to run the build script to know this.
It would be nice if our solution to this problem lends itself to static
analysis. This allows us to:
* Generate documentation for the build.
* Validate that appropriate values have been provided, before actually running
the script. Project properties are often used to implement the configurable
aspects of a build, where the user must provide a value as input for the build.
For example, if the script declares a 'java5Home' property with no default
value, Gradle can complain when no value has been provided before running the
script. The means you don't need defensive if(hasProperty()) checks in your
script.
* Building on the above, Gradle can prompt for missing values, or give you a
useful message in the help page, or display a build configuration wizard in the
IDE or CI config UI, or offer other UIs for visualising and managing your build
configuration.
* Offer code completion when authoring build scripts.
I wonder if we can simplify the problem by offering a dsl convenience only for
project properties. You'd be able to use the convention object mechanism for
all types (including project), but for the project (and only the project) we
also offer a convenience mechanism.
We actually want to have some way to declare: domain object o has a property
with the given name, type, default value, description, and constraints. Using a
convention object provides natural places for all this stuff:
class MyConfig {
/** description */
@Constraint1
Type name = defaultValue
}
> One
> alternative would be to require the use of a "dyn" namespace for setting
> dynamic properties (somewhat similar to your properties block):
>
> dyn.foo = 3
> ...
> println foo // no qualification needed
This feels like pretty much the same thing. A general pattern we have in the
DSL is to allow either
<namespace>.someProp = value
or
<namespace> {
someProp = value
}
(and sometimes <namespace> someProp: value, but that's a different issue)
So, we would probably just handle both options.
>
> Another approach would be to reserve the "foo = bar" syntax for dynamic
> properties, and do all configuration with "foo bar":
>
> exec {
> executable "my.exe"
> args "one", "two"
> foo = bar
> }
>
> This would make for a nice visual distinction between the declarative and
> imperative.
I think there are a few issues with this approach:
* Currently, for multi-valued properties, 'foo bar' will add 'bar' to the
collection, and 'foo = bar' replaces the contents of foo with [bar]. We'd need
to come up with a new syntax for handling multi-valued properties (which is
fine - I don't 100% like the existing syntax anyway).
* It feels like this might be more difficult to do static analysis for, given
that assignment will still work the usual way in the imperative portions of the
build script.
* We might want the value provided on the rhs of the assignment to be a default
value, so that it is only used if a value has not already been provided (eg
using -P or gradle.properties). Overriding the semantics of assignment might be
stretching too far.
> Actually I have something bigger in mind here (more flexible
> mapping between DSL and domain model), but I don't want to distract from the
> current discussion.
Go on. You can't not talk about it now you've mentioned it :)
--
Adam Murdoch
Gradle Developer
http://www.gradle.org
CTO, Gradle Inc. - Gradle Training, Support, Consulting
http://www.gradle.biz