Apakah "konvensi konfigurasi" tidak melanggar prinsip pemrograman dasar?

51

Saya melihat kerangka WPV MVVM Caliburn.Micro dan membaca bahwa banyak hal standar didasarkan pada konvensi penamaan .

Misalnya, pengikatan properti secara otomatis di View ke properti di ViewModel. Meskipun ini tampaknya nyaman (menghapus beberapa kode boilerplate), reaksi insting pertama saya adalah bahwa itu tidak sepenuhnya jelas bagi seorang programmer baru yang akan membaca kode ini. Dengan kata lain, fungsionalitas aplikasi tidak sepenuhnya dijelaskan oleh kodenya sendiri, tetapi juga oleh dokumentasi kerangka kerja.

SUNTING:

Jadi pendekatan ini disebut convention over configuration. Karena saya tidak dapat menemukan pertanyaan mengenai hal ini, saya mengubah pertanyaan saya:

Pertanyaanku adalah:

Apakah konvensi mengenai konfigurasi adalah cara yang benar untuk menyederhanakan hal-hal, atau itu melanggar beberapa prinsip pemrograman (dan jika demikian, yang mana)?

Geerten
sumber
8
Sebagian besar pendekatan / prinsip melanggar beberapa pendekatan / prinsip lain sampai tingkat tertentu. Ini sebagian besar masalah prioritas dan pertukaran.
Joachim Sauer
1
Benar, tetapi saya menemukan perbedaan yang dinyatakan dalam pertanyaan saya agak aneh, dan karena itu saya tertarik pada trade-off tertentu dan mungkin melanggar prinsip ketika menggunakan konvensi tentang konfigurasi.
Geerten
Konsep keterlacakan perangkat lunak relevan di sini. Pemrogram bergantung pada alat seperti grep, tetapi membutuhkan alat yang lebih baik untuk melacak penggunaan kode yang dihasilkan. Sebagai contoh, alat harus membuatnya lebih eksplisit bahwa kelas css "user-id" terkait dengan metode yang dihasilkan getUserId () dan kolom tabel user_id.
Macneil

Jawaban:

49

Saya tidak menganggap "aplikasi harus sepenuhnya dijelaskan oleh kode sendiri" prinsip dasar pemrograman. Ada banyak dan banyak hal yang tidak dijelaskan dengan hanya melihat kode aplikasi. Selain mengetahui hal-hal dasar dari bahasa pemrograman itu sendiri (sintaks dan semantik), Anda perlu mengetahui konvensi. Jika pengenal di Jawa dimulai dengan huruf kapital, itu adalah tipe. Ada banyak konvensi yang perlu Anda ketahui.

Konvensi tentang konfigurasi adalah tentang mengurangi jumlah keputusan yang harus dibuat oleh programmer tentang berbagai hal. Untuk beberapa hal ini jelas - tidak ada yang akan mempertimbangkan memiliki bahasa di mana huruf besar jenis adalah sesuatu yang Anda perlu nyatakan di bagian atas program Anda - tetapi untuk hal-hal lain itu tidak begitu jelas.

Menyeimbangkan konvensi dan konfigurasi adalah tugas yang sulit. Terlalu banyak konvensi dapat membuat kode membingungkan (sebagai contoh, ambil variabel implisit Perl). Terlalu banyak kebebasan di sisi programmer dapat membuat sistem sulit untuk dipahami, karena pengetahuan yang didapat dari satu sistem jarang berguna ketika mempelajari yang lain.

Contoh yang bagus dari mana konvensi bantu programmer adalah ketika menulis plugin Eclipse. Saat melihat sebuah plugin yang belum pernah saya lihat, saya langsung tahu banyak hal tentangnya. Daftar dependensi ada di MANIFEST.MF, titik ekstensi ada di plugin.xml, kode sumbernya di bawah "src", dan seterusnya. Jika hal-hal ini tergantung pada programmer untuk menentukan, setiap plugin Eclipse tunggal akan berbeda, dan navigasi kode akan jauh lebih sulit.

