Mengapa java tidak digunakan sebagai bahasa build?

24

Jika Java adalah bahasa tujuan umum, dan membangun sebuah program adalah sesuatu yang dapat dideskripsikan menggunakan bahasa Java, mengapa ini bukan cara terbaik untuk menulis file build dan sebaliknya kami menggunakan alat seperti Ant, Maven, dan Gradle? Bukankah itu lebih mudah, dan juga menghilangkan kebutuhan untuk belajar bahasa pemrograman lain? (BTW - pertanyaan ini juga dapat diterapkan ke bahasa lain, seperti C #)

vainolo
sumber
7
Anda mungkin memiliki pertanyaan yang sedikit lebih menarik tentang "mengapa bahasa tujuan umum tidak digunakan untuk bahasa build" - Maksud saya, C juga bukan bahasa build. Saya juga menyarankan melihat upacara sekitar mengkompilasi satu file .java di Jawa
8
Ini mungkin bisa digeneralisasi sebagai "Mengapa repot dengan DSL?"
FrustratedWithFormsDesigner
1
Pertanyaan yang lebih baik mungkin; mengapa IDE / kompiler / alat sangat buruk sehingga alat membangun dibutuhkan di tempat pertama.
Brendan
6
@ Brendan itu bukan pertanyaan karena build tools dan IDE melayani tujuan yang berbeda.
jwenting
1
Karena bahasa "tujuan umum" tidak boleh digunakan daripada bahasa khusus domain yang didefinisikan dengan baik dan sederhana. Dan, jika kebutuhan untuk belajar "bahasa pemrograman lain" menyangkut Anda, Anda seharusnya tidak benar-benar pemrograman, cobalah beberapa perdagangan lainnya.
SK-logic

Jawaban:

21

Alat Khusus untuk Tujuan Khusus

  • Verbositas

    Bahasa tujuan umum seringkali terlalu bertele-tele. Jika saya harus mengelola bangunan di Jawa, saya akan sangat tertekan dengan ukuran binatang itu. Namun, ini bisa dengan mudah dikelola menggunakan DSL yang ditulis dalam Java. Dan sampai batas tertentu itulah cara Anda dapat melihat Gradle (untuk Groovy) dan Buildr (untuk Ruby).

  • Kesulitan

    Bahasa tujuan umum sulit. Yah saya tidak berpikir pemrograman itu sulit dan tidak dapat diambil oleh siapa pun, tetapi intinya adalah: insinyur bangunan Anda belum tentu programmer Anda!

  • Tujuan

    Itu kurang lebih di persimpangan kesulitan dan kata kerja . Bahasa dirancang untuk suatu tujuan, dan di sini kita berbicara tentang sesuatu yang sangat spesifik. Jadi mengapa Anda perlu atau ingin menggunakan bahasa tujuan umum ? Untuk bangunan, Anda perlu:

    • cabang dan kondisional untuk menangani konfigurasi terpisah, lingkungan, dll ...
    • seperangkat instruksi untuk mengekstrak data dari lingkungan Anda,
    • seperangkat instruksi untuk menghasilkan kiriman.

    Anda tidak benar-benar membutuhkan lebih banyak.

Tentu itu menjengkelkan ketika sistem build Anda sepertinya tidak cukup fleksibel untuk satu kasus penggunaan khusus yang Anda kejar, tetapi mungkin jauh lebih baik daripada alternatif bagi kebanyakan orang.

Itu mungkin mengapa ada polaritas antara orang-orang yang lebih suka sistem deklaratif membangun daripada kebanyakan onces diprogram: Saya kira seorang pengembang mungkin memiliki kecenderungan alami untuk mencari cara untuk keluar dari kotak.

Tunggu, Apakah Kami Benar-Benar Membutuhkan Alat?

Pertanyaan terkait lainnya adalah: apakah kita benar-benar membutuhkan alat bangun? Bukankah fakta bahwa mereka ada dalam semua bahasa pertanda bahwa mereka mengisi celah yang bahkan seharusnya tidak ada di tempat pertama?

Beberapa bahasa tidak selalu memerlukan alat bangun. Misalnya, sebagian besar bahasa skrip tidak memerlukannya dan diselesaikan pada waktu buka. Atau take Go, yang kompilernya akan menangani segalanya untuk Anda, yang merupakan tandingan yang bagus: bagaimana jika kompiler seperti gcc tiba-tiba tidak memerlukan banyak bendera, tautan, dan file makefile untuk mati semuanya bersama-sama? Atau jika javac tidak memerlukan build.xml atau pom.xml untuk memberitahunya apa yang harus dilakukan? Tidakkah manajemen ketergantungan secara langsung menjadi bagian dari perangkat bahasa itu sendiri, karena dependensi merupakan bagian dari program akhir?

Tentunya sepertinya pendekatan yang jauh lebih sederhana bagi pengguna (pembangun). Meskipun orang dapat berargumen bahwa mereka hanya melakukan di bawah tenda dan mengambil pilihan dan peluang Anda untuk mempengaruhi proses pembuatan itu (tapi kemudian Anda berharap alat seperti itu memungkinkan ekstensi kompiler dan hal-hal serupa). Ditambah lagi, kami biasa melihat alat dan bahasa sebagai dua hal yang terpisah, jadi dia mungkin tampak tidak yakin untuk tiba-tiba memilikinya digabungkan secara ketat.

Saya tidak berpikir bahasa yang Anda gunakan untuk membangun program Anda adalah masalah. Ini adalah bahasa yang Anda gunakan untuk memprogram dan platform intinya dan alat yang penting, dan kami masih membuat kemajuan dalam hal itu.


Secara pribadi, saya telah menggunakan make / gmake / autotools / pmk dan senang dengan mereka untuk C, dan saya mulai dengan Java ketika yang kami miliki hanyalah membuat, lalu semut, dan sekarang saya umumnya lebih memilih Maven daripada semua alternatif ini. Meskipun saya dapat melihat nilai dalam gradle, buildr dan lainnya, tetapi saya suka prevalensi pakar sejauh ini, sampai pergeseran yang lebih signifikan terjadi. Ditambah lagi, saya suka itu kaku, tetapi masih memberi Anda kemampuan untuk mengatasinya jika perlu. Itu tidak mudah adalah hal yang baik.

Ini alat membangun. Belajarlah untuk merangkulnya dan jangan melawannya. Ini pertempuran yang kalah. Atau setidaknya yang sangat sangat panjang.

haylem
sumber
Sangat menyukai pragmatisme Anda. Pertanyaan saya keluar karena penasaran. Saya menggunakan pakar (pernah menggunakan make dan semut di masa lalu), dan itu memang "ilmu hitam" yang kadang-kadang baik dan kadang-kadang buruk. Tapi itu masih ajaib.
vainolo
1
"Atau jika javac tidak memerlukan build.xml atau pom.xml untuk memberitahunya apa yang harus dilakukan?" - heh. tidak dan tidak pernah melakukannya.
user253751
@immibis: itu bisa diperdebatkan. Saya tidak akan benar-benar menikmati membangun proyek-proyek saya di kantor hanya dengan javac :) Tentu saja akan membutuhkan sedikit lem dengan Makefile atau skrip shell atau paling tidak alias shell untuk menyatukan semuanya. Atau program raksasa dengan semua yang ada di satu folder dan semua depo di repo. Bukan sesuatu yang saya sukai! :) Tapi itu perdebatan lain sepenuhnya, tidak terkait dengan pertanyaan OP.
haylem
Mengintegrasikan sistem build dengan bahasa juga bermasalah untuk proyek polyglot. Jika saya menggunakan bahasa A dan B dan ingin memiliki satu proses build untuk mereka, sistem build bahasa mana yang saya gunakan?
Sebastian Redl
@SebastianRedl Jadi bagaimana masalahnya menjadi lebih mudah dengan memperkenalkan bahasa ketiga ? Pilih saja bahasa yang lebih baik untuk Anda. (Dan tentu saja, jika Anda membutuhkan bahasa ketiga, Jawa juga bisa seperti itu.)
Ville Oikarinen
21

