Beberapa perspektif gambar besar untuk ditambahkan ke jawaban lain yang bermanfaat namun lebih detail-sentris:
Di Swift, tanda seru muncul dalam beberapa konteks:
- Membuka paksa:
let name = nameLabel!.text
- Opsinya terbuka secara implisit:
var logo: UIImageView!
- Pengecoran paksa:
logo.image = thing as! UIImage
- Pengecualian yang tidak ditangani:
try! NSJSONSerialization.JSONObjectWithData(data, [])
Semua ini adalah konstruksi bahasa yang berbeda dengan makna yang berbeda, tetapi mereka semua memiliki tiga hal penting yang sama:
1. Poin seru menghindari pemeriksaan keamanan waktu kompilasi Swift.
Ketika Anda menggunakan !
di Swift, Anda pada dasarnya mengatakan, "Hei, kompiler, saya tahu Anda pikir kesalahan bisa terjadi di sini, tapi saya tahu dengan pasti bahwa itu tidak akan pernah terjadi."
Tidak semua kode yang valid cocok dengan kotak sistem tipe waktu kompilasi Swift - atau pemeriksaan tipe statis bahasa apa pun , dalam hal ini. Ada beberapa situasi di mana Anda dapat secara logis membuktikan bahwa kesalahan tidak akan pernah terjadi, tetapi Anda tidak dapat membuktikannya ke kompiler . Karena itulah para perancang Swift menambahkan fitur-fitur ini sejak awal.
Namun, kapan pun Anda menggunakannya !
, Anda mengesampingkan memiliki jalur pemulihan untuk kesalahan, yang berarti bahwa ...
2. Poin seru adalah potensi gangguan.
Tanda seru juga mengatakan, “Hei Swift, saya sangat yakin bahwa kesalahan ini tidak pernah terjadi sehingga lebih baik bagi Anda untuk menabrak seluruh aplikasi saya daripada bagi saya untuk membuat kode jalur pemulihan untuk itu."
Itu pernyataan berbahaya. Itu bisa menjadi yang benar: dalam kode mission-critical di mana Anda telah berpikir keras tentang invarian kode Anda, mungkin output palsu lebih buruk daripada crash.
Namun, ketika saya melihat !
di alam liar, jarang digunakan dengan penuh kesadaran. Sebagai gantinya, itu sering berarti, "nilai ini opsional dan saya tidak benar-benar berpikir terlalu keras tentang mengapa bisa nol atau bagaimana menangani dengan baik situasi itu, tetapi menambahkan !
membuatnya mengkompilasi ... jadi kode saya sudah benar, kan?"
Waspadalah terhadap kesombongan titik seru. Sebagai gantinya…
3. Poin seru paling baik digunakan dengan hemat.
Setiap !
konstruksi ini memiliki ?
rekanan yang memaksa Anda untuk menangani kasus kesalahan / nol:
- Membuka bungkus bersyarat:
if let name = nameLabel?.text { ... }
- Opsional:
var logo: UIImageView?
- Gips bersyarat:
logo.image = thing as? UIImage
- Pengecualian nol kegagalan:
try? NSJSONSerialization.JSONObjectWithData(data, [])
Jika Anda tergoda untuk menggunakannya !
, selalu baik untuk mempertimbangkan dengan hati-hati mengapa Anda tidak menggunakannya ?
. Apakah crash program Anda benar-benar pilihan terbaik jika !
operasi gagal? Mengapa nilai itu opsional / tersedia?
Apakah ada jalur pemulihan yang masuk akal yang bisa diambil kode Anda dalam kasus nil / error? Jika demikian, kode itu.
Jika tidak mungkin nol, jika kesalahan tidak pernah terjadi, maka adakah cara yang masuk akal untuk mengolah logika Anda sehingga kompiler tahu itu? Jika demikian, lakukanlah; kode Anda akan lebih rentan terhadap kesalahan.
Ada saat-saat ketika tidak ada cara yang masuk akal untuk menangani kesalahan, dan mengabaikan kesalahan - dan dengan demikian melanjutkan dengan data yang salah - akan lebih buruk daripada menabrak. Itulah saat-saat untuk menggunakan kekuatan membuka bungkus.
Saya secara berkala mencari seluruh basis kode saya !
dan mengaudit setiap penggunaannya. Sangat sedikit penggunaan yang digunakan untuk pengawasan. (Pada tulisan ini, seluruh kerangka Siesta memiliki tepat dua contohnya .)
Itu tidak berarti Anda tidak boleh menggunakan !
kode Anda - hanya saja Anda harus menggunakannya dengan penuh perhatian , dan jangan pernah menjadikannya pilihan default.