2021-09-26

1: Opting to Write More Reasonable Groovy-Based Gradle Scripts

<The previous article in this series | The table of contents of this series | The next article in this series>

The pervasively-promoted way of writing Groovy-based Gradle scripts is not advantageous for fully utilizing the full potential of Gradle.

Topics


About: Gradle
About: Groovy

The table of contents of this article


Starting Context


  • The reader has a basic knowledge on Groovy or Java.

Target Context


  • The reader will know how the pervasively-promoted way of writing Groovy-based Gradle scripts is a bad idea and know the preferable way.

Orientation


This is the 1st step toward fully utilizing Gradle; further steps will be taken in following articles of this series.


Main Body

Stage Direction
Here is Special-Student-7 in a room in an old rather isolated house surrounded by some mountains in Japan.


1: Gradle Is Great, Because It Is Groovy-Based


Special-Student-7-Hypothesizer
Gradle is my primary choice as build tool; I deem it great.

Special-Student-7-Rebutter
Are you saying so based on some experience with some other build tools?

Special-Student-7-Hypothesizer
Yes, I used to use Apache Ant, but gave up on it.

Special-Student-7-Rebutter
Why?

Special-Student-7-Hypothesizer
Because it is restrictive: it has a set of things I am supposed to do, and it would be fine if I wanted to do only those things, but I am sorry, I do not want to do only what are supposed by it.

Special-Student-7-Rebutter
That seems a usual thing for any tool. You are not supposed to cut paper with a hammer.

Special-Student-7-Hypothesizer
Certainly, but I am not happy with a pair of scissors that supposes me to cut only white paper.

Special-Student-7-Rebutter
So, what are not supposed by the tool but are wanted by you?

Special-Student-7-Hypothesizer
I do programming not only in Java, but also in C++, C#, Python, and even in UNOIDL, and in Linux and in Microsoft Windows, and have to dictate what commands should be executed with what arguments on what conditions, and sometimes, some derived files have to be tweaked.

Special-Student-7-Rebutter
Does the tool not allow such things?

Special-Student-7-Hypothesizer
I am not sure whether it does not allow them absolutely, but things become very cumbersome when I try to do such sort of things: the tool is XML-based, and dictating somehow intricate logic in a XML form is irksome, if not impossible. Sometimes, I had to be resigned to put such logic into an operating system script, but that is unsatisfactory, because such a script is operating system dependent, but I do not want different versions of my build scripts.

I really do not see any merit in build tools' being XML-based.

Special-Student-7-Rebutter
Some people seem to be claiming its merit to be programming-less.

Special-Student-7-Hypothesizer
But their users are programmers! What kind of programmers are they who love programming-less-ness?

Special-Student-7-Rebutter
Reluctant programmers, I guess: not every programmer is enthusiastic on programming.

Special-Student-7-Hypothesizer
Ah, so XML-based build tools are for reluctant programmers, I understand.

Anyway, I began to think "Is there not a better built tool for my usage?".

Special-Student-7-Rebutter
And you found Gradle . . .

Special-Student-7-Hypothesizer
I found also Apache Maven, but reading some introductions for Apache Maven, I was sure I did not like it.

Special-Student-7-Rebutter
Why?

Special-Student-7-Hypothesizer
For one thing, it is XML-based, which implies its usual restrictiveness.

Special-Student-7-Rebutter
That seems to be a sufficient reason for you to turn down the tool.

Special-Student-7-Hypothesizer
For another, it promotes "Convention over Configuration".

Special-Student-7-Rebutter
Is that a problem?

Special-Student-7-Hypothesizer
Having conventions itself is not particularly any problem if I have complete freedom to do unconventionally, but I have to reasonably expect an annoying barrage of recommendations to obey conventions and hampering scarcity of information for doing unconventionally, which is the problem.

Special-Student-7-Rebutter
Is that the case for Apache Maven?

Special-Student-7-Hypothesizer
It seems so more or less; it is usually inevitable, because the tool's community is consisted of people who have adopted the tool knowing the policy; expecting otherwise is unreasonable.

On the other hand, what is great about Gradle is that not only it is scripts-based, but also its scripts are Groovy-based (or Kotlin-based, but I will omit mentioning Kotlin, because I do not use it, at least for now).

Special-Student-7-Rebutter
Is that because you are familiar with Groovy?