Javaadalah sebuah keharusan bahasa, Ant, Maven, dll deklaratif bahasa:

Kita dapat mendefinisikan perbedaan sebagai berikut:

  • Pemrograman imperatif: memberi tahu "mesin" bagaimana melakukan sesuatu, dan akibatnya apa yang Anda inginkan akan terjadi.
  • Pemrograman deklaratif: memberi tahu "mesin" apa yang Anda inginkan terjadi, dan biarkan komputer mengetahui bagaimana melakukannya. 1

Bahasa build memberi tahu builder apa yang harus dilakukan, dari mana harus diambil, dll. Mesin yang menjalankan build (yang ditulis dalam bahasa imperatif, seperti yang dicatat oleh @ElliottFrisch), membaca instruksi ini, dan memenuhinya.

Bahasa deklaratif mungkin tampak lebih tepat dalam membangun skenario, karena membangun tugas umumnya sama di seluruh, dan dianggap lebih dapat dipelihara dan dibaca dalam bentuk itu daripada dalam bentuk kode lengkap.

Uri Agassi
sumber
3
Setidaknya ada satu sistem build yang menggunakan bahasa imperatif. Scons menggunakan Python.
user16764
Membuatnya penting tidak lebih sulit daripada menulis kelas yang dapat berisi daftar dependensi, dan metode untuk menyelesaikan dependensi tersebut. Saya curiga ada alasan lain --- seperti waktu startup JVM, mungkin.
2
@ Lee: Hampir semua alat pembuatan yang digunakan di dunia Java (Semut, Maven, Gradle, SBT, ...) juga biasanya berjalan di JVM (dengan pengecualian Rake, Buildr atau Scons, yang bisa , tetapi tidak memiliki untuk berjalan di JVM).
Jörg W Mittag
6
@ vainolo "Kebanyakan orang tidak terlalu suka Ant / Maven / Make" benar-benar? Itu pernyataan yang berani!
Ben Thurley
1
@BenThurley Saya orang suka membuatnya, mengapa semut dibuat? dan jika semut disukai, mengapa pakar? Dan sekarang mengapa orang menggunakan Gradle? Tapi saya setuju bahwa itu adalah pernyataan yang berani, dan itu hanya didukung oleh bukti "anekdotal" dari beberapa puluhan pengembang java
vainolo
4

