Javaが汎用言語であり、プログラムの構築がJava言語を使用して記述できるものである場合、なぜこれがビルドファイルを記述する最良の方法ではないのか、代わりにAnt、Maven、Gradleなどのツールを使用しますか?それはもっと簡単なことではなく、また別のプログラミング言語を学ぶ必要性を排除しませんか?(ところで-この質問は、C#などの他の言語にも適用できます)
Javaが汎用言語であり、プログラムの構築がJava言語を使用して記述できるものである場合、なぜこれがビルドファイルを記述する最良の方法ではないのか、代わりにAnt、Maven、Gradleなどのツールを使用しますか?それはもっと簡単なことではなく、また別のプログラミング言語を学ぶ必要性を排除しませんか?(ところで-この質問は、C#などの他の言語にも適用できます)
回答:
冗長性
汎用言語は冗長すぎることがよくあります。Javaでビルドを管理しなければならなかった場合、獣の大きさによって非常に早く落ち込んでしまいます。ただし、Javaで記述されたDSLを使用して簡単に管理できます。そしてある程度、Gradle(Groovy)とBuildr(Ruby)を見ることができます。
困難
汎用言語は難しいです。プログラミングは難しいとは思いませんし、だれも手に入れることはできませんが、ポイントは、ビルドエンジニアは必ずしもプログラマーではないということです!
目的
それは多かれ少なかれ難易度と冗長性の交差点にあります。言語は目的のために設計されており、ここでは非常に具体的なものについて話しています。なぜあなたは必要とするか、または使用したい一般的な目的の言語を?ビルドには、次のものが必要です。
あなたは本当に多くを必要としません。
ビルドシステムが、ある特定のユースケースに十分な柔軟性を持たないように思えるのは面倒ですが、ほとんどの人にとってはおそらく他のシステムよりもはるかに優れています。
それがおそらく、ほとんどのプログラム可能なプログラムよりも宣言型ビルドシステムを好む人々の間で極性がある理由です。開発者は、箱から抜け出す方法を探す自然な傾向があると思います。
もう1つの関連する質問は、「ビルドツールが本当に必要なのか」ということです。それらがすべての言語に存在するという事実は、そもそもそこにあるべきではないギャップを埋める兆候ではありませんか?
一部の言語では、ビルドツールは必ずしも必要ありません。たとえば、ほとんどのスクリプト言語は1つを必要とせず、ロード時に解決します。または、Goのコンパイラーがすべてを処理してくれるので、これは良い対抗策です。gccのようなコンパイラーが突然すべてのフラグ、リンカー、メイクファイルを必要としなかった場合はどうでしょうか。または、javacがbuild.xmlまたはpom.xmlを必要とせずに、何をすべきかを彼に指示した場合はどうなりますか?依存関係は最終的なプログラムの一部であるため、依存関係の管理を直接言語のツールの一部にすべきではありませんか?
確かに、ユーザー(ビルダー)にとってはるかに単純なアプローチのようです。彼らは内部でやっていることを主張し、そのビルドプロセスに影響を与えるあなたの選択と機会を奪いますが、そのようなツールがコンパイラの拡張などを許可することを望みます。さらに、ツールと言語を2つの別個の要素として見ていました。そのため、突然それらを密接に結び付けるのは不純に思えるかもしれません。
プログラムのビルドに使用する言語が問題ではないと思います。重要なのは、プログラミングに使用する言語とそのコアプラットフォームおよびツールであり、それについてはまだ前進しています。
個人的には、make / gmake / autotools / pmkを使用してCに満足しており、Javaを使い始めてからmakeを実行し、その後antを実行するようになりました。私はgradle、builder、その他に価値を見ることができますが、私はこれまでのところ、より重要な変化が起こるまで、mavenの流行が好きです。プラス私のようなそれは剛性のだが、それでも必要に応じて周りのこと、あなたに仕事する能力を残していること。簡単ではないというのは良いことです。
これはビルドツールです。それを受け入れることを学んで、それと戦ってはいけません。負けの戦いです。または、少なくとも非常に長いもの。
Java
される不可欠、言語Ant
、Maven
などです宣言型言語:
次のように違いを定義できます。
- 命令型プログラミング:「マシン」に何かをする方法を伝えると、結果として、あなたが何をしたいのかが起こります。
- 宣言型プログラミング:「マシン」に何をしたいのかを伝え、コンピューターにその方法を理解させます。1
ビルド言語は、ビルダーに何を行うべきか、どこから取るべきかなどを指示します。ビルドを実行するエンジン(@ElliottFrischのような命令型言語で記述されています)がこれらの指示を読み取り、それらを実行します。
宣言タスクはビルドシナリオでより適切に見えるかもしれません。ビルドタスクは全体的に同じであり、本格的なコード形式よりもその形式の方が保守性と可読性が高いと考えられるためです。
典型的なビルドシステムの機能を見ると、次のことがわかります。
いくつかの言語(Java / C#/ Python /など)を使用して一連のビルドファイルを作成する場合は、3番目または4番目の反復までに(a)ほとんどのデータと外部コマンドを何かのデータとして保持します。 XML(b)のように、お気に入りの言語で「ビルドエンジン」を記述します。
また、ビルドエンジンのさまざまな機能をトリガーするために、XMLのデータの一部をインタープリター言語として扱うと便利です。データの一部のマクロを解釈したり、文字列の置換を実行することもできます。
言い換えると、Make、Ant、Rake、またはMsBuildで終わることになります。それが上手くいくための命令型言語と、やりたいことを記述するデータ構造。通常はXMLで。
これらの場合、Java / C ++ / C#の使用には多くの要因が考慮されます。
まず、ビルドスクリプトを実行してアプリをビルドする前に、ビルドスクリプトをコンパイルする必要があります。ビルドスクリプトのビルドに必要なパッケージ、フラグ、コンパイラバージョン、ツールパスをどのように指定しますか?確かに、あなたはそれを回避する方法を思いつくことができますが、そのビルドステップを必要としない言語(例えばpython)を持っているか、ビルドツールがネイティブに理解する言語を持っている方がはるかに簡単です。
第二に、ビルドファイルはデータ量が多いのに対し、Java / C ++ / C#はコードやアルゴリズムの作成により適しています。Javaや友人は、保存したいすべてのデータを非常に簡潔に表現しているわけではありません。
第三に、Javaと友人は有効であるために多くの定型文を必要とします。ビルドファイルは、すべてのインポートを含むクラス内のメソッド内になければなりません。スクリプト言語またはカスタム言語を使用する場合、その定型文をすべて回避し、ビルドの詳細のみを保持できます。
確かに!人々がしばしば(当初)考えているよりも複雑な問題に、強力で表現力豊かな言語を使用してみませんか?特に問題に直面している人々がすでにそのような言語に精通している場合。(構築はプログラマー自身の問題であり、プログラマーによって最もよく解決されます。)
私もこの質問を数年前に自問し、Javaはビルド、特にJavaプロジェクトの定義に適した言語であると判断しました。そして、結果として、私はそれについて何かを始めました。
免責事項:この回答では、開発中のビルドシステムであるiwantを推進しています。しかし、これはとにかく意見を述べる議論なので、大丈夫だと確信しています。
Javaの利点(パワーと表現力)や具体的な欠点については詳しく説明しません。興味がある場合は、iwantページで詳細を読むことができます。
代わりに、Java(および他のGPL)がビルドに適さないとしてすぐに却下される理由を検討します。ここでの多くの回答とコメントは、そのような考え方の良い例です。典型的な議論のいくつかを考えてみましょう:
「Javaは必須ですが、ビルドは宣言的な方法で定義するのが最適です」と彼らは言うかもしれません。
本当です。しかし、内部DSLのメタ言語として言語を使用する場合、本当に重要なのはその構文です。Javaのような命令型言語でさえ、だまされて宣言型になることがあります。宣言的に見えると感じる場合、それは(実際的な目的のために)宣言的です。例えば:
JacocoTargetsOfJavaModules.with()
.jacocoWithDeps(jacoco(), modules.asmAll.mainArtifact())
.antJars(TestedIwantDependencies.antJar(),
TestedIwantDependencies.antLauncherJar())
.modules(interestingModules).end().jacocoReport(name)
これは、iwantのデモプロジェクトの実際の例です。
実際、これを「テスト」や「コンパイル」などの命令型の動詞にユーザーをさらす宣言型ビルドシステムと比較してください。上記の宣言には名詞のみが含まれ、動詞は含まれません。コンパイルとテストは、ユーザーに必要な名詞を付与するために、iwantによって暗黙的に処理されるタスクです。それは言語ではありません。それがあなたの使い方です。
「Javaは冗長です」
はい、多くのJavaコードは冗長です。しかし、繰り返しになりますが、それは言語ではなく、使用方法です。実装が冗長な場合は、素敵な抽象化の背後にカプセル化します。多くのGPLは、このための適切なメカニズムを提供します。
上記のJavaスニペットがXMLで記述されていることを想像してください。括弧を山括弧で置き換え、それらを移動します。そして、すべてのキーワードを終了タグとして複製します!構文としてのJava は冗長ではありません。
(XMLと比較することは、赤ちゃんからキャンディーを奪うようなものですが、非常に多くのビルドがたまたまXMLで定義されています。)
「ビルドスクリプトをコンパイルする必要があります」
これは有効なポイントです。それにもかかわらず、それは解決すべき小さな技術的問題にすぎません。beanshellまたは他のインタープリターを使用して解決できました。代わりに、単に別のビルドの問題として扱い、単純なJavaブートストラップをコンパイルして実行する単純なシェルまたはantスクリプトでブートストラップを行うことで解決しました。
「Javaには定型文があります」
本当です。クラスをインポートする必要があり、「public」、「class」などに言及する必要があります。そして、ここでは単純な外部DSLが最初の簡単な勝利を記録します。
そして、プロジェクトが非常に些細なもので、この定型句が重要な場合、おめでとうございます。あなたの問題は難しいものではなく、あなたがそれをどう解決するかは本当に問題ではありません。
しかし、多くのプロジェクトでは、コンパイル、カバレッジレポート、パッケージング以上のものが必要です。Javaのボイラープレートが顧客の問題に受け入れられる場合、問題を作成してみませんか?なぜ他人の子供専用の靴を作るのですか?
私が他の答えに取り組んでいないと思うことの一つは、これらのビルド言語の制限と透明性が、それらを有用にするものの大きな部分であるということです。たとえば、Mavenを見てみましょう。はい、ビルドを実行しますが、依存関係も定義します。これにより、Mavenビルドでこれらの依存関係を取得し、依存関係などを確認できます。
これがJavaで直接行われたかどうかを検討してください。ビルドツールは、依存関係があることを確認します。次に、他のJavaアプリケーションをプルダウンして実行し、依存関係を判断する必要があります。しかし、Mavenの場合は、依存関係の宣言のみを参照します。Mavenビルドファイルは透過的です。チューリング完全言語は本質的に非透過的であるため、このような一部の目的では劣っています。