Luke,

It might be worth restating the problem... to my understanding there is an 
issue with mostly people new to groovy not discovering (or taking too long to 
discover) that they mistyped a property and instead of assigning a value to an 
existing property they are creating a new property and assigning value to it.   
It would help to understand if there is something more than this...

IMO the approach you suggest seems to move too much in the direction of a Java 
idiom... my preference would be to maintain a groovy idiom.  realizing that 
your suggested approach would work just fine in a groovy world... 

When I think about a solution my mind gravitates toward the ExpandoMetaClass or 
the groovy mocking demand object.   In this approach it feels groovy like, yet 
is very explicit.

so if we assume we have an ext object available for all gradle objects or some 
subset... which of course would make the property ext reserved.  then the 
solutions you provided below would look like:

project.ext.foo = "bar" or
project.ext['foo'] = "bar

assert project.foo == "bar"

Is there something I'm missing?  or other reasons this wouldn't make sense?

Ken Sipe | [email protected] | blog: http://kensipe.blogspot.com



On Feb 15, 2012, at 4:26 PM, Luke Daley wrote:

> After discussing with Adam, here's the proposal.
> 
> We add something like:
> 
> public interface DynamicExtension {
>    /**
>     * Registers a new property with the given name and initial value.
>     */
>    void add(String name, Object value);
> 
>    /**
>     * Returns the value for the registered property with the given name.
>     */
>    Object get(String name);
> 
>    /**
>     * Updates the value for the registered property with the given name to 
> the given value.
>     */
>    void set(String name, Object value);
> }
> 
> We also add the following to ExtensionContainer: 
> 
> DynamicExtension addDynamic(String name, Action<DynamicExtension> configure = 
> null)
> 
> The basic idea is that we drive everything through the extension mechanism, 
> but provide a lightweight extension impl that users can use for adhoc state. 
> DynamicExtension objects will also of course act like maps, in that you can 
> read/write registered properties via standard groovy property notation.
> 
> 
> From there we do some more with this machinery, maybe as a transitional 
> measure or maybe as a long term measure. We will pre-populate all extension 
> containers with a special dynamic extension named something like “mine”, 
> “user” or “ext”. This extension will also promote it's properties into the 
> top level element. Assuming it's called “ext”, the following would work…
> 
> project.ext.add("foo", "bar")
> assert project.foo == "bar"
> 
> This would not (with clean slate):
> 
> project.extensions.addDynamic("custom")
> project.custom.add("foo", "bar")
> assert project.foo == "bar"
> 
> but this would:
> 
> assert project.custom.foo == "bar"
> 
> The link between the “special” dynamic extension is bidirectional…
> 
> project.ext.add("foo", "bar")
> project.foo = "abc"
> assert project.ext.foo == "abc"
> 
> 
> With the introduction of this, the following would give you a deprecation 
> warning:
> 
> task foo {
>  newProperty = "value"
> }
> 
> It will suggest you either do `ext.add("newProperty", "value")` or add your 
> own new namespaced extension. 
> 
> 
> It's not clear yet whether the behaviour of promoting properties out of a 
> special namespace up to the top level is something that we want to support 
> long term or not. There are no plans in this round of work to emit any kind 
> of warning when reading/writing top level dynamic properties provided they 
> have been declared. We can potentially do that later.
> 
> One of the reasons for pushing towards namespacing the dynamic properties is 
> that it provides a better migration path for builds. Using dynamic extensions 
> are a lightweight way to extend objects. As needs get more advanced, the 
> dynamic extension can be swapped for a real one with real methods and setters 
> etc. without changing it's public DSL API. For example, someone might start 
> out doing this…
> 
> configurations.all { 
>  dependencies.all {
>    it.extensions.addDynamic("maven") { add "optional", false }
>  }
> }
> 
> Then later…
> 
> class MavenDependencyExtension {
>  Dependency dependency
>  boolean optional
> }
> 
> configurations.all { 
>  dependencies.all {
>    it.extensions.add("maven", MavenDependencyExtension, [dependency: it])
>  }
> }
> 
> 
> There's also an argument to be made for safety, but at the cost of 
> convenience. If all “added” stuff is in a namespace, it's easier to tell at a 
> glance that it's added. 
> 
> 
> I'm feeling pretty good about most of that as the idea of dynamic extensions 
> is pretty good I think and something that should be there. The only real 
> contentious decision that we need to make now is if we allow new properties 
> to be _registered_ on the top level object, which really comes down to making 
> some kind of commitment to namespaces. That is, between something like…
> 
> project.addProperty("foo", "bar")
> 
> and…
> 
> project.ext.add("foo", "bar")
> 
> If we go the latter, we can resolve later whether or not to deprecate the 
> promotion to top level or not. I think this is the right path.
> 
> -- 
> Luke Daley
> Principal Engineer, Gradleware 
> http://gradleware.com
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
> 
>    http://xircles.codehaus.org/manage_email
> 
> 


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to