
Jika Anda kadang-kadang bertanya pada diri sendiri pertanyaan: "apakah semuanya baik untuk saya dalam metode ini?" Dan pilih antara "bagaimana jika itu meledak" dan "lebih baik untuk memeriksa untuk berjaga-jaga", maka selamat datang di ...
Koreksi: Seperti
dicatat lorc dan
0xd34df00d , apa yang dibahas di bawah ini disebut tipe dependen. Anda dapat membacanya di
sini . Nah, di bawah ini adalah sumber teks dengan pemikiran saya tentang ini.
Selama pengembangan, sering ada kebutuhan untuk memverifikasi validitas data untuk beberapa algoritma. Secara formal, ini dapat digambarkan sebagai berikut: misalkan kita mendapatkan beberapa struktur data, periksa nilainya terhadap rentang nilai yang diizinkan (ODZ) tertentu, dan meneruskannya. Selanjutnya, struktur data yang sama dapat dikenakan verifikasi yang sama. Jika struktur tetap tidak berubah, memeriksa ulang validitasnya jelas merupakan tindakan yang tidak perlu.
Meskipun validasi bisa sangat lama, masalahnya bukan hanya dalam kinerja. Jauh lebih tidak menyenangkan adalah tanggung jawab ekstra. Pengembang tidak yakin apakah perlu memeriksa struktur untuk validitas lagi. Selain verifikasi yang tidak perlu, sebaliknya, kita dapat mengasumsikan tidak adanya verifikasi, dengan salah mengasumsikan bahwa struktur telah diverifikasi sebelumnya.
Dengan demikian, kegagalan fungsi diperbolehkan dalam metode yang mengharapkan struktur terbukti dan tidak bekerja dengan benar dengan struktur yang nilainya di luar kisaran tertentu dari nilai yang dapat diterima.
Di situlah letak masalah yang lebih dalam yang tidak terlihat. Bahkan, struktur data yang valid adalah subtipe dari struktur asli. Dari sudut pandang ini, masalah dengan metode yang hanya menerima objek yang valid setara dengan kode berikut dalam bahasa fiksi:
class Parent { ... } class Child : Parent { ... } ... void processValidObject(Parent parent) { if (parent is Child) {
Setuju bahwa sekarang masalahnya jauh lebih jelas. Di depan kita adalah pelanggaran kanonik dari prinsip substitusi Liskov. Baca mengapa melanggar prinsip substitusi itu buruk, misalnya, di
sini .
Masalah mentransfer objek yang tidak valid dapat diselesaikan dengan membuat subtipe untuk struktur data asli. Misalnya, Anda dapat membuat objek melalui pabrik yang mengembalikan objek subtipe yang valid atau nol sesuai dengan struktur asli. Jika kita mengubah tanda tangan metode yang mengharapkan struktur yang valid sehingga mereka hanya menerima subtipe, maka masalahnya akan hilang. Selain keyakinan bahwa sistem bekerja dengan tepat, jumlah validasi per sentimeter persegi kode akan berkurang. Kelebihan lainnya adalah bahwa dengan tindakan seperti itu kami mengalihkan tanggung jawab untuk memvalidasi data dari pengembang ke kompiler.
Di Swift, pada level sintaks, masalah memeriksa null diselesaikan. Idenya adalah untuk memisahkan tipe menjadi tipe nullable dan non-nullable. Pada saat yang sama, itu dibuat dalam bentuk gula sedemikian rupa sehingga programmer tidak perlu mendeklarasikan jenis baru. Ketika mendeklarasikan tipe variabel, ClassName menjamin bahwa variabel tersebut bukan nol, dan ketika mendeklarasikan ClassName? variabelnya nol. Pada saat yang sama, kovarians ada di antara tipe, yaitu, Anda dapat meneruskan objek tipe ClassName ke metode yang menerima ClassName?
Ide ini dapat diperluas ke DLD yang ditentukan pengguna. Memberikan objek dengan metadata yang mengandung DLD yang disimpan dalam tipe akan menghilangkan masalah yang dijelaskan di atas. Akan menyenangkan untuk mendapatkan dukungan untuk alat semacam itu dalam bahasa, tetapi perilaku ini juga diimplementasikan dalam bahasa OO "biasa", seperti Java atau C #, menggunakan warisan dan pabrik.
Situasi dengan validasi data adalah konfirmasi lain bahwa entitas dalam OOP tidak diambil dari dunia nyata, tetapi dari kebutuhan teknik.
UPD: Sebagaimana dicatat dengan benar dalam komentar, ada baiknya membuat subtipe hanya jika kita mendapatkan keandalan tambahan dan mengurangi jumlah validasi identik.
Juga, artikel tersebut tidak memiliki contoh. Biarkan beberapa jalur file datang kepada kami di pintu masuk. Sistem kami dalam beberapa kasus berfungsi dengan semua file, dan dalam beberapa kasus hanya dengan file yang dapat kami akses. Selanjutnya, kami ingin mentransfernya ke berbagai subsistem, yang juga berfungsi dengan file yang dapat diakses dan tidak dapat diakses. Lebih lanjut, subsistem ini mentransfer file lebih jauh, di mana lagi tidak jelas apakah file tersebut tersedia atau tidak. Dengan demikian, di setiap tempat yang meragukan, pemeriksaan akses akan muncul atau mungkin dilupakan sebaliknya. Karena itu, sistem akan menjadi lebih rumit karena ambiguitas dan pemeriksaan yang meluas. Tetapi pemeriksaan ini memuat disk dan umumnya berat. Anda dapat menembolok cek ini di bidang boolean, tetapi ini tidak akan menyelamatkan kami dari kenyataan akan perlunya verifikasi. Saya sarankan mengalihkan tanggung jawab untuk memeriksa dari pengembang ke kompiler.