Saya penggemar berat tipe statis memeriksa. Ini mencegah Anda membuat kesalahan bodoh seperti ini:
// java code
Adult a = new Adult();
a.setAge("Roger"); //static type checker would complain
a.setName(42); //and here too
Tapi itu tidak mencegah Anda melakukan kesalahan bodoh seperti ini:
Adult a = new Adult();
// obviously you've mixed up these fields, but type checker won't complain
a.setAge(150); // nobody's ever lived this old
a.setWeight(42); // a 42lb adult would have serious health issues
Masalahnya muncul ketika Anda menggunakan jenis yang sama untuk mewakili jenis informasi yang jelas berbeda. Saya sedang berpikir solusi yang baik untuk ini akan memperluas Integer
kelas, hanya untuk mencegah kesalahan logika bisnis, tetapi tidak menambah fungsionalitas. Sebagai contoh:
class Age extends Integer{};
class Pounds extends Integer{};
class Adult{
...
public void setAge(Age age){..}
public void setWeight(Pounds pounds){...}
}
Adult a = new Adult();
a.setAge(new Age(42));
a.setWeight(new Pounds(150));
Apakah ini dianggap praktik yang baik? Atau ada masalah teknik yang tidak terduga di jalan dengan desain yang ketat?
a.SetAge( new Age(150) )
Masih tidak mau mengkompilasi?new Age(...)
objek, Anda tidak dapat menetapkannya secara salah ke variabel tipeWeight
di tempat lain. Ini mengurangi jumlah tempat di mana kesalahan bisa terjadi.Jawaban:
Anda pada dasarnya meminta sistem unit (tidak, bukan tes unit, "unit" seperti dalam "unit fisik", seperti meter, volt, dll.).
Dalam kode Anda
Age
mewakili waktu danPounds
mewakili massa. Ini mengarah ke hal-hal seperti konversi unit, unit dasar, presisi, dll.Ada upaya untuk memasukkan hal semacam itu ke Jawa, misalnya:
Dua yang terakhir tampaknya hidup dalam hal github ini: https://github.com/unitsofmeasurement
C ++ memiliki unit melalui Boost
LabView hadir dengan banyak unit .
Ada contoh lain dalam bahasa lain. (suntingan dipersilakan)
Seperti yang Anda lihat di atas, semakin besar kemungkinan bahasa digunakan untuk menangani nilai dengan unit, semakin asli mendukung unit. LabView sering digunakan untuk berinteraksi dengan perangkat pengukuran. Karena itu masuk akal untuk memiliki fitur seperti itu dalam bahasa dan menggunakannya tentu akan dianggap sebagai praktik yang baik.
Tetapi dalam bahasa tingkat tinggi tujuan umum apa pun, di mana permintaan rendah untuk jumlah keras seperti itu, itu mungkin tidak terduga.
Dugaan saya adalah: kinerja / memori. Jika Anda berurusan dengan banyak nilai, overhead objek per nilai mungkin menjadi masalah. Tapi seperti biasa: Optimalisasi prematur adalah akar dari semua kejahatan .
Saya pikir "masalah" yang lebih besar membuat orang terbiasa, karena unit biasanya didefinisikan secara implisit seperti:
Orang-orang akan bingung ketika mereka harus melewati objek sebagai nilai untuk sesuatu yang tampaknya dapat digambarkan dengan sederhana
int
, ketika mereka tidak terbiasa dengan sistem unit.sumber
int
..." --- yang mana kita memiliki Principal of Least Surprise sebagai panduan di sini. Tangkapan yang bagus.Berbeda dengan jawaban nol, mendefinisikan tipe untuk "unit" bisa bermanfaat jika bilangan bulat tidak cukup untuk menggambarkan pengukuran. Misalnya, berat badan sering diukur dalam beberapa unit dalam sistem pengukuran yang sama. Pikirkan "pound" dan "ons" atau "kilogram" dan "gram".
Jika Anda membutuhkan tingkat pengukuran yang lebih terperinci, menentukan jenis untuk unit ini bermanfaat:
Untuk sesuatu seperti "usia", saya sarankan untuk menghitungnya pada waktu berjalan berdasarkan tanggal lahir orang tersebut:
sumber
Apa yang tampaknya Anda cari dikenal sebagai tipe yang ditandai . Mereka adalah cara untuk mengatakan "ini adalah bilangan bulat yang mewakili usia" sementara "ini juga bilangan bulat tetapi merupakan bobot" dan "Anda tidak dapat menetapkan satu ke yang lain". Perhatikan, bahwa ini lebih jauh daripada unit fisik seperti meter atau kilogram: Saya mungkin punya dalam program saya "ketinggian orang" dan "jarak antara titik-titik di peta", keduanya diukur dalam meter, tetapi tidak kompatibel satu sama lain karena menetapkan satu ke yang lain tidak masuk akal dari perspektif logika bisnis.
Beberapa bahasa, seperti jenis dukungan Tag Scala cukup mudah (lihat tautan di atas). Di tempat lain, Anda bisa membuat kelas pembungkus sendiri, tetapi ini kurang nyaman.
Validasi, misalnya memeriksa bahwa tinggi badan seseorang "masuk akal" adalah masalah lain. Anda dapat memasukkan kode tersebut di
Adult
kelas Anda (konstruktor atau setter), atau di dalam kelas tipe / pembungkus yang ditandai. Di satu sisi, kelas bawaan sepertiURL
atauUUID
memenuhi peran seperti itu (antara lain, misalnya menyediakan metode utilitas).Apakah menggunakan jenis yang ditandai atau kelas pembungkus benar-benar akan membantu membuat kode Anda lebih baik, akan tergantung pada beberapa faktor. Jika objek Anda sederhana dan memiliki beberapa bidang, risiko menetapkannya salah rendah dan kode tambahan yang diperlukan untuk menggunakan jenis yang ditandai mungkin tidak sepadan dengan usaha. Dalam sistem yang kompleks dengan struktur kompleks dan banyak bidang (terutama jika banyak dari mereka memiliki tipe primitif yang sama), sebenarnya dapat membantu.
Dalam kode yang saya tulis, saya sering membuat kelas wrapper jika saya membagikan peta. Jenis seperti
Map<String, String>
itu sangat buram sendiri, jadi membungkusnya di kelas dengan nama yang bermakna sepertiNameToAddress
banyak membantu. Tentu saja, dengan jenis yang ditandai, Anda dapat menulisMap<Name, Address>
dan tidak perlu pembungkus untuk seluruh peta.Namun, untuk tipe sederhana seperti Strings atau Integer, saya menemukan kelas wrapper (di Jawa) terlalu merepotkan. Logika bisnis reguler tidak terlalu buruk, tetapi timbul sejumlah masalah dengan membuat serialisasi tipe-tipe ini ke JSON, memetakannya ke objek DB, dll. Anda dapat menulis pemetaan dan pengait untuk semua kerangka kerja besar (mis. Data Jackson dan Spring), tetapi kerja ekstra dan pemeliharaan terkait dengan kode ini akan mengimbangi apa pun yang Anda peroleh dari menggunakan pembungkus ini. Tentu saja, YMMV dan di sistem lain, keseimbangannya mungkin berbeda.
sumber