2021年10月10日日曜日

1: もっとリーズナブルなGroovyベースGradleスクリプトを書くことにする

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

GroovyベースGradleスクリプトを書くための広く宣伝されている方法は、Gradleのフルポテンシャルをフルに活用するのに有利ではありません。

話題


About: Gradle
About: Groovy

この記事の目次


開始コンテキスト


  • 読者は、GroovyまたはJavaの基本的知識を持っている。

ターゲットコンテキスト



  • 読者は、GroovyベースGradleスクリプトを書くための広く宣伝されている方法がいかに悪いアイデアであるかを知り、より好ましい方法を知る。

オリエンテーション


これは、Gradleをフルに活用することに向かう第1ステップです。さらなるステップが、本シリーズの引き続く記事にて踏まれます。


本体

ト書き
Special-Student-7が、日本の、いくつかの山に囲まれた、古い、かなり孤立した家の、ある部屋にいる。


1: Gradleはグレートだ、理由は、Groovyベースであること


Special-Student-7-Hypothesizer
Gradleは、ビルドツールとして、私の第1選択だ。私はそれをグレートだと思う。

Special-Student-7-Rebutter
君は、他のビルドツールでのなんらかの経験に基づいて、そう言っているのか?

Special-Student-7-Hypothesizer
そうだ、私はかつてApache Antを使用していたが、それをあきらめた。

Special-Student-7-Rebutter
なぜだ?

Special-Student-7-Hypothesizer
なぜなら、それは制限的だから: それには、私が何を行なうかという一群の想定があり、もしも私がそれらのことのみを行ないたいのであれば問題ないのだろうが、申し訳ない、私は、それに想定されていることのみを行ないたくはない。

Special-Student-7-Rebutter
それは、どのツールにも言える普通のことに思える。君は、ハンマーで紙を切るようには想定されていない。

Special-Student-7-Hypothesizer
確かに、しかし、私が白い紙のみを切ると想定してるはさみを私は喜ばない。

Special-Student-7-Rebutter
それで、そのツールに想定されていないが君が欲することとは何なのだ?

Special-Student-7-Hypothesizer
私は、Javaにてのみプログラミングするわけではなく、C++、C#、Pythonでも行ない、UNOIDLでさえ行ない、LinuxにおいてもMicrosoft Windowsにおいてもだ、そして、いかなるコマンドがいかなる条件でいかなる引数で実行されるかを指図しなければならない、そして、場合によっては、いくつかの生成されたファイルに手を加えなければならない。

Special-Student-7-Rebutter
そのツールは、そうしたことを許さないのか?

Special-Student-7-Hypothesizer
それらを絶対的に許さないのか否かははっきり知らないが、そうした類いのことをしようとすると、とても面倒なことになる: そのツールはXMLベースであり、かなり込み入ったロジックをXMLフォームで指図するのはうんざりなことになる、仮に不可能でないとしても。場合によっては、諦めて、そうしたロジックをオペレーティングシステムスクリプトの中に入れなければならなかったが、それは不満足なものだ、なぜなら、そうしたスクリプトはオペレーティングシステム依存であるが、私は、私のビルドスクリプトの複数バージョンなど欲しくないから。

私は、実際のところ、ビルドツールがXMLベースであることに何のメリットも見いださない。

Special-Student-7-Rebutter
一部の人々は、そのメリットはプログラミングレスであることだと主張しているようだが。

Special-Student-7-Hypothesizer
しかし、そのユーザーはプログラマーだ!プログラミングレスを愛するとは、いったいどういう種類のプログラマーなのだ?

Special-Student-7-Rebutter
いやいやなプログラマーなのだろう。全てのプログラマーがプログラミングに熱心なわけでもない。

Special-Student-7-Hypothesizer
ああ、それじゃあ、XMLベースのビルドツールは、いやいやなプログラマーのためのものなんだ。

とにかく、私は思い始めた、「私の使い方にもっと適したビルトツールはないのか?」。

Special-Student-7-Rebutter
それで、君はGradleを見つけたと . . .

Special-Student-7-Hypothesizer
Apache Mavenも見つけたが、Apache Mavenのいくつかの紹介を読んで、私はそれを好かないと確信した。

