Saya memulai proyek grup sekolah di Jawa, menggunakan Swing. Ini adalah GUI langsung pada aplikasi desktop Database.
Profesor memberi kami kode dari proyek tahun lalu sehingga kami bisa melihat bagaimana dia melakukan sesuatu. Kesan awal saya adalah bahwa kode ini jauh lebih rumit dari yang seharusnya, tetapi saya membayangkan programmer sering berpikir ini ketika melihat kode yang tidak hanya mereka tulis.
Saya berharap menemukan alasan mengapa sistemnya baik atau buruk. (Saya bertanya kepada profesor dan dia berkata saya akan melihat nanti mengapa itu lebih baik, yang tidak memuaskan saya.)
Pada dasarnya, untuk menghindari sambungan antara objek, model (logika bisnis), dan pandangannya yang bertahan lama, semuanya dilakukan dengan string. Objek yang bertahan yang disimpan dalam database adalah hashtables dari string, dan model dan tampilan "berlangganan" satu sama lain, memberikan kunci string untuk "peristiwa" yang mereka ikuti.
Ketika suatu peristiwa dipicu, tampilan atau model mengirimkan string ke semua pelanggannya yang memutuskan apa yang harus dilakukan untuk peristiwa itu. Misalnya, dalam salah satu metode pendengar tindakan tampilan (saya percaya ini hanya menetapkan bicycleMakeField pada objek yang dapat bertahan):
else if(evt.getSource() == bicycleMakeField)
{
myRegistry.updateSubscribers("BicycleMake", bicycleMakeField.getText());
}
Panggilan itu akhirnya sampai ke metode ini dalam model Kendaraan:
public void stateChangeRequest(String key, Object value) {
... bunch of else ifs ...
else
if (key.equals("BicycleMake") == true)
{
... do stuff ...
Profesor itu mengatakan bahwa cara melakukan hal-hal ini lebih dapat diperluas dan dipelihara daripada memiliki pandangan cukup memanggil metode pada objek logika bisnis. Dia mengatakan tidak ada hubungan antara pandangan dan model karena mereka tidak tahu keberadaan satu sama lain.
Saya pikir ini adalah jenis sambungan yang lebih buruk, karena tampilan dan model harus menggunakan string yang sama agar dapat bekerja. Jika Anda menghapus tampilan atau model, atau membuat kesalahan ketik dalam string, Anda tidak mendapatkan kesalahan kompilasi. Itu juga membuat kode jauh lebih lama daripada yang saya pikir perlu.
Saya ingin membahas hal ini dengannya, tetapi dia menggunakan pengalaman industrinya untuk membantah setiap argumen yang mungkin saya, siswa yang tidak berpengalaman, buat. Apakah ada beberapa keuntungan dari pendekatannya yang saya lewatkan?
Untuk memperjelas, saya ingin membandingkan pendekatan di atas, dengan memiliki pandangan yang jelas digabungkan dengan model. Misalnya, Anda bisa meneruskan objek model kendaraan ke tampilan, lalu mengubah "make" kendaraan, lakukan ini:
vehicle.make = bicycleMakeField.getText();
Ini akan mengurangi 15 baris kode yang saat ini HANYA digunakan untuk mengatur merek kendaraan di satu tempat, menjadi satu baris kode yang dapat dibaca. (Dan karena operasi semacam ini dilakukan ratusan kali di seluruh aplikasi, saya pikir ini akan menjadi kemenangan besar untuk keterbacaan serta keamanan.)
Memperbarui
Pemimpin tim saya dan saya merestrukturisasi kerangka kerja seperti yang kami inginkan dengan menggunakan pengetikan statis, memberi tahu profesor, dan akhirnya memberinya demo. Dia cukup dermawan untuk membiarkan kita menggunakan kerangka kerja kita selama kita tidak meminta bantuannya, dan jika kita dapat menjaga kecepatan tim kita hingga kecepatan - yang tampaknya adil bagi kita.
Jawaban:
Pendekatan yang disarankan profesor Anda paling baik diketik dengan ketat dan salah di hampir setiap level.
Kopling sebaiknya dikurangi dengan inversi ketergantungan , yang melakukannya dengan pengiriman polimorfik, daripada memasang kabel pada sejumlah kasing.
sumber
Profesor Anda melakukan kesalahan . Dia mencoba sepenuhnya memisahkan pandangan dan model dengan memaksa komunikasi untuk bepergian melalui string di kedua arah (tampilan tidak tergantung pada model dan model tidak tergantung pada tampilan) , yang benar-benar mengalahkan tujuan desain berorientasi objek dan MVC. Kedengarannya seperti bukannya menulis kelas dan merancang arsitektur berbasis OO, dia menulis modul berbeda yang hanya menanggapi pesan berbasis teks.
Agar lebih adil bagi profesor, ia mencoba membuat di Jawa apa yang tampak sangat mirip dengan antarmuka .NET yang disebut
INotifyPropertyChanged
, yang memberi tahu pelanggan tentang peristiwa perubahan dengan cara melewati string yang menentukan properti mana yang telah berubah. Dalam. NET setidaknya, antarmuka ini terutama digunakan untuk berkomunikasi dari model data untuk melihat objek dan elemen GUI (mengikat).Jika dilakukan dengan benar , mengambil pendekatan ini dapat memiliki beberapa manfaat¹:
events
tetapi di Jawa Anda harus membuat kelas atau objek dan menulis kode berlangganan / berhenti berlangganan untuk setiap acara.Jadi, singkatnya (dan untuk menjawab pertanyaan Anda), itu bisa dilakukan, tetapi pendekatan yang diambil profesor Anda adalah kesalahan karena tidak membiarkan setidaknya ketergantungan satu arah antara Tampilan dan Model. Hanya saja tidak praktis, terlalu akademis, dan bukan contoh yang baik tentang bagaimana menggunakan alat yang ada.
¹ Cari di Google untuk
INotifyPropertyChanged
menemukan sejuta cara yang ditemukan orang untuk mencoba menghindari penggunaan string sihir saat menerapkannya.sumber
enum
s (ataupublic static final String
s) harus digunakan sebagai pengganti String sihir.Profesor Anda tidak mengerti OO . Misalnya memiliki kelas Kendaraan konkret?
Dan agar kelas ini memahami cara membuat sepeda?
Kendaraan harus abstrak dan harus ada subkelas beton yang disebut Sepeda. Saya akan bermain sesuai aturannya untuk mendapatkan nilai bagus dan kemudian melupakan pengajarannya.
sumber
Saya pikir Anda memiliki poin bagus, string sihirnya buruk. Seseorang di tim saya harus men-debug masalah yang disebabkan oleh string sihir beberapa minggu yang lalu (tapi itu dalam kode mereka sendiri yang mereka tulis jadi saya tutup mulut). Dan itu terjadi ... di industri !!
Keuntungan dari pendekatannya adalah bahwa mungkin lebih cepat untuk kode, terutama untuk proyek demo kecil. Kerugiannya adalah bahwa ia cenderung untuk kesalahan ketik dan semakin sering string digunakan semakin besar kemungkinan kesalahan ketik. Dan jika Anda ingin mengubah string ajaib, string refactoring lebih sulit daripada variabel refactoring karena alat refactoring mungkin juga menyentuh string yang berisi string ajaib (sebagai substring) tetapi bukan dirinya sendiri string ajaib, dan tidak boleh disentuh. Juga, Anda mungkin perlu menyimpan kamus atau indeks string sihir agar pengembang baru tidak akan mulai menemukan string sihir baru untuk tujuan yang sama, dan tidak akan membuang waktu mencari string sihir yang ada.
Dalam konteks ini, sepertinya Enum mungkin lebih baik daripada string sihir atau bahkan konstanta string global. Juga, IDE akan sering memberi Anda semacam bantuan kode (lengkapi-otomatis, refactor, temukan-semua-referensi, dll ...) ketika Anda menggunakan string atau Enums yang konstan. IDE tidak akan menawarkan banyak bantuan jika Anda menggunakan string ajaib.
sumber
Menggunakan 'pengalaman industri' adalah argumen yang buruk. Profesor Anda perlu mengajukan argumen yang lebih baik dari itu :-).
Seperti yang telah dinyatakan orang lain, penggunaan String sihir tentu disukai, menggunakan enum dianggap jauh lebih aman. Enum memiliki makna dan ruang lingkup , string sihir tidak. Selain itu, cara di mana profesor Anda memisahkan masalah dianggap sebagai teknik yang lebih tua dan lebih rapuh daripada yang digunakan saat ini.
Saya melihat bahwa @backtodos telah membahas hal ini ketika saya menjawab ini, jadi saya hanya akan menambahkan pendapat saya bahwa menggunakan Inversion of Control (yang merupakan bentuk Ketergantungan Injeksi, Anda akan menjalankan kerangka Spring dalam industri sebelum terlalu lama. ..) dianggap sebagai cara yang lebih modern untuk menangani jenis decoupling ini.
sumber
Mari kita perjelas; ada pasti beberapa kopling di sana. Fakta bahwa ada topik yang dapat dilanggankan seperti itu merupakan titik penggabungan, sebagaimana juga sifat dari pesan yang lain (seperti "string tunggal"). Karena itu, pertanyaannya kemudian menjadi apakah kopling lebih besar bila dilakukan melalui string atau tipe. Jawabannya tergantung pada apakah Anda khawatir tentang kopling yang didistribusikan dari waktu ke waktu atau ruang: apakah pesan akan disimpan dalam file sebelum dibaca nanti, atau akan dikirim ke proses lain (terutama jika itu tidak ditulis dalam bahasa yang sama), menggunakan string dapat membuat segalanya lebih sederhana. Kelemahannya adalah tidak ada pemeriksaan tipe; kesalahan tidak akan terdeteksi sampai runtime (dan kadang-kadang bahkan tidak).
Strategi mitigasi / kompromi untuk Java bisa menggunakan antarmuka yang diketik, tetapi di mana antarmuka yang diketik itu dalam paket terpisah. Ini harus terdiri dari hanya Java
interface
dan tipe nilai dasar (mis., Enumerasi, pengecualian). Seharusnya tidak ada implementasi antarmuka dalam paket itu. Kemudian setiap orang menerapkan menentang itu dan, jika menyampaikan pesan dengan cara yang kompleks diperlukan, implementasi tertentu dari delegasi Java dapat menggunakan string ajaib yang diperlukan. Itu juga membuatnya lebih mudah untuk memigrasi kode ke lingkungan yang lebih profesional seperti JEE atau OSGi, dan sangat membantu hal-hal kecil seperti pengujian ...sumber
Apa yang profesor Anda usulkan adalah penggunaan "string sihir". Sementara itu memang "longgar pasangan" antara satu sama lain, memungkinkan untuk perubahan yang lebih mudah, itu adalah anti-pola; string harus sangat, SANGAT jarang digunakan untuk berisi atau mengontrol instruksi kode, dan ketika benar-benar harus terjadi, nilai string yang Anda gunakan untuk mengendalikan logika harus ditentukan secara terpusat dan terus-menerus sehingga ada SATU otoritas pada nilai yang diharapkan dari string tertentu.
Alasan mengapa sangat sederhana; string tidak diperiksa kompiler untuk sintaksis atau konsistensi dengan nilai-nilai lain (paling baik, mereka diperiksa untuk form yang tepat mengenai karakter escape dan pemformatan khusus bahasa lainnya dalam string). Anda dapat meletakkan apa pun yang Anda inginkan dalam sebuah string. Dengan demikian, Anda bisa mendapatkan algoritma / program yang rusak putus asa untuk dikompilasi, dan itu tidak sampai berjalan bahwa kesalahan terjadi. Pertimbangkan kode berikut (C #):
... semua kode ini dikompilasi, percobaan pertama, tetapi kesalahannya jelas dengan tampilan kedua. Ada banyak contoh pemrograman jenis ini, dan mereka semua tunduk pada kesalahan semacam ini, BAHKAN JIKA Anda mendefinisikan string sebagai konstanta (karena konstanta dalam. NET ditulis untuk manifes setiap perpustakaan di mana mereka digunakan, yang harus maka semua akan dikompilasi ulang ketika nilai yang didefinisikan diubah agar nilai tersebut berubah "secara global"). Karena kesalahan tidak ditangkap pada waktu kompilasi, itu harus ditangkap selama pengujian run-time, dan itu hanya dijamin dengan cakupan kode 100% dalam pengujian unit dengan latihan kode yang memadai, yang biasanya hanya ditemukan pada kegagalan-aman yang paling absolut. , sistem waktu nyata.
sumber
Sebenarnya, kelas-kelas itu masih sangat erat. Kecuali sekarang mereka digabungkan sedemikian rupa sehingga kompiler tidak dapat memberi tahu Anda ketika ada masalah!
Jika seseorang mengubah "BicycleMake" menjadi "BicyclesMake" maka tidak ada yang akan mengetahui bahwa semuanya rusak sampai runtime.
Kesalahan runtime jauh lebih mahal untuk diperbaiki daripada kompilasi kesalahan waktu - ini semua jenis kejahatan.
sumber