Why is the apply() method the suggested syntax for add plugins?


(mh) #1

apply plugins: ‘myplugin’

is a lot harder to understand and adds a lot of overhead in comparison to

plugins.apply ‘myplugin’

Why is this suggested API?


(Peter Niederwieser) #2

It was probably deemed more readable at the time. It’s also just a named parameter, which is used all over the place in Gradle. Anyway, ‘plugins.apply ‘myplugin’’ will work as well.


(mh) #3

One difference between plugins.apply() and apply({plugins}) is that an extended “Project” class can handle it differently and tbh. it sounds like a horrible Idea if an extended Project would handle it like this. Also “apply” is a naturally strongly limited compared to direct access of the functions (a lot of functionality does not have an “apply” pendant). Okay: The api is here now and used but that why my question is “why suggest it?” it seems like not a good idea at all …


(Peter Niederwieser) #4

Both notations are equally capable, both are just method calls, and both can be misused. Frankly, I don’t see a big difference, except that the latter may be easier to understand (in terms of what’s going on underneath) for newcomers with a (Java) programming background.


(mh) #5

I guess most of Gradles newcomers have a programming background and clarification is always a good thing, isn’t it? But aside from that: The default notation has a maintenance overhead and a (small) performance overhead (creates temporary objects,etc.) that makes it just more difficult to handle. Still can’t find a plus argument for the “apply plugin: ‘’” notation.


(Peter Niederwieser) #6

Clarification is good, but “horrible idea” is a gross overstatement. The performance overhead is completely negligible, and I don’t know what you mean by “maintenance overhead”. I find that ‘apply plugin: ‘foo’’ reads better than ‘plugins.apply ‘foo’’. It’s a common idiom in Gradle and other Groovy DSLs. Ultimately, it comes down to a matter of taste.


(mh) #7

The horrible idea refers to “extending Project and changing the way apply works” as it would break established idioms and would be hard to understand. (refers to a possible case not an actual one)

Maintenance overhead refers to the fact that now you can call every method on all properties of project just like “plugins.apply()” but you can not pass anything into “apply {}” just the methods provided in DefaultObjectConfigurationAction. In order to offer more functionality (like for example: passing a list of pluginIds instead of just one pluginId) you have to change both the PluginContainer and the Action: Having to change the code at two different locations is afaik. a maintenance overhead.


(Peter Niederwieser) #8

I disagree but respect your opinion.


(mh) #9

Disagree with the fact that you’d have to add that method twice? Or disagree with it being a bad idea?


(Peter Niederwieser) #10

I disagree that the former notation is a horrible idea, is less safe, is a meaningful performance/maintenance overhead, etc.


(mh) #11

I didn’t talk about the notation. I talked about the idea to extend Project for a different implementation of plugins.

class MyProject extends AbstractProject {

@override

public void apply(Map<String, ?> options) {

// use different way to apply

} }

because it would also have to implement getPlugins() and then suddenly: project.plugins.apply() wouldn’t be equals to project.apply({plugins:…})

(final might help)

Sorry to have not made that clear.

Aside from that: general disagreement is pretty unfriendly. I was trying to understand the reasoning behind gradle and the chosen syntax, not bashing it. I still assume that I don’t understand something basic now: are my assumptions just wrong or do I not get an idea?


(Luke Daley) #12

Hi Martin,

For google and for the search here, the title of posts is very important. In the future, please consider using more descriptive and accurate titles to posts.

Thanks.


(mh) #13

Thank you! I will keep that in mind. Sorry for the inconvenience.


(Luke Daley) #14

The Project interface is optimised for user friendliness and how it feels in the DSL. We always prefer simple API to simple implementation. Secondly, this is not really designed for extensibility through inheritance.

The apply function is more general than just plugins. The concept is that you’re applying something to the domain object, be it a plugin or something else. So “apply” provides a unified entry point.

Are you able to share why you need your own Project implementation or what you are doing here?


(mh) #15

I was trying to illustrate a “difference” that I could figure out between the two ways:

“.apply” allows overriding “how X is applied” without caring about how “plugins.apply” works. I see this as problematic because: What if someone (anyone) wants to extend the “apply”? That would read essentially for me like: “.apply” is a generic something that does not have a standard way to behave?! (I figured out that the documentation of apply says that plugin/from/to are allowed)

Its not that I have a use-case right now: I was really just trying to see the different sides of both variants.

I think the idea of “apply” is not hard to understand. Just how it plugs everything together: Thoughts like: How does gradle resolve “plugin”? What else can I use “apply” for? How can I work on a proposal for offering multiple plugins (not just one)?

When studying the code I just found that the existing call results in plugins.apply(“myplugin”) mostly. I just found the other call sort of: Why would I use “apply” if it does the same thing just obfuscated?! What do I win as a gradle user by using apply instead of the plugins that is a lot closer to what actually happens?

btw.: From start this API would have made sense to me: plugin(“myproject”).apply(); Just saying.

(I admit I am new to groovy.)


(Peter Niederwieser) #16

It wasn’t a general disagreement. I had already made all my points but you seemed to be neglecting them. Maybe this was a series of misunderstandings.


(Rolf Suurd) #17

Apply also works for reusable scripts: apply from: ‘awesome-script.gradle’

So, for scripts, you would suggest script(‘location/of/script’).apply()?


(mh) #18

@Rolf: To me: If “plugins” is the short form of “getPlugins()” then plugin(“id”) is the short-form of getPlugin(“id”) so it would be just logical if script('location") would be the short-form of getScript(“location”) - so: yes.


(mh) #19

Thinking about it: if “plugin(‘myplugin’)” would return a “Configuration(interface)” then there could be something like “apply(Configuration config)” then the syntax could be like “apply plugin ‘myplugin’” and it would be already easy to understand.