JesperE
sumber
4
+1: pengembangan perangkat lunak cukup rumit. Jika Anda dapat menghindari kompleksitas dalam hal-hal yang Anda kendalikan, lakukanlah. Simpan kerumitan untuk tempat-tempat yang benar-benar Anda butuhkan.
scrwtp
1
Terima kasih atas penjelasan yang jelas tentang perbedaan dan keseimbangan.
Geerten
3
"Jika pengenal di Jawa dimulai dengan huruf kapital, itu adalah tipe." - apakah itu tipe tergantung pada konteks sintaksis bukan pada pola penamaan, konvensi penamaan Java tidak mempengaruhi 'konfigurasi kompilasi'. Apakah Anda yakin ini adalah contoh yang valid? Contoh terakhir tidak benar juga - ini tentang "konvensi konfigurasi" bukan "konvensi konfigurasi". Anda mengatakan hal-hal yang benar tetapi tidak ada hubungannya dengan prinsip subj.
Den
4
Jangan terlalu menganalisis contoh, mereka hanya contoh. Yang pertama hanyalah contoh dari konvensi, yang terakhir adalah contoh di mana konvensi adalah hal yang baik. Contoh Perl adalah contoh di mana terlalu banyak konvensi (implisit) adalah hal yang buruk (IMO, saya harus menambahkan).
JesperE
1
Hal yang saya benci adalah ketika konvensi tentang konfigurasi menjadi konvensi tanpa konfigurasi ... dalam kasus terakhir Anda cenderung terjebak dengan basis kode mungkin sulit untuk diintegrasikan dengan alat lain.
Andy
77

Memberi +1 ke @JesperE, dan ingin menambahkan sesuatu:

apakah itu melanggar beberapa prinsip pemrograman

Ya, "konvensi konfigurasi" melanggar prinsip "eksplisit lebih baik daripada implisit" (lihat, misalnya, di "Zen-Of-Python" ).

Di sisi lain, "konfigurasi atas konvensi" yang berlawanan cenderung melanggar "Sederhana lebih baik daripada kompleks", dan lebih buruk lagi, itu melanggar prinsip KERING dengan cara yang halus, karena Anda perlu mengulangi nama yang digunakan dalam kode Anda juga dalam konfigurasi Anda .

Doc Brown
sumber
4
Itu jawaban paling langsung untuk pertanyaan itu!
Joachim Sauer
Ini adalah jawaban benar yang sebenarnya di antara dua yang paling dipilih.
Den
+1 untuk "eksplisit lebih baik daripada implisit"
Justin Ohms
12
Bagian favorit saya tentang jawaban ini adalah bahwa hal itu secara implisit menyoroti kenyataan daripada prinsip-prinsip pengembangan perangkat lunak yang baik sering duduk dalam ketegangan satu sama lain. Rekayasa adalah tentang menyeimbangkan ketegangan-ketegangan itu dengan tepat untuk konteks dan aplikasi spesifik Anda.
Chris Krycho
Jawaban yang bagus. Untuk memperluas komentar @Chris Krycho, hal yang menyenangkan tentang standar atau prinsip perangkat lunak adalah Anda memiliki begitu banyak pilihan. :-)
user949300
9

Beberapa "convention over configuration" hanya bermuara pada default yang masuk akal. Anda hanya perlu mengkonfigurasi sesuatu untuk menggunakannya untuk tujuan non-standar. Saya harus membandingkan Struts dengan Rails di sini. Di Rails, Anda harus meletakkan "tindakan / layar" Anda di folder dan kemudian hanya berfungsi. Di Struts, Anda masih harus meletakkannya di folder, tetapi Anda juga harus membuat nama tindakan DAN file JSP DAN nama formulir DAN kacang formulir DAN tentukan bagaimana ketiga hal ini bekerja bersama di Struts-config. xml DAN tentukan bahwa formulir tersebut adalah milik permintaan (RESTful). Jika itu tidak cukup, pemetaan form / form-bean memiliki bagiannya sendiri di Struts-config yang kemudian dipetakan secara independen ke bagian tindakan dalam file yang sama dan semuanya bergantung pada string tulisan tangan dalam file JSP untuk bekerja tepat. Untuk setiap layar, itu setidaknya 6 hal yang tidak harus Anda lakukan dan banyak peluang untuk membuat kesalahan. Saya pikir Anda dapat mengatur sebagian besar atau semua hal itu secara manual di Rails jika Anda perlu, tetapi 2/3 dari waktu pengembangan Struts diambil untuk membangun dan mempertahankan lapisan kompleksitas yang tidak perlu.

Dalam semua keadilan, Struts 1 dirancang ketika orang porting aplikasi antara desktop dan web. Fleksibilitas yang telah dibuat oleh Struts membuatnya cocok untuk segala yang dilakukan Rails, plus semua yang dibutuhkan oleh aplikasi desktop. Sayangnya, kumpulan konfigurasi yang memungkinkan fleksibilitas adalah bola dan rantai besar bagi seseorang yang hanya perlu menulis aplikasi web atau hanya aplikasi desktop.