Special-Student-7-Rebutter
なぜだ?

Special-Student-7-Hypothesizer
一つには、それはXMLベースであり、それはそれにおなじみの制限を示唆している。

Special-Student-7-Rebutter
それは、君には、そのツールを却下する十分な理由であるようだ。

Special-Student-7-Hypothesizer
他には、それは、「コンフィギュレーションよりもコンベンション優先」を宣伝している。

Special-Student-7-Rebutter
それは問題なのか?

Special-Student-7-Hypothesizer
コンベンションを持っていること自体は特に何の問題でもない、もしも、コンベンションに従わずにやる完全な自由が私にあるのであれば、しかし、リーズナブルに考えて、コンベンションに従えという推奨の苛立たしい集中砲火と、足かせとなる、コンベンションに従わずにやるための情報の乏しさを予想しなければならず、それが問題だ。

Special-Student-7-Rebutter
それは、Apache Mavenの場合にあてはまるのか?

Special-Student-7-Hypothesizer
多かれ少なかれそのように思われる。それは通常、避けられない、なぜなら、そのツールのコミュニティは、そのポリシーを知ったうえでそのツールを採用した人々で構成されているのだから。そうでないと予想するのはリーズナブルでない。

他方で、Gradleがグレートである点は、それは単にスクリプトベースであるだけでなく、そのスクリプトがGroovyベースであることだ(またはKotlinベースだが、私はKotlinに言及することは省く、私はそれを使っていないから、少なくとも今のところ)。

Special-Student-7-Rebutter
それは、君がGroovyになじんでいるからか?

Special-Student-7-Hypothesizer
実のところ、私はGroovyに全然なじんでいなかったが、Groovyは、Javaベースであり、その中で任意のJavaコードを許し、私はJavaになじんでいる。

Special-Student-7-Rebutter
それは君にはよかったな。

Special-Student-7-Hypothesizer
そして、どのJavaプログラマーにもよいはずだ。

GradleスクリプトがGradleオリジナルの、おそらくは貧弱で制限的な、なじみのない言語に基づいているのではないことが重要だ。

Special-Student-7-Rebutter
あのグレートなJava言語に基づく代わりに。

Special-Student-7-Hypothesizer
Javaは、とても広用途なプログラミング言語であり、Javaができることは、私たちはGradleスクリプトの中でできる。

Special-Student-7-Rebutter
それでは、後は万事めでたしというわけか?

Special-Student-7-Hypothesizer
唯一の欠点は動作の重さであるが、それは、環境がハイパフォーマンスであれば、たいした差し障りにはならないかもしれない。


2: GroovyベースGradleスクリプトを書くための広く宣伝されている方法は、不得策である、しかしながら


Special-Student-7-Hypothesizer
しかしながら、GroovyベースGradleスクリプトを書くための広く宣伝されている方法は、とても不得策だ、私の意見では。

Special-Student-7-Rebutter
「広く宣伝されている方法」?どの方法だ?

Special-Student-7-Hypothesizer
このオフィシャルドキュメントページの中の「Hello World」スクリプトがその方法を代表している。

Special-Student-7-Rebutter
えーと . . .

Special-Student-7-Hypothesizer
それをここに引用しよう。

@Gradle ソースコード
task hello {
	doLast {
		println 'Hello world!'
	}
}

Special-Student-7-Rebutter
そのとてもシンプルなコードがどのように「とても不得策」なのか?

Special-Student-7-Hypothesizer
問題は、それはGroobyコードとして意味をなさないことだ。

Special-Student-7-Rebutter
えーと、そこの「task」は何なのだ?Groovyにはそんなキーワードがあるのか?

Special-Student-7-Hypothesizer
いいや、ない。「task」はメソッドだ、実のところ。

Special-Student-7-Rebutter
はあ?それじゃあ、その裸の(修飾されていない)「hello」は引数なのか?それは変数か?しかし、それはどこで定義されたのか?

Special-Student-7-Hypothesizer
意味をなしていないことが分かるだろう。

他方で、同じオフィシャルドページから引用した以下のコードを見てみよう。

