Saya menemukan entri blog yang mengecilkan penggunaan Strings di Java untuk membuat kode Anda kurang semantik, menyarankan bahwa Anda harus menggunakan kelas bungkus tipis sebagai gantinya. Ini adalah contoh sebelum dan sesudah entri yang disediakan untuk menggambarkan masalah:
public void bookTicket(
String name,
String firstName,
String film,
int count,
String cinema);
public void bookTicket(
Name name,
FirstName firstName,
Film film,
Count count,
Cinema cinema);
Dalam pengalaman saya membaca blog pemrograman saya sampai pada kesimpulan bahwa 90% adalah omong kosong, tapi saya bertanya-tanya apakah ini poin yang valid. Entah bagaimana rasanya tidak benar bagi saya, tetapi saya tidak bisa menunjukkan dengan tepat apa yang salah dengan gaya pemrograman.
Jawaban:
Enkapsulasi ada untuk melindungi program Anda dari perubahan . Apakah representasi Nama akan berubah? Jika tidak, maka Anda membuang-buang waktu dan YAGNI berlaku.
Sunting: Saya sudah membaca posting blog dan dia punya ide bagus secara fundamental. Masalahnya adalah dia terlalu jauh. Sesuatu seperti
String orderId
itu benar - benar buruk, karena mungkin"!"£$%^&*())ADAFVF
itu tidak validorderId
. Ini berarti bahwaString
mewakili nilai yang jauh lebih mungkin daripada yang adaorderId
s. Namun, untuk sesuatu sepertiname
, maka Anda tidak dapat memperkirakan nama yang valid atau tidak, dan adaString
yang validname
.Pada contoh pertama, Anda (benar) mengurangi input yang mungkin menjadi input yang valid saja. Dalam contoh kedua, Anda tidak mencapai penyempitan input yang valid.
Edit lagi: Pertimbangkan kasus input yang tidak valid. Jika Anda menulis "Gareth Gobulcoque" sebagai nama Anda, itu akan terlihat konyol, itu tidak akan menjadi akhir dari dunia. Jika Anda memasukkan OrderID yang tidak valid, kemungkinan besar itu tidak akan berfungsi.
sumber
Name
, Anda tidak dapat secara tidak sengaja melewatkan nilai String yang tidak terkait. Di mana Anda mengharapkanName
, hanyaName
akan mengkompilasi, dan String "Saya berutang $ 5" tidak dapat diterima secara tidak sengaja. (Catat ini tidak terkait dengan validasi nama apa pun!)Itu hanya gila :)
sumber
var p = new Point(x: 10, y:20);
Juga, tidak seperti Bioskop yang berbeda dari string. Saya akan mengerti jika seseorang berurusan dengan kuantitas fisik, seperti tekanan, suhu, energi, di mana unit berbeda dan beberapa tidak bisa negatif. Penulis blog perlu mencoba fungsional.Saya setuju dengan penulis, kebanyakan. Jika ada setiap perilaku aneh ke lapangan, seperti validasi dari perintah id, maka saya akan membuat kelas untuk mewakili jenis itu. Poin keduanya bahkan lebih penting: jika Anda memiliki seperangkat bidang yang mewakili beberapa konsep seperti alamat, buat kelas untuk konsep itu. Jika Anda memprogram di Jawa, Anda harus membayar mahal untuk pengetikan statis. Anda mungkin juga mendapatkan semua nilai yang Anda bisa.
sumber
Jangan lakukan itu; itu akan terlalu rumit dan Anda tidak akan membutuhkannya
... adalah jawaban yang saya tulis di sini 2 tahun yang lalu. Sekarang, saya tidak begitu yakin; sebenarnya, dalam beberapa bulan terakhir saya mulai memigrasikan kode lama ke format ini, bukan karena saya tidak punya yang lebih baik untuk dilakukan tetapi karena saya benar-benar membutuhkannya untuk mengimplementasikan fitur baru atau mengubah yang sudah ada. Saya mengerti keengganan otomatis yang orang lain di sini telah melihat kode itu, tapi saya pikir ini adalah sesuatu yang pantas dipikirkan.
Manfaat
Manfaat utama adalah kemampuan untuk memodifikasi dan memperluas kode. Jika Anda menggunakan
daripada hanya melewati beberapa bilangan bulat di sekitar - yang merupakan sesuatu yang, sayangnya, banyak antarmuka lakukan - maka jauh lebih mudah untuk kemudian menambahkan dimensi lain. Atau ubah tipenya menjadi
double
. Jika Anda menggunakanList<Author> authors
atauList<Person> authors
alih-alihList<String> authors
nanti menjadi lebih mudah untuk menambahkan lebih banyak informasi ke apa yang penulis wakili. Menulisnya seperti ini rasanya seperti saya menyatakan yang jelas, tetapi dalam praktiknya saya telah bersalah menggunakan string dengan cara ini berkali-kali sendiri, terutama dalam kasus di mana itu tidak jelas pada awalnya maka saya akan membutuhkan lebih dari Sebuah benang.Saat ini saya sedang mencoba untuk memperbaiki daftar string yang saling terkait di seluruh kode saya karena saya memerlukan lebih banyak informasi di sana, dan saya merasakan sakitnya: \
Di luar itu, saya setuju dengan penulis blog bahwa itu membawa lebih banyak informasi semantik , sehingga memudahkan pembaca untuk mengerti. Sementara parameter sering diberi nama yang bermakna dan mendapatkan jalur dokumentasi khusus, ini sering tidak terjadi dengan bidang atau penduduk setempat.
Manfaat akhirnya adalah keamanan jenis , untuk alasan yang jelas, tetapi di mata saya itu adalah hal kecil di sini.
Kekurangannya
Butuh waktu lebih lama untuk menulis . Menulis kelas kecil cepat dan mudah tetapi tidak mudah, terutama jika Anda membutuhkan banyak kelas ini. Jika Anda mendapati diri Anda berhenti setiap 3 menit untuk menulis beberapa kelas pembungkus baru, itu juga dapat merusak konsentrasi Anda. Saya ingin berpikir, bagaimanapun, bahwa upaya ini biasanya hanya akan terjadi pada tahap pertama dari penulisan kode apa pun; Saya biasanya bisa mendapatkan ide yang cukup bagus dengan cepat tentang entitas apa yang perlu dilibatkan.
Ini bisa melibatkan banyak setter redundan (atau konstruksi) dan pengambil . Penulis blog memberikan contoh yang benar-benar jelek dari
new Point(x(10), y(10))
bukannew Point(10, 10)
, dan saya ingin menambahkan bahwa penggunaan juga mungkin melibatkan hal-hal sepertiMath.max(p.x.get(), p.y.get())
bukanMath.max(p.x, p.y)
. Dan kode panjang sering dianggap lebih sulit untuk dibaca, dan memang begitu. Tetapi dalam semua kejujuran, saya punya perasaan banyak kode bergerak objek di sekitar, dan hanya metode tertentu yang membuatnya, dan bahkan lebih sedikit membutuhkan akses ke rincian berpasir nya (yang bukan OOPy toh).Belum pasti
Saya akan mengatakan apakah ini membantu keterbacaan kode masih bisa diperdebatkan. Ya, lebih banyak informasi semantik, tetapi kode lebih panjang. Ya, lebih mudah untuk memahami peran masing-masing lokal, tetapi lebih sulit untuk memahami apa yang dapat Anda lakukan dengannya kecuali Anda pergi dan membaca dokumentasinya.
Seperti sebagian besar sekolah pemikiran lain, saya pikir tidak sehat untuk mengambil yang satu ini secara ekstrem. Saya tidak melihat diri saya pernah memisahkan koordinat x dan y untuk masing-masing dari tipe yang berbeda. Saya pikir
Count
itu tidak perlu ketikaint
harus mencukupi. Saya tidak sukaunsigned int
penggunaan dalam C - sementara secara teori bagus, itu tidak memberi Anda informasi yang cukup, dan tidak melarang memperluas kode Anda nanti untuk mendukung -1 ajaib itu. Terkadang Anda memang membutuhkan kesederhanaan.Saya pikir posting blog itu sedikit di sisi ekstrim. Tetapi secara keseluruhan, saya telah belajar dari pengalaman yang menyakitkan bahwa ide dasar di baliknya dibuat dari hal-hal yang benar.
Saya tidak menyukai kode over-engineered. Saya benar-benar melakukannya. Tetapi digunakan dengan benar, saya tidak berpikir ini over-engineering.
sumber
Meskipun agak berlebihan, saya sering berpikir sebagian besar barang yang saya lihat kurang direkayasa.
Ini bukan hanya "Keamanan", Salah satu hal yang sangat baik tentang Java adalah bahwa hal itu banyak membantu Anda dengan mengingat / mencari tahu apa yang perlu / diharapkan metode panggilan perpustakaan apa pun.
Perpustakaan Java TERBURUK (sejauh ini) yang pernah saya kerjakan ditulis oleh seseorang yang sangat menyukai Smalltalk dan memodelkan perpustakaan GUI setelah itu untuk membuatnya bertindak lebih seperti smalltalk - masalahnya adalah setiap metode mengambil objek dasar yang sama, tetapi sebenarnya tidak bisa MENGGUNAKAN segala sesuatu yang objek dasar bisa dilemparkan, jadi Anda kembali menebak apa yang harus dilewatkan ke dalam metode dan tidak tahu jika Anda telah gagal sampai runtime (Sesuatu yang saya harus berurusan dengan setiap saat ketika saya sedang bekerja di C).
Masalah lain - Jika Anda menyebarkan string, int, koleksi, dan array tanpa objek, yang Anda miliki hanyalah bola data tanpa makna. Ini tampak alami ketika Anda berpikir dalam hal perpustakaan bahwa "beberapa aplikasi" akan digunakan, tetapi ketika merancang seluruh aplikasi itu jauh lebih membantu untuk menetapkan makna (kode) untuk semua data Anda di tempat di mana data didefinisikan dan hanya berpikir dalam dalam hal bagaimana objek tingkat tinggi ini berinteraksi. Jika Anda melewati primitif alih-alih objek maka Anda - menurut definisi - mengubah data di tempat yang berbeda dari yang ditentukan (Ini juga mengapa saya benar-benar tidak suka Setters dan Getters - konsep yang sama, Anda beroperasi pada data yang bukan milik Anda).
Akhirnya, jika Anda mendefinisikan objek yang terpisah untuk semuanya, Anda selalu memiliki tempat yang bagus untuk memvalidasi semuanya - misalnya jika Anda membuat objek untuk kode pos dan kemudian menemukan bahwa Anda harus memastikan bahwa kode pos selalu menyertakan ekstensi 4 digit, Anda memiliki tempat sempurna untuk mengatakannya.
Sebenarnya itu bukan ide yang buruk. Memikirkan hal itu, saya bahkan tidak yakin saya akan mengatakan itu over-engineered sama sekali, hanya saja lebih mudah untuk dikerjakan dalam hampir segala hal - satu-satunya pengecualian adalah menjamurnya kelas-kelas kecil tetapi kelas-kelas Java sangat ringan dan mudah untuk menulis bahwa ini bahkan bukan biaya (mereka bahkan dapat dihasilkan).
Saya akan sangat tertarik untuk melihat proyek java yang ditulis dengan baik yang sebenarnya memiliki terlalu banyak kelas yang didefinisikan (Di mana hal itu membuat program lebih sulit), saya mulai berpikir bahwa tidak mungkin memiliki terlalu banyak kelas.
sumber
Saya pikir Anda harus melihat konsep ini dari titik awal yang lain. Lihatlah dari sudut pandang seorang perancang basis data: jenis-jenis yang dilewatkan dalam contoh pertama tidak mendefinisikan parameter Anda dengan cara yang unik, apalagi cara yang bermanfaat.
Dua parameter diperlukan untuk menentukan pelindung aktual yang memesan tiket, Anda mungkin memiliki dua film berbeda dengan nama yang identik (misalnya remake), Anda mungkin memiliki film yang sama dengan nama yang berbeda (misalnya terjemahan). Rantai bioskop tertentu mungkin memiliki kantor cabang yang berbeda, jadi bagaimana Anda akan mengatasinya dalam string dan dengan cara yang konsisten (mis. Anda menggunakan
$chain ($city)
atau$chain in $city
atau bahkan sesuatu yang lain dan bagaimana Anda akan memastikan bahwa ini adalah digunakan secara konsisten. Yang terburuk sebenarnya adalah menentukan patron Anda melalui dua parameter, fakta bahwa nama depan dan nama keluarga diberikan tidak menjamin pelanggan yang valid (dan Anda tidak dapat membedakan duaJohn Doe
s).Jawabannya adalah mendeklarasikan tipe, tetapi ini akan jarang menjadi pembungkus tipis seperti yang saya tunjukkan di atas. Kemungkinan besar, mereka akan berfungsi sebagai penyimpanan data Anda atau digabungkan dengan beberapa jenis database. Jadi suatu
Cinema
objek kemungkinan akan memiliki nama, lokasi, ... dan dengan cara itu Anda menghilangkan ambiguitas tersebut. Jika mereka pembungkus tipis, mereka kebetulan.Jadi, IMHO posting blog hanya mengatakan "pastikan Anda melewati jenis yang benar", penulisnya hanya membuat pilihan yang terlalu dibatasi untuk memilih tipe data dasar khususnya (yang merupakan pesan yang salah).
Alternatif yang diusulkan lebih baik:
Di sisi lain, saya pikir posting blog terlalu jauh dengan membungkus semuanya.
Count
terlalu umum, saya dapat menghitung apel atau jeruk dengan itu, menambahkannya dan masih memiliki situasi di tangan saya di mana sistem tipe memungkinkan saya untuk melakukan operasi yang tidak masuk akal. Anda tentu saja dapat menerapkan logika yang sama seperti di blog dan menentukan jenisCountOfOranges
dll, tetapi itu juga konyol.Untuk apa nilainya, saya benar-benar menulis sesuatu seperti
Singkat cerita: Anda tidak boleh melewati variabel tidak masuk akal; satu-satunya saat Anda benar-benar menentukan objek dengan nilai yang tidak menentukan objek yang sebenarnya, adalah ketika Anda menjalankan kueri (misalnya
public Collection<Film> findFilmsWithTitle(String title)
) atau ketika Anda menyusun bukti konsep. Usahakan sistem tipe Anda bersih, jadi jangan gunakan tipe yang terlalu umum (misalnya film yang diwakili oleh aString
) atau terlalu membatasi / spesifik / dibuat-buat (misalnyaCount
alih-alihint
). Gunakan jenis yang mendefinisikan objek Anda secara unik dan tidak ambigu jika memungkinkan dan layak.sunting : ringkasan yang bahkan lebih pendek. Untuk aplikasi kecil (misalnya bukti konsep): mengapa repot dengan desain yang rumit? Cukup gunakan
String
atauint
terus saja.Untuk aplikasi besar: apakah benar bahwa Anda memiliki banyak kelas yang terdiri dari satu bidang dengan tipe data dasar? Jika Anda memiliki sedikit kelas seperti itu, Anda hanya memiliki objek "normal", tidak ada yang istimewa terjadi di sana.
Saya merasakan ide merangkum string, ... hanyalah sebuah desain yang tidak lengkap: terlalu rumit untuk aplikasi kecil, tidak cukup lengkap untuk aplikasi besar.
sumber
Bagi saya melakukan ini sama dengan menggunakan wilayah di C #. Umumnya jika Anda merasa ini diperlukan untuk membuat kode Anda dapat dibaca maka Anda memiliki masalah yang lebih besar Anda harus menghabiskan waktu Anda.
sumber
Saya akan mengatakan itu adalah ide yang sangat bagus dalam bahasa dengan fitur seperti typedef sangat diketik.
Di Jawa Anda tidak memiliki ini sehingga menciptakan seluruh kelas baru untuk hal-hal ini berarti biaya mungkin lebih besar daripada manfaatnya. Anda juga bisa mendapatkan 80% dari manfaat dengan berhati-hati tentang penamaan variabel / parameter Anda.
sumber
Akan lebih baik, JIKA String (end Integer, dan ... berbicara hanya tentang String) belum final, sehingga kelas-kelas ini bisa MENJADI beberapa (dibatasi) String dengan makna dan masih dapat dikirim ke beberapa objek independen yang tahu bagaimana menangani tipe dasar (tanpa berbicara bolak-balik).
Dan "selamat tinggal" dari itu meningkat ketika ada misalnya. pembatasan semua nama.
Tetapi ketika membuat beberapa aplikasi (bukan perpustakaan), selalu memungkinkan untuk memperbaikinya. Jadi saya lebih suka memulai tanpa itu.
sumber
Sebagai contoh: dalam sistem yang kami kembangkan saat ini, ada banyak entitas berbeda yang dapat diidentifikasi oleh berbagai jenis pengidentifikasi (karena penggunaan sistem eksternal), kadang-kadang bahkan jenis entitas yang sama. Semua pengidentifikasi adalah Strings - jadi jika seseorang mencampur jenis id mana yang harus dilewatkan sebagai parameter, tidak ada kesalahan waktu kompilasi yang ditampilkan, tetapi program akan meledak saat runtime. Ini sering terjadi. Jadi saya harus mengatakan bahwa tujuan utama prinsip ini bukan untuk melindungi terhadap perubahan (walaupun juga berfungsi untuk perubahan), tetapi untuk melindungi diri dari bug. Lagi pula, jika seseorang mendesain API, itu harus mencerminkan konsep domain, sehingga secara konsep berguna untuk mendefinisikan kelas domain-spesifik - semuanya tergantung pada apakah ada keteraturan dalam pikiran pengembang,
sumber