Jika Anda melihat fitur-fitur sistem build tipikal yang Anda temukan:

  1. Banyak data: nama, sakelar, pengaturan, item konfigurasi, string, dll
  2. Banyak interaksi dengan lingkungan: perintah, variabel lingkungan
  3. "Build engine" yang relatif mudah menangani dependensi, threading, logging dll.

Jika Anda mulai menulis serangkaian file build menggunakan beberapa bahasa (Java / C # / Python / etc), sekitar iterasi ketiga atau keempat Anda akan puas dengan (a) menjaga sebagian besar data dan perintah eksternal sebagai data dalam sesuatu seperti XML (b) menulis "mesin pembuat" dalam bahasa favorit Anda.

Anda juga akan merasa berguna untuk memperlakukan beberapa data dalam XML Anda sebagai bahasa yang ditafsirkan, untuk memicu berbagai fitur dalam mesin pembuat. Anda juga dapat menginterpretasikan beberapa makro atau melakukan penggantian string, dalam data.

Dengan kata lain, Anda akan selesai dengan Make, atau Ant, atau Rake, atau MsBuild. Bahasa imperatif untuk hal-hal yang dilakukannya dengan baik, dan struktur data untuk menggambarkan apa yang ingin Anda lakukan, sekarang biasanya dalam XML.

david.pfx
sumber
2

Sejumlah faktor diperhitungkan terhadap penggunaan Java / C ++ / C # dalam kasus ini.

Pertama, Anda harus mengkompilasi skrip build Anda sebelum dapat menjalankannya untuk membangun aplikasi Anda. Bagaimana Anda menentukan paket, flag, versi kompiler, jalur alat apa saja yang diperlukan untuk membangun skrip build Anda? Tentu saja, Anda dapat menemukan cara untuk mengatasinya, tetapi jauh lebih mudah untuk memiliki bahasa yang tidak memerlukan langkah build (misalnya python) atau bahasa yang dipahami oleh alat build Anda.

Kedua, file build adalah data yang berat sedangkan Java / C ++ / C # jauh lebih diarahkan untuk menulis kode dan algoritma. Java dan teman-teman tidak memiliki representasi yang sangat ringkas dari semua data yang ingin Anda simpan.

Ketiga, Java dan teman-teman membutuhkan banyak boilerplate agar valid. File build harus berada di dalam metode di dalam kelas dengan semua impornya. Saat menggunakan bahasa skrip atau bahasa khusus, Anda dapat menghindari semua itu dan hanya memiliki detail build sendiri.

Winston Ewert
sumber
0

Memang! Mengapa tidak menggunakan bahasa yang kuat dan ekspresif untuk masalah yang lebih kompleks daripada yang sering orang (awalnya) pikirkan? Apalagi ketika orang yang menghadapi masalah sudah kompeten dengan bahasa seperti itu. (Bangunan adalah masalah pemrogram sendiri dan paling baik dipecahkan oleh pemrogram.)

Saya juga bertanya pada diri sendiri pertanyaan ini bertahun-tahun yang lalu dan memutuskan bahwa Jawa adalah bahasa yang baik untuk mendefinisikan bangunan, terutama untuk proyek-proyek Jawa. Dan, sebagai hasilnya, saya mulai melakukan sesuatu tentang itu.

DISCLAIMER : Dalam jawaban ini saya mempromosikan iwant , sistem build yang saya kembangkan. Tapi karena ini adalah diskusi pendapat, saya yakin tidak apa-apa.

Saya tidak akan menguraikan manfaat Jawa (kekuatan dan ekspresif) atau saya ingin secara khusus. Jika Anda tertarik, Anda dapat membaca lebih lanjut di halaman iwant .

Sebagai gantinya saya akan mempertimbangkan mengapa Java (dan GPL lainnya) begitu mudah diberhentikan sebagai tidak sesuai untuk pembangunan. Banyak jawaban dan komentar di sini adalah contoh bagus dari pemikiran seperti itu. Mari kita pertimbangkan beberapa argumen umum:

"Java sangat penting, tetapi build paling baik didefinisikan dengan cara deklaratif" , kata mereka.

Benar. Tetapi ketika menggunakan bahasa sebagai bahasa logam untuk DSL internal , yang benar-benar diperhitungkan adalah sintaksisnya . Bahkan bahasa imperatif seperti Java dapat diakali menjadi deklaratif. Jika terlihat dan terasa deklaratif, itu (untuk tujuan praktis) deklaratif. Sebagai contoh:

JacocoTargetsOfJavaModules.with()
    .jacocoWithDeps(jacoco(), modules.asmAll.mainArtifact())
    .antJars(TestedIwantDependencies.antJar(),
            TestedIwantDependencies.antLauncherJar())
    .modules(interestingModules).end().jacocoReport(name)

Ini adalah contoh nyata dari proyek demo iwant .

Faktanya, bandingkan ini dengan beberapa sistem build yang seharusnya deklaratif yang mengekspos pengguna mereka pada kata kerja imperatif seperti "test" atau "compile". Deklarasi di atas hanya berisi kata benda, tanpa kata kerja. Kompilasi dan pengujian adalah tugas-tugas yang secara implisit ditangani oleh iwant untuk memberikan pengguna kata benda yang diinginkannya. Itu bukan bahasa. Begitulah cara Anda menggunakannya.

"Java is verbose"

Ya, banyak kode Java di luar sana yang verbose. Tetapi sekali lagi, itu bukan bahasa, itu bagaimana Anda menggunakannya. Jika suatu implementasi bertele-tele, cukup enkapsulasi di balik abstraksi yang bagus. Banyak GPL menyediakan mekanisme yang memadai untuk ini.

Bayangkan saja cuplikan Java di atas yang ditulis dalam XML. Ganti tanda kurung dengan kurung sudut dan pindahkan. Dan duplikat setiap kata kunci sebagai tag penutup! Java sebagai sintaks yang tidak verbose.

(Saya tahu, membandingkan dengan XML seperti mengambil permen dari bayi, tetapi banyak bangunan yang didefinisikan dalam XML.)

"Anda harus mengkompilasi skrip pembuatan Anda"

Ini adalah poin yang valid. Namun demikian, ini hanya masalah teknis kecil yang harus dipecahkan. Saya bisa menyelesaikannya dengan menggunakan beanhell atau penerjemah lain. Sebagai gantinya, saya menyelesaikannya dengan memperlakukannya hanya sebagai masalah build dan bootstrap iwant dengan shell sederhana atau skrip semut yang mengkompilasi dan menjalankan bootstrapper Java sederhana.

"Java memiliki boilerplate"

Benar. Anda harus mengimpor kelas, Anda harus menyebutkan "publik", "kelas" dan sebagainya. Dan di sini DSL eksternal sederhana mencetak kemenangan awal yang mudah.

Dan jika proyek Anda sangat sepele sehingga boilerplate ini signifikan, selamat. Masalah Anda bukan yang sulit dan benar-benar tidak masalah bagaimana Anda menyelesaikannya.

Tetapi banyak proyek membutuhkan lebih dari kompilasi, laporan cakupan dan pengemasan. Jika boilerplate Java dapat diterima untuk masalah pelanggan, mengapa tidak membangun masalah? Mengapa hanya membuat sepatu untuk anak-anak orang lain?

Ville Oikarinen
sumber
0

Satu hal yang menurut saya tidak dijawab oleh jawaban lain adalah bahwa keterbatasan dan transparansi bahasa-bahasa bangunan ini adalah bagian besar dari apa yang membuatnya bermanfaat. Mari kita ambil Maven, misalnya. Ya, itu mengeksekusi build tetapi juga mendefinisikan dependensi. Hal ini memungkinkan untuk membangun Maven untuk menarik turun dependensi tersebut dan melihat dependensi mereka dan seterusnya dan seterusnya.

Pertimbangkan apakah ini dilakukan dengan Java secara langsung. Alat build akan melihat bahwa ada ketergantungan. Maka perlu menarik ke bawah sehingga aplikasi Java lain dan menjalankannya untuk menentukan apa dependensi itu. Tetapi untuk Maven, itu hanya melihat deklarasi ketergantungan. File build maven transparan. Bahasa lengkap Turing secara inheren tidak transparan dan oleh karena itu lebih rendah untuk beberapa tujuan seperti ini.

JimmyJames
sumber
Bagaimana Gradle cocok dengan ini? Ini mendefinisikan dependensi dalam gaya deklaratif, menggunakan bahasa tujuan umum (Groovy). Dalam alat yang berbasis Groovy, JavaScript atau Lisp, adalah wajar untuk menggunakan kompiler atau penerjemah bahasa untuk menguraikan deklarasi, apakah Anda hanya ingin membacanya atau 'mengeksekusi' mereka (menerapkan beberapa fungsi). Bahwa dualitas kode dan data bukan bagian dari idiom Java yang diterima secara umum, meskipun bukan tidak mungkin. Kelengkapan Turing tidak mencegah representasi data yang baik. Itu membuka kemungkinan data Anda akan melakukan sesuatu yang tidak Anda harapkan.
joshp
@ joshp Saya tidak terbiasa dengan Gradle. Ini digambarkan sebagai DSL dan hal-hal terlihat agak deklaratif. Berbasis pada Groovy tidak berarti setara dengan Groovy dalam kekuatannya. Anda mungkin berada dalam posisi yang lebih baik untuk mengatakan apakah Gradle sebenarnya adalah bahasa lengkap Turing. Contoh ketergantungan yang saya lihat tampak cukup sederhana. Bisakah Anda menggunakan ekspresi Groovy yang sewenang-wenang dalam hal-hal seperti pernyataan dependensi?
JimmyJames
Secara pribadi saya bahkan tidak suka dependensi transitif. Seringkali mereka hanya menimbulkan kejutan di classpath (beberapa versi perpustakaan yang tidak kompatibel). Itu sebabnya pakar memiliki elemen mengecualikan, tetapi kerumitan tidak hanya sepadan. Ketergantungan yang eksplisit membuat hidup lebih sederhana. Namun, dependensi transitif dapat diimplementasikan dengan Java. Saya telah melakukan sesuatu seperti itu dengan iwant dengan menggunakan kembali membangun definisi proyek lain.
Ville Oikarinen
@VilleOikarinen Saya kebetulan setuju dengan Anda. Saya pikir itu juga menyebabkan ton gembung karena tidak ada biaya yang dirasakan untuk menarik lebih banyak dependensi bahkan jika Anda tidak menggunakannya. Namun, dalam konteks jawaban ini, saya tidak mengomentari nilai atau kebijaksanaan fitur itu tetapi tentang bagaimana penggunaan DSL berguna dalam mencapainya.
JimmyJames
1
@VilleOikarinen Saya pikir kita sudah mencapai akhir ini, tetapi saya hanya ingin menjelaskan bahwa saya tidak berbicara tentang pom / maven. Ini adalah contoh DSL build tetapi saya tidak terlalu memikirkannya. Saya menggunakannya dengan enggan dan saya pikir itu kikuk. Tapi yang paling dominan adalah deklarasi ketergantungan. Saya menggunakan Buildr untuk sementara dan membaca pom untuk dependensi tetapi tidak menggunakannya untuk spesifikasi build. Ada sejumlah alat yang bukan berbasis Java yang memahami pom ini tetapi AFAIK, yang mereka pedulikan hanyalah dependensi.
JimmyJames