Special-Student-7-Hypothesizer
In fact, I was not familiar with Groovy at all, but Groovy is Java-based and allows any Java code in it, and I am familiar with Java.

Special-Student-7-Rebutter
Good for you.

Special-Student-7-Hypothesizer
And should be good for any Java programmer.

It is important that Gradle scripts are not based on a Gradle-original, probably meager and restrictive, unfamiliar language.

Special-Student-7-Rebutter
Instead on the great Java language.

Special-Student-7-Hypothesizer
Java is a very versatile programming language, and what Java can do, we can do in Gradle scripts.

Special-Student-7-Rebutter
So, is it happy ever after?

Special-Student-7-Hypothesizer
The only drawback is the heaviness, which may not be much nuisance if the environment is high-performance.


2: The Pervasively-Promoted Way of Writing Groovy-Based Gradle Scripts Is Unwise, Though


Special-Student-7-Hypothesizer
However, the pervasively-promoted way of writing Groovy-based Gradle scripts is very unwise, in my opinion.

Special-Student-7-Rebutter
"the pervasively-promoted way"? What way?

Special-Student-7-Hypothesizer
The "Hello World" script in this official document page is representing the way.

Special-Student-7-Rebutter
Well . . .

Special-Student-7-Hypothesizer
Let me cite it here.

@Gradle Source Code
task hello {
	doLast {
		println 'Hello world!'
	}
}

Special-Student-7-Rebutter
How is that very simple code "very unwise"?

Special-Student-7-Hypothesizer
The problem is that it does not make sense as Groovy code.

Special-Student-7-Rebutter
Well, what is that "task" there? Does Groovy have such a keyword?

Special-Student-7-Hypothesizer
No, it does not. "task" is a method, actually.

Special-Student-7-Rebutter
Huh? Then, is that naked (without quoted) "hello" an argument? Is that a variable? But where has it been defined?

Special-Student-7-Hypothesizer
You see that it does not make sense.

On the other hand, let us look at this code cited from the same official page.

@Gradle Source Code
4.times { counter ->
    task "task$counter" {
        doLast {
            println "I'm task number $counter"
        }
    }
}

Special-Student-7-Rebutter
Huh? Why is the task name specification suddenly a string this time?

Special-Student-7-Hypothesizer
The page offers no explanation; the 2nd code, which is incoherent with the 1st one, suddenly appears from the blue.

Special-Student-7-Rebutter
I wonder who thought that that kind of document was OK . . .

Special-Student-7-Hypothesizer
In fact, the task name specification should really be always a string, at least as Groovy code.

Special-Student-7-Rebutter
Then, why is the 1st code OK?

Special-Student-7-Hypothesizer
Gradle is surreptitiously making it OK.

Special-Student-7-Rebutter
Why is it making defective code OK?

Special-Student-7-Hypothesizer
They are promoting such defective code.

Special-Student-7-Rebutter
Why?

Special-Student-7-Hypothesizer
Because they think that such defective code is neat, I guess.

Special-Student-7-Rebutter
"neat"? . . . I do not understand the concept of "neat"ness.

Special-Student-7-Hypothesizer
It is a Biasian concept, which I myself do not really understand well.

Anyway, obviously, the 1st code is trying hard to hide the fact that "task" is a method and in fact, the fact that the script is Groovy-based.

Special-Student-7-Rebutter
Why would it want to do such a thing?

Special-Student-7-Hypothesizer
I can only guess that it feels neat for some people.

But it feels as unwise to me as neat to them, because for one, it is hiding the tool's strongest point (at least for me) of being Groovy-based (I said that the tool is great because it is Groovy-based), for another, the tactics is not working.

Special-Student-7-Rebutter
When you say "not working" . . .

Special-Student-7-Hypothesizer
The 2nd code requires "task" to be a method, otherwise that "task" in that loop would not make sense. So, the fact cannot be hidden, unless they prohibit the 2nd code, making the tool a restrictive one that has no merit over XML-based ones.

Special-Student-7-Rebutter
. . . Is there not another reason for their promoting the way, a reason even we can understand, I mean, other than "neat"ness?

Special-Student-7-Hypothesizer
Like labor-saving? But it saves only 2 characters (2 double quotes). Going that way for saving just 2 characters would be too foolish, even for Biasians.

Special-Student-7-Rebutter
So, they are promoting the way because it is just "neat". . . . This "neat"ness is very enigmatic to me.


3: A More Reasonable "Hello World" Script


Hypothesizer 7
This is a more reasonable "Hello World" script.

@Gradle Source Code
task ("hello", {
	doLast ({
		println ('Hello world!')
	})
})

"task" is really a method of 'org.gradle.api.Project' (an interface) implemented by 'org.gradle.api.internal.project.DefaultProject', and "hello" (which has to be a string) and the "{~}" block (which is a closure) are the arguments passed into the method.

Special-Student-7-Rebutter
Do you mean that the script becomes a 'DefaultProject' instance?

Special-Student-7-Hypothesizer
Actually no.

Special-Student-7-Rebutter
Huh? Then, why can the method be called from the script without any qualification?

Special-Student-7-Hypothesizer
A good point; we will see it in the next article.

Special-Student-7-Rebutter
Well, otherwise, the code is very clear that way.

Special-Student-7-Hypothesizer
The '(' and ')' pairs can be omitted according to the Groovy specifications, but that is not any good idea, in my opinion.

The reason is the entailed inconsistency: the pair is required anyway if there is no argument or if ambiguity would sneak in otherwise. So, sometimes, the pair appears, and sometimes, not, which I call inconsistency. Besides, I have to ask myself "Isn't this ambiguous?" every time. Omitting the 2 characters is not much labor-saving that is worth such inconsistency and required extra care.

Special-Student-7-Rebutter
Having those '(' and ')' pairs makes it clear that they are function calls.

Special-Student-7-Hypothesizer
Other than that, the official "Hello World" code omits just the """ and """ pair and a single ",".

As a conclusion, the pervasively-promoted way is barely labor-saving.


4: The Pervasively-Promoted Way of Writing Groovy-Based Gradle Scripts Is Disgusting, in Fact


Special-Student-7-Hypothesizer
In fact, I deem the pervasively-promoted way of writing Groovy-based Gradle scripts not only unwise, but also disgusting.

It reeks of an attitude I am really repulsed by.

Special-Student-7-Rebutter
What attitude?

Special-Student-7-Hypothesizer
The attitude that tells you "You don't need to understand; just do as I tell you!".

Special-Student-7-Rebutter
Where do you sense the attitude?

Special-Student-7-Hypothesizer
The way is not just not helping us to understand what is really going on, but intentionally trying to prevent us from understanding it, which is nothing but telling you "You don't need to understand.".

Special-Student-7-Rebutter
I cannot deny that.

Special-Student-7-Hypothesizer
And it is evidently also telling you to do as it tells you.

Special-Student-7-Rebutter
A tutorial is usually so.

Special-Student-7-Hypothesizer
So, what else can it be?

Special-Student-7-Rebutter
Such an attitude is certainly not nice; it is an attitude toward slaves: slaves are supposed to blindly obey without any understanding, but free men are supposed to judge themselves based on what? of course on understandings.

Special-Student-7-Hypothesizer
I wonder why many Biasians are happy with such an attitude.

Special-Student-7-Rebutter
They may not be particularly "happy".


5: We Can Do This Because We Understand


Special-Student-7-Hypothesizer
As now we understand, we can do like this.

@Gradle Source Code
def closureA = {int a_index ->
	println String.format ('Hello world, %s!', a_index)
}

for (int l_index = 0; l_index < 10; l_index ++) {
	def int l_indexCopied = l_index
	task (String.format ("hello%d", l_index), {
		doLast ({
			closureA (l_indexCopied)
		})
	})
}

1st, as '{~}' block is a closure, we can define a closure only once and reuse it, possibly customized via some arguments (note that passing different variables as 'l_indexCopied's (a new variable per iteration) is important, because the closure encloses the passed variable, not the passed value).

2nd, tasks can be dynamically created with the task names dynamically determined.

Special-Student-7-Rebutter
Certainly.

Special-Student-7-Hypothesizer
That kind of scripts can be written only because we understand Gradle scripts as Groovy code.


References


  • Gradle Inc.. (2020). Build Script Basics. Retrieved from https://docs.gradle.org/6.7.1/userguide/tutorial_using_tasks.html
<The previous article in this series | The table of contents of this series | The next article in this series>