@Gradle ソースコード
4.times { counter ->
    task "task$counter" {
        doLast {
            println "I'm task number $counter"
        }
    }
}

Special-Student-7-Rebutter
はあ?タスク名指定はなぜ突然に文字列になったのか、今回の場合?

Special-Student-7-Hypothesizer
そのページは何の説明も差し出さない。1番目のコードと一貫性のない2番目のコードが、突然、なんの前触れもなく現われる。   

Special-Student-7-Rebutter
一体、誰がそんなドキュメントがオーケーだと考えたのだろうか . . .

Special-Student-7-Hypothesizer
実のところ、タスク名指定は、本当は常に文字列であるべきものだ、少なくともGroovyコードとしては。

Special-Student-7-Rebutter
それでは、なぜ、第1のコードはオーケーなのか?

Special-Student-7-Hypothesizer
Gradleがこっそりとそれをオーケーにしている。

Special-Student-7-Rebutter
なぜ、それは欠陥コードをオーケーにしているのか?

Special-Student-7-Hypothesizer
彼らはそういう欠陥コードを広めようとしている。

Special-Student-7-Rebutter
なぜだ?

Special-Student-7-Hypothesizer
彼らは、そういう欠陥コードが、いけてると考えているということだろう。

Special-Student-7-Rebutter
「いけてる」? . . . 私には「いけてる」というコンセプトが理解できない。

Special-Student-7-Hypothesizer
それは、バイアス人のコンセプトであり、私自身も本当によく理解しているとはいえない。

とにかく、明らかに、第1のコードは、「task」はメソッドであるという事実、もっと言えば、スクリプトがGroovyベースであるという事実を一生懸命隠そうとしている。

Special-Student-7-Rebutter
なぜ、そのようなことをしたいのだ?

Special-Student-7-Hypothesizer
それが一部の人々にはいけてると感じられるものと推測するほかない。

しかし、それは、彼らにいけてる感じられるのと同程度に私には不得策に感じられる、なぜなら、一つには、それは、Groovyベースであるという、そのツールの最強ポイント(少なくとも私には)を隠しているからで(私は、そのツールがグレートであるのは、それがGroovyベースであるからだ、と言った)、他には、その戦略はうまくいっていないからだ。

Special-Student-7-Rebutter
「うまくいっていない」というのは . . .

Special-Student-7-Hypothesizer
第2のコードは、「task」がメソッドであることを必要とする、さもなければ、そのループ内のその「task」は意味をなさないだろう。したがって、その事実は隠せない、もしも、第2のコードを禁止して、そのツールを制限的な、XMLベースなツールたちを凌駕するメリットのないものにしようというのでない限りは。

Special-Student-7-Rebutter
. . . 彼らがその方法を宣伝している他の理由はないのだろうか、私たちでも理解できるような理由は、つまり、「いけてる」というの以外に?

Special-Student-7-Hypothesizer
省力化のような?しかし、それはたった2文字(2つの二重引用符)減らしているだけだ。たった2文字減らすためのだけにその方向に進むのは、あまりにも愚かだろう、バイアス人にとってさえも。

Special-Student-7-Rebutter
すると、彼らはその方法を、単にそれが「いけてる」というだけの理由で宣伝しているわけか。 . . . この「いけてる」というのは、私には全く謎だ。


3: もっとリーズナブルな「Hello World」スクリプト


Hypothesizer 7
以下が、もっとリーズナブルな「Hello World」スクリプトだ。

@Gradle ソースコード
task ("hello", {
	doLast ({
		println ('Hello world!')
	})
})

「task」は、本当には、'org.gradle.api.internal.project.DefaultProject'によって実装された'org.gradle.api.Project'(インターフェイスである)のメソッドであり、「hello」(それは文字列でなければならない)および「{~}」ブロック(それはクロージャである)は、そのメソッドに渡される引数である。

Special-Student-7-Rebutter
そのスクリプトは'DefaultProject'インスタンスになる、と言っているのか?

Special-Student-7-Hypothesizer
実のところ、違う。

Special-Student-7-Rebutter
はあ?それでは、なぜ、そのメソッドは、そのスクリプトから何の修飾もなく呼べるのか?

Special-Student-7-Hypothesizer
良いポイントだ。私たちは、それを、次記事で見ることにしよう。

Special-Student-7-Rebutter
えーと、それを除いては、コードはその形態でとても明快だ。

Special-Student-7-Hypothesizer
そこの'('、')'ペアたちは、Groovyの仕様によれば省略することができるが、それは、全然グッドなアイデアではない、私の意見では。

その理由は、それに必然的に伴う非一貫性だ: もしも、引数が全然ないか、他の意味で曖昧さが忍び込むようであれば、そのペアはどのみち要求される。したがって、ある時には、そのペアが現われ、ある時には、現われず、それを私は非一貫性と呼ぶ。それに加えて、毎度、私は自問しなければならない、「これは曖昧ではないのか?」。その2文字を省略することは、そのような非一貫性および求められる余計なケアに値するほどのたいした省力化ではない。

Special-Student-7-Rebutter
それらの'('、')'ペアがあることで、それらがファンクションコールであることが明確になる。

Special-Student-7-Hypothesizer
それを除けば、オフィシャルな「Hello World」は、"""、 """ペアと1つの","だけを省いたにすぎない。

結論として、広く宣伝されている方法は、ほとんど省力化にはならない。


4: GroovyベースGradleスクリプトを書くための広く宣伝されている方法は嫌悪感をもよおす、実のところ


Special-Student-7-Hypothesizer
実のところ、GroovyベースGradleスクリプトを書くための広く宣伝されている方法に、私は、それを不得策だと思うだけでなく、嫌悪感をももよおされる。

そこからは、私が本当に嫌悪を抱く態度が滲み出ている。

Special-Student-7-Rebutter
どんな態度だ?

Special-Student-7-Hypothesizer
「お前は理解する必要などない。ただ私の言うとおりすればよいのだ!」という態度だ。

Special-Student-7-Rebutter
君は、どこにその態度を感じるのだ?

Special-Student-7-Hypothesizer
その方法は、本当に起こっていることを私たちが理解するよう助けようとしていないばかりでなく、私たちがそれを理解するのを意図的に妨げようとしており、それは、「お前は理解する必要などない。」と言っている以外の何物でもない。

Special-Student-7-Rebutter
私にはそれを否定できないな。

Special-Student-7-Hypothesizer
そして、それは明らかに、それが言うようにするように君に言っている。

Special-Student-7-Rebutter
チュートリアルとは通常そういうものだ。

Special-Student-7-Hypothesizer
してみると、他にどうありうるのか?

Special-Student-7-Rebutter
そういう態度は、間違いなく、感じの良いものでない。それは、奴隷に対する態度だ: 奴隷は、何の理解もなしに盲目的に従うように想定されているが、自由な人間は、自ら判断するように想定されており、それは何に基づくのか?勿論、理解に基づいてだ。

Special-Student-7-Hypothesizer
そのような態度に対して、なぜ多くのバイアス人がハッピーなのか、私には疑問だ。

Special-Student-7-Rebutter
彼らは別に「ハッピー」ではないかもしれない。


5: 私たちは、理解しているから、これができる


Special-Student-7-Hypothesizer
今や、私は、理解しているから、これができる。

@Gradle ソースコード
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)
		})
	})
}

第1に、'{~}'ブロックはクロージャだから、クロージャをただ1回定義して、それを再利用することができる、必要であれば、いくつかの引数を介してそれをカスタマイズして(注目点として、'l_indexCopied'として、毎回、別の変数を渡す(イテレーション毎に新たな変数)ことが重要である、なぜなら、クロージャは、渡された変数(渡された値ではなく)を囲い込むから)。

第2に、タスクは動的に生成することができる、タスク名が動的に決定されるように。

Special-Student-7-Rebutter
勿論。

Special-Student-7-Hypothesizer
そうしたスクリプトは、GradleスクリプトをGroovyコードとして理解しているからこそ、書くことができる。


参考資料


  • Gradle Inc.. (2020). Build Script Basics. Retrieved from https://docs.gradle.org/6.7.1/userguide/tutorial_using_tasks.html
<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>