Saya bekerja di suatu tempat bahwa mereka mengambil langkah berikutnya dan berpendapat, "Konfigurasi atas Kode " tetapi setelah melihat yang dibawa ke ekstrim logis, hasilnya adalah bahwa konfigurasi menjadi bahasa pengkodean baru. Itu adalah permainan shell di mana kompleksitas didorong tanpa dijinakkan dengan cara yang signifikan. Dan itu memberi saya penghargaan untuk semua jenis pengecekan dan jaring pengaman lainnya yang dimiliki oleh bahasa pemrograman yang dirancang dengan baik. Beberapa format file konfigurasi setengah matang yang meledak tanpa pesan kesalahan jika Anda menambahkan spasi atau tanda baca BUKAN perbaikan atas bahasa pemrograman berkualitas yang memiliki rangkaian alat pengeditan dan kompiler berkualitas yang ditulis untuk itu.

Saya tidak bisa membayangkan bahwa memiliki standar yang masuk akal melanggar prinsip teoritis tentang ekstensibilitas dan modularitas. Seorang programmer Ruby / Rails akan lebih cepat memasukkan poker panas di mata mereka daripada beralih ke kerangka kerja seperti Struts 1 di mana semua konfigurasi dibuat secara eksplisit dalam beberapa file XML. Saya tidak memperdebatkan Rails vs Struts IN GENERAL, tetapi konvensi itu bisa menjadi kemenangan produktivitas yang sangat besar. Kedua teknologi ini adalah perbandingan dunia nyata paling ekstrem yang pernah saya jumpai.

Jika Anda bekerja di Jawa sama sekali, lihat Joshua Bloch's, "Java Efektif," Butir 2: "Pertimbangkan Builder ketika dihadapkan dengan banyak parameter konstruktor" hlm. 11-16. Untuk sebagian besar tujuan, beberapa parameter (konfigurasi) diperlukan, dan beberapa bersifat opsional. Ide dasarnya adalah hanya memerlukan konfigurasi yang diperlukan dan hanya membuat pengguna (yang bisa menjadi program lain) menentukan opsi tambahan yang diperlukan. Saya membersihkan banyak kode dengan pola ini sebulan yang lalu dan itu berkilau positif.

GlenPeterson
sumber
7

Dengan kata lain, fungsionalitas aplikasi tidak sepenuhnya dijelaskan oleh kodenya sendiri, tetapi juga oleh dokumentasi kerangka kerja.

Fungsionalitas aplikasi yang menggunakan kerangka kerja selalu bergantung pada kerangka kerja, konvensi atas konfigurasi tidak membuat perbedaan dalam hal itu.

Dalam pengalaman saya, konvensi konfigurasi tidak hanya membuat kode lebih mudah dibaca, tetapi juga mengurangi kemungkinan untuk memperkenalkan bug halus (terutama copy-paste-bug).

Misalnya, mari kita asumsikan dalam beberapa kerangka A, acara FooBarmemicu panggilan ke handleFooBar. Dalam kerangka B lainnya, korelasi ini dikonfigurasi di suatu tempat di file XML.

Jadi, di A, sederhana saja

handleFooBar() {
   ...
}

dan kecuali Anda telah salah mengeja FooBar, itu akan dipanggil setiap kali FooBar terjadi.

Di B, itu lagi

handleFooBar() {
   ...
}

tetapi juga

<eventconfiguration>
  <event>
    <type>FooBar</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

Dengan ratusan hal untuk dikonfigurasikan dengan cara ini, sangat mudah untuk membuat bug yang tidak disengaja

<eventconfiguration>
  <event>
    <type>BarFoo</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

karena setelah copy paste, kami hanya berubah <type>tetapi lupa untuk berubah <handler>.

Karena file-file konfigurasi itu besar dan monoton, kecil kemungkinan seseorang akan menemukan bug dengan proofreading daripada dia akan menemukan bug yang sama dalam kode program yang sebenarnya.

pengguna281377
sumber
1
1: menghindari berulang, membosankan-to-write, hard-to-baca, konfigurasi hampir-selalu-jelas adalah yang keuntungan utama dari konvensi-over-konfigurasi.
Joachim Sauer
-1

Ini mungkin melanggar beberapa prinsip, tetapi pada saat yang sama mematuhi salah satu prinsip desain yang paling mendasar, SRP (Single Responsibility Principle).

rai.skumar
sumber
2
Menggunakan konvensi tidak ada hubungannya dengan tanggung jawab tunggal. Saya bisa menggunakan konvensi dan melakukan 100 hal di dalamnya.
Suamere