Hi Steve,
On May 13, 2009, at 5:10 PM, Steve Appling wrote:
I'm still not sure that I understand the motivation to change from
using createTask to the keyword style syntax. I think this looks
less like normal groovy code (which makes it harder to initially
understand). Perhaps I'm just ranting about DSLs in general, which
are always a balance between convenience and ease of learning.
What distinguished those approaches is rather subtle. I can't provide
any killer argument. But let's look at 0.5.2:
You create as task with createTask("name"). But you can access the
task with name (unquoted). You could also argue the latter is not
normal groovy code (and may be you do). The alternative would be to
say task("name") or with 0.6 tasks.getByName("name"). But I think it
is nice to access a task like a variable. It is not just convenient
for the writer, it is also nicer and better to read. One major
motivation for Adam to change the 0.5.2 behavior was the mismatch
between using strings for creating task vs. the unquoted name for
accessing them (Adam, please correct me if I'm wrong). And I think the
new syntax is therefore more consistent and nicer (better) to read. It
is kind of funny. Some people (the developers in any case :)) really
like it. And we were almost surprised that not everybody liked this
change. But we had our reasons for this and it was not just DSL hype :)
That said, if you are going to use a keyword style syntax, I would
prefer a keyword to create a new task that looked more like a verb -
perhaps createTask or newTask. I think the keyword task is
confusingly close to the Project.task methods and Project.getTasks.
If I was going to the javadoc to try to understand what methods in
project were available to me, I would find this confusing.
We had a discussion a while back about the general approach for the DSL.
See: http://markmail.org/message/uiejxtpqwbsa74sc
Some experienced DSL writers recommended strongly to go for
declarative vs. describing operations. And I agree with them. Again I
think this is nicer and better to read.
The Project.task and getTasks method are replaced by the methods of
the new tasks container (e.g. project.tasks.all/getByName/...). At
least it is consistent to what we do in configurations/dependencies/
repositories.
There is already a method to add actions to a task. Why is the "<<"
syntax needed? It just seems like more non-obvious magic. Could
you not just use:
task hello.doLast { stuff to do }
Now here I will use the normal groovy code argument :)
List list = []
list << 'String' // normal Groovy code
I think to use doLast you would have to use parentheses:
task(hello).doLast { ... }
Another argument is: what are the major use cases? If I create a
custom task, I just want to add an action and I don't care about
doLast and doFirst. It is rather confusing in this context to use
doLast and doFirst (and in fact doFirst and doLast has confused quite
a few people at the beginning). Of course what we could do would be to
provide an additional method do, which is equivalent to doLast. But
then we would still have the parentheses problem.
I do like the idea of making more of a distinction between action
closures and configuration closures. The 0.5.2 syntax was confusing
initially.
I'm happy that there is at least one aspect which you like.
Many thanks for your feedback
- Hans
Hans Dockter wrote:
We plan to make another change to the Task DSL before we release 0.6.
At the moment the behavior that if you pass a closure to an
existing task, the closure is used for configuring the task object.
If you pass a closure to a task when creating a task, this closure
is used as an action. The reason for this behavior is that we
wanted to make Gradle behave as convenient as possible for the
major use cases. If you create a simple task like HelloWorld, you
usually don't want to configure it but want to add an action. And
if you are accessing a task provided for example by the Java
plugin, you usually want to configure it. The pay-off for this
behavior, is that it can be a bit confusing at the beginning. And
it is different from the normal Gradle behavior, which always uses
closure assigned to objects for configuring them. The use case that
made us change our mind about what is the best behavior, is when
you don't create simple tasks but tasks of a custom type (e.g.
Jar). In such a case you often want to configure the tasks when you
create it (in contrast to simple tasks).
We plan therefore to change the DSL in the following way:
task hello << { <action> }
task hello { <configure> }
task myJar(type: Jar) { <configure> }
existingTask << { <action>} // equivalent to existingTask.doLast
existingTask { <configure> }
We were also thinking about using the work 'do' instead of <<. That
would be nice to read. But this is not trivial to implement in
Groovy. And the << operator is already used in Groovy for adding
elements to a list, which is something similar to adding an action
to a task.
Feedback is very welcome
- Hans
--
Hans Dockter
Gradle Project lead
http://www.gradle.org
--
Steve Appling
Automated Logic Research Team
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
--
Hans Dockter
Gradle Project lead
http://www.gradle